Docker cookbook · Beginner

Run PostgreSQL in Compose with a healthcheck and persistent data

Start a database for development that keeps data and that the app waits for.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Use the official image with a named volume, a pg_isready healthcheck, credentials from a git-ignored .env file, and depends_on: condition: service_healthy for the app.

Solution

services:
  db:
    image: postgres:18-alpine
    env_file: .env
    volumes: [pgdata:/var/lib/postgresql]
    ports: ["127.0.0.1:5432:5432"]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 2s
      retries: 20
  api:
    build: .
    env_file: .env
    depends_on:
      db: {condition: service_healthy}
volumes:
  pgdata:

Pitfalls

  • $ in healthcheck commands is interpolated by Compose; escape it as $$.
  • Mounting the volume at the wrong path for the image version; PostgreSQL 18 images keep data under /var/lib/postgresql (version subdirectories), older ones under /var/lib/postgresql/data.
  • docker compose down -v deletes the data.

Variations

  • Init scripts in /docker-entrypoint-initdb.d/ run on first start only.
  • Seed data with a one-off docker compose run --rm api seed.

Further reading: Official PostgreSQL image

Reference: https://hub.docker.com/_/postgres

More Docker recipes

Was this page helpful?