services: webserver: build: context: . dockerfile: nginx/Dockerfile container_name: nginx_webserver volumes: - nginx_logs:/var/log/nginx restart: unless-stopped depends_on: api: condition: service_started networks: - proxy # external — reachable by your reverse proxy / traefik - internal # needs a path to the api container api: build: . container_name: wp_api environment: # Preferred: the API builds its own connection string from these and # encodes the password automatically (no manual URL-encoding needed). POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} POSTGRES_HOST: db # Optional full-URL override (must be URL-encoded if used). DATABASE_URL: ${DATABASE_URL:-} # Signs login session cookies. MUST be set (see server/.env.example). AUTH_SECRET_KEY: ${AUTH_SECRET_KEY} AUTH_SESSION_HOURS: ${AUTH_SESSION_HOURS:-12} restart: unless-stopped depends_on: db: condition: service_healthy # waits for postgres to accept connections networks: - internal db: image: postgres:16-alpine container_name: wp_db environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - pgdata:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] interval: 10s timeout: 5s retries: 5 networks: - internal volumes: pgdata: nginx_logs: networks: proxy: name: proxy external: true internal: internal: true # no outbound internet access from api/db