A clean, secure, and environment-aware PostgreSQL + pgAdmin stack using Docker Compose, ready for development, testing, and production. It includes strong secrets management, health checks, and environment-specific overrides that make it simple to run safely in all stages.
pgstack-docker/
│
├── docker-compose.yml # Base configuration (shared across all stages)
├── docker-compose.dev.yml # Development override (pgAdmin + ports)
├── docker-compose.test.yml # Test override (ephemeral, CI-friendly)
├── docker-compose.prod.yml # Production override (hardened, no ports)
│
├── .env # Default environment variables (local/dev)
├── .env.prod # Environment variables for production
│
├── secrets/
│ ├── postgres_password.txt # Postgres password (Docker secret)
│ └── pgadmin_password.txt # pgAdmin password (Docker secret)
│
└── README.md # You're reading it 🙂
| Service | Description |
|---|---|
| db | PostgreSQL 18 container with persistent data volume (db_data) and health checks. |
| pgadmin | pgAdmin 4 (web UI for PostgreSQL), enabled only in development mode. |
| Profile | Description | pgAdmin | Ports | Data Persistence | Security |
|---|---|---|---|---|---|
| dev | Full development stack for local use. | ✅ | 5432:5432, 8080:80 |
Persistent volumes | Medium |
| test | Ephemeral test environment (tmpfs DB, random port). | ❌ | Random | In-memory | Light |
| prod | Hardened production environment. | ❌ | None | Persistent volumes | Strong |
git clone https://github.com/<your-username>/pgstack-docker.git
cd pgstack-dockermkdir -p secrets
echo "strong-db-password" > secrets/postgres_password.txt
echo "strong-pgadmin-password" > secrets/pgadmin_password.txtEdit .env for local/dev and .env.prod for production.
Runs PostgreSQL and pgAdmin locally with exposed ports.
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile dev up -dAccess:
- pgAdmin: http://localhost:8080
- PostgreSQL:
localhost:5432Credentials from.envandsecrets/postgres_password.txt.
Stop and clean:
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile dev downEphemeral PostgreSQL instance using tmpfs (fast, no data persistence). Great for CI/CD or integration testing.
docker compose -f docker-compose.yml -f docker-compose.test.yml up -d dbDiscover the random test port:
docker compose -f docker-compose.yml -f docker-compose.test.yml port db 5432Clean up:
docker compose -f docker-compose.yml -f docker-compose.test.yml down -vHardened configuration — no pgAdmin, no published ports, read-only file system, and resource limits.
docker compose --env-file .env.prod \
-f docker-compose.yml -f docker-compose.prod.yml \
--profile prod up -dValidate before running:
docker compose --env-file .env.prod \
-f docker-compose.yml -f docker-compose.prod.yml \
--profile prod configStop and remove:
docker compose --env-file .env.prod \
-f docker-compose.yml -f docker-compose.prod.yml \
--profile prod down| Service | Health Check Command |
|---|---|
| Postgres | pg_isready -U $POSTGRES_USER -d $POSTGRES_DB |
| pgAdmin | wget -qO- http://127.0.0.1/misc/ping >/dev/null |
All services will wait until dependencies are healthy before startup.
docker compose down -v --remove-orphans- Use
docker compose configto preview the final merged configuration. - For Swarm or resource enforcement, add
--compatibilitywhen deploying. - Keep
PGADMIN_CONFIG_values as Python literals ('True',10, or'string'). - Never expose
5432or pgAdmin in production.
MIT License © 2025
Better is better than best.