Running PostgreSQL in Docker
Learn how to run PostgreSQL in Docker with persistent data storage, environment-based configuration, custom initialization scripts, and proper networking for application connectivity.
Detailed Explanation
PostgreSQL with Docker
Running PostgreSQL in Docker is ideal for development environments and testing. The official image handles initialization automatically based on environment variables:
docker run -d \
--name postgres \
-e POSTGRES_USER=myuser \
-e POSTGRES_PASSWORD=mypassword \
-e POSTGRES_DB=myapp \
-p 5432:5432 \
postgres:16
Environment Variables
The official PostgreSQL image supports these key variables:
| Variable | Purpose | Default |
|---|---|---|
POSTGRES_PASSWORD |
Superuser password (required) | None |
POSTGRES_USER |
Superuser name | postgres |
POSTGRES_DB |
Default database name | Same as POSTGRES_USER |
PGDATA |
Data directory path | /var/lib/postgresql/data |
Persistent Data Storage
Without a volume, database data is lost when the container is removed. Always mount a volume for the data directory:
docker run -d \
--name postgres \
-e POSTGRES_USER=myuser \
-e POSTGRES_PASSWORD=mypassword \
-e POSTGRES_DB=myapp \
-v pgdata:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:16
Custom Initialization Scripts
Place SQL or shell scripts in /docker-entrypoint-initdb.d/ to run them when the database is first created:
docker run -d \
--name postgres \
-e POSTGRES_USER=myuser \
-e POSTGRES_PASSWORD=mypassword \
-v pgdata:/var/lib/postgresql/data \
-v $(pwd)/init-scripts:/docker-entrypoint-initdb.d:ro \
-p 5432:5432 \
postgres:16
Scripts run in alphabetical order and only on first initialization (when the data directory is empty). Common uses:
- Creating additional databases
- Loading seed data
- Setting up extensions (
CREATE EXTENSION pgcrypto;) - Creating additional users and roles
Custom PostgreSQL Configuration
Override the default postgresql.conf:
docker run -d \
--name postgres \
-e POSTGRES_USER=myuser \
-e POSTGRES_PASSWORD=mypassword \
-v pgdata:/var/lib/postgresql/data \
-v $(pwd)/postgresql.conf:/etc/postgresql/postgresql.conf:ro \
-p 5432:5432 \
postgres:16 -c 'config_file=/etc/postgresql/postgresql.conf'
Or pass individual parameters directly:
docker run -d \
--name postgres \
-e POSTGRES_PASSWORD=mypassword \
postgres:16 \
-c shared_buffers=256MB \
-c max_connections=100 \
-c work_mem=4MB
Connecting from Another Container
Use Docker networking for container-to-container communication:
docker network create app-net
docker run -d \
--name postgres \
--network app-net \
-e POSTGRES_PASSWORD=mypassword \
-v pgdata:/var/lib/postgresql/data \
postgres:16
docker run -d \
--name api \
--network app-net \
-e DATABASE_URL=postgres://postgres:mypassword@postgres:5432/postgres \
my-api-image
Notice the connection string uses postgres (the container name) as the hostname.
Production Docker Run
docker run -d \
--name postgres \
--restart unless-stopped \
--memory 2g \
--cpus 2 \
--network app-net \
-e POSTGRES_USER=appuser \
-e POSTGRES_PASSWORD_FILE=/run/secrets/db_password \
-e POSTGRES_DB=production \
-v pgdata:/var/lib/postgresql/data \
-v $(pwd)/init:/docker-entrypoint-initdb.d:ro \
postgres:16 \
-c shared_buffers=512MB \
-c max_connections=200
Use Case
Setting up a PostgreSQL database for a development team, with persistent storage, initialization scripts that create the schema and seed data, and network connectivity to the application container.