docker compose for an app with a PostgreSQL database
A compose.yaml that runs your application next to a PostgreSQL container, with a named volume for the data, a health check so the app starts after the database is ready, and the commands to operate it.
Drafted with AI from official documentation. Scripts were run in a test environment and repository links verified. Awaiting a human check. Did it work for you? Last edited Outdated?
Docker Compose describes several containers in one YAML file and starts, stops and rebuilds them together. The most common pair is an application plus a database. This entry walks through a compose.yaml for an app and PostgreSQL, explaining each part, and then the day-to-day commands. Compose ships as the docker compose plugin with Docker Engine and Docker Desktop; the old separate docker-compose binary is retired.
The compose file
Save this as compose.yaml in the project directory, next to the app’s Dockerfile:
services:
app:
build: .
ports:
- "8000:8000"
environment:
DATABASE_URL: postgres://app:app_password@db:5432/app
depends_on:
db:
condition: service_healthy
restart: unless-stopped
db:
image: postgres:17
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app_password
POSTGRES_DB: app
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d app"]
interval: 5s
timeout: 3s
retries: 10
restart: unless-stopped
volumes:
pgdata:
What each part does
services: one entry per container. Compose puts them on a shared network where each service is reachable by its name, so the app connects to hostdb, port5432, and no port needs to be published for the database.build: .builds the app image from the Dockerfile in this directory. Useimage:instead when the image already exists in a registry.portspublishes the app onlocalhost:8000. Quote port mappings; unquoted8000:8000can be misread by YAML.environmentpasses configuration in. The PostgreSQL image readsPOSTGRES_USER,POSTGRES_PASSWORDandPOSTGRES_DBon first start to create the user and database.volumes: pgdata:/var/lib/postgresql/datastores the database files in a named volume, sodocker compose downandupkeep the data. The volume is declared at the bottom.healthcheckrunspg_isreadyevery 5 seconds. Combined withdepends_on: condition: service_healthyit makes the app wait until PostgreSQL accepts connections, not merely until the container exists.restart: unless-stoppedbrings both back after a reboot or crash.
The example pins postgres:17. Pin a major version for databases: moving to a newer major requires a dump and restore, and from PostgreSQL 18 the official image also changed its default data directory, so an unpinned latest can break on the next pull.
Keep secrets out of the file
Compose reads a .env file in the same directory and substitutes ${VAR} in the YAML. Put the password there and keep .env out of version control:
POSTGRES_PASSWORD=choose-a-long-random-password
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
Run docker compose config to see the file with all variables filled in and check that it parses.
Start, inspect, stop
docker compose up -d
docker compose ps
docker compose logs -f db
docker compose logs -f app
docker compose exec db psql -U app -d app
docker compose stop
docker compose down
up -dbuilds what is missing, creates the network and volume, and starts both services in the background.exec db psql ...opens a SQL shell inside the database container;\dtlists tables,\qleaves.stopstops the containers but keeps them;downremoves containers and the network but keeps the named volume.- Careful:
docker compose down -valso deletes thepgdatavolume and with it the whole database.
Rebuild after code changes
docker compose up -d --build app
docker compose pull db
docker compose up -d
--build rebuilds the app image before starting. pull fetches a newer postgres:17 minor release, which is safe to apply with a plain up -d.
Back up the database
docker compose exec db pg_dump -U app -d app > backup.sql
cat backup.sql | docker compose exec -T db psql -U app -d app
The first line writes a plain SQL dump to the host. The second restores it into an empty database; -T disables the pseudo-terminal so the file can be piped in.
Official documentation
Did this work for you?
No votes yet. Be the first.
If it did not work, the report form below tells the editors what went wrong.
See also
- 0056 Docker Compose: run a small web app with a database Docker Compose describes several containers, their ports, volumes and environment in one compose.yaml file, then starts them all with docker compose up. Intermediate · Step by step · Linux, macOS, Windows Article Docker basics · Docker Compose 15 Oct 2026
- 0198 Install PostgreSQL and connect with psql on Debian, Ubuntu and RHEL Install the PostgreSQL server from your distribution or the official PGDG repositories, start it, and open your first psql session as the… Beginner · Step by step · Linux Article Install & connect 15 Oct 2026
- 0199 psql meta-commands cheat sheet The backslash commands you use every day in psql: connecting, listing databases, tables and roles, describing objects, timing queries, expanded output and… Beginner · Cheat sheet · Any system Article Install & connect · Roles & administration 15 Oct 2026
- 0201 pg_hba.conf and PostgreSQL authentication methods pg_hba.conf decides who may connect from where and how they must prove who they are. Rules are checked top to bottom and… Intermediate · Explains an idea · Linux Article Install & connect · Security & access 15 Oct 2026
- 0210 Fix: FATAL: no pg_hba.conf entry for host The server received the connection but no pg_hba.conf rule matches this client address, user, database and SSL mode. Add or correct a… Intermediate · Fixes an error · Linux Article Install & connect · Security & access 15 Oct 2026
- 0211 Fix: psql connection to server on socket /var/run/postgresql/.s.PGSQL.5432 failed psql tried the local Unix socket and found nothing there. The server is not running, listens on another port, or uses a… Beginner · Fixes an error · Linux Article Install & connect 15 Oct 2026
Repos in the wild
- postgres/postgres: PostgreSQL source code mirror postgres/postgres The official read-only GitHub mirror of the PostgreSQL source repository. Browse the code and history here; patches go through the project's mailing lists, not pull requests. GitHub
- docker/compose docker/compose The source of Docker Compose, the tool that defines and runs multi-container applications from a compose.yaml file. Useful for release notes, the issue tracker and the examples directory. GitHub
- Traefik: a reverse proxy that configures itself from Docker and Kubernetes traefik/traefik Traefik is an open-source edge router that discovers services from Docker labels, Kubernetes resources and other providers and routes traffic to them, with automatic Let's Encrypt certificates and a dashboard. GitHub
History
Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.
- Dominik +4,198 chars