name: softvowels services: db: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: payload POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: softvowels volumes: - pgdata:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U payload -d softvowels"] interval: 10s timeout: 5s retries: 10 networks: - app cms: build: context: . dockerfile: ./apps/cms/Dockerfile restart: unless-stopped depends_on: db: condition: service_healthy environment: NODE_ENV: production PORT: 3000 DATABASE_URI: postgres://payload:${POSTGRES_PASSWORD}@db:5432/softvowels PAYLOAD_SECRET: ${PAYLOAD_SECRET} PAYLOAD_PUBLIC_SERVER_URL: https://${CMS_HOSTNAME} SERVER_URL: https://${CMS_HOSTNAME} CORS_ORIGINS: https://${WEB_HOSTNAME},http://localhost:4321 ASTRO_REVALIDATE_URL: http://host.docker.internal:4321/__revalidate ASTRO_REVALIDATE_TOKEN: ${REVALIDATE_TOKEN} volumes: - cms-uploads:/app/apps/cms/media networks: - app # The public site. We deliberately do NOT bake dist/ into the image: # scripts/rebuild.sh (run by the host-side webhook) writes fresh HTML to # ./apps/web/dist on the host, and we mount that path into nginx. That way # publishing in /admin → new content is live within ~30-60s without any # docker build / image push step. web: image: nginx:1.27-alpine restart: unless-stopped depends_on: - cms volumes: - ./apps/web/dist:/usr/share/nginx/html:ro - ./apps/web/nginx-default.conf:/etc/nginx/conf.d/default.conf:ro networks: - app volumes: pgdata: cms-uploads: networks: app: driver: bridge