A clean local PostgreSQL setup using Docker Compose—with environment variables, persistent storage, health checks, and Adminer included.
Stack: PostgreSQL 17 • Docker Compose • Adminer • Alpine Linux
Why Docker for PostgreSQL?
Installing PostgreSQL directly on your machine works—but it also means managing versions, cleaning up installations, and configuring everything manually.
With Docker Compose, you get:
A fresh PostgreSQL instance in seconds
Isolated development environment
Persistent data using volumes
Easy reset whenever needed
Adminer for database management in the browser
Let's build it.
Project Structure
your-project/
├── .env
├── compose.yaml
└── data/
└── db/
Important: Keep
.envandcompose.yamlin the same directory. Docker Compose automatically loads.envonly when both files are located together.
Step 1 — Create the .env file
Create a file named .env.
DB_NAME=postgres
DB_USER=your_username
DB_PASSWORD=your_password
DB_PORT=5432
Keeping credentials here makes your Compose file cleaner and easier to reuse.
Tip: Add
.envto.gitignore. Even for local projects, credentials should never be committed.
Step 2 — Create compose.yaml
We'll run two containers:
PostgreSQL
Adminer
services:
db:
image: postgres:17-alpine
container_name: postgres
restart: always
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
ports:
- ${DB_PORT}:5432
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${DB_NAME} -U $${DB_USER}"]
interval: 10s
timeout: 30s
retries: 5
volumes:
- ./data/db:/var/lib/postgresql/data
attach: false
database-ui:
image: adminer
restart: always
ports:
- 8080:8080
depends_on:
db:
condition: service_healthy
Understanding the Compose File
Environment Variables
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
These values come directly from the .env file.
PostgreSQL reads them only during the first initialization.
If the data directory already exists, PostgreSQL simply starts using the existing database.
Health Check
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${DB_NAME} -U $${DB_USER}"]
Instead of checking whether the container is merely running, Docker waits until PostgreSQL is actually ready to accept connections.
Notice the double dollar signs:
$${DB_NAME}
Docker Compose escapes the variable, allowing it to be evaluated inside the container, not by Compose itself.
Persistent Storage
volumes:
- ./data/db:/var/lib/postgresql/data
This maps PostgreSQL's data directory to your project folder.
Benefits:
Data survives container restarts
Easy backups
Delete the folder anytime for a fresh database
Service Dependency
depends_on:
db:
condition: service_healthy
Adminer waits until PostgreSQL reports a healthy state before starting.
Without this, Adminer may start too early and fail to connect.
Step 3 — Start Everything
Run:
docker compose up -d
On the first run Docker will:
Download both images
Create the containers
Initialize PostgreSQL
Start Adminer
Give PostgreSQL around 10–15 seconds to finish initialization.
Check Container Status
docker compose ps
A healthy PostgreSQL container looks similar to:
NAME STATUS
postgres Up (healthy)
database-ui Up
Step 4 — Open Adminer
Open your browser and navigate to:
You'll see the Adminer login page.
Use the following details:
Use the credentials from your .env file.
System : PostgreSQL
Server : db
Username : <your DB_USER>
Password : <your DB_PASSWORD>
Database : <your DB_NAME>
Why use db instead of localhost?
Inside Docker, every service gets its own hostname.
Since PostgreSQL's service is named:
db:
Adminer can reach it using:
db
Using localhost would point to the Adminer container itself—not PostgreSQL.
Useful Docker Commands
Stop the containers
docker compose down
Your database remains because it's stored in ./data/db.
View PostgreSQL logs
docker logs -f postgres
Verify environment variables
docker compose config
Connect directly using psql
docker exec -it postgres psql -U your_username -d postgres
Replace your_username with the value from your .env file.
Final Thoughts
That's it!
You now have a fully reproducible PostgreSQL development environment powered by Docker Compose.
With just two containers, you've added:
PostgreSQL 17
Persistent storage
Health checks
Environment variable support
Adminer web interface


Top comments (0)