Files
blog/docker-compose.yml
T
davide 960b007ba7 Add Docker Compose stack with PostgreSQL and Caddy
Production traffic enters through Caddy, which terminates TLS for the public
domain and the CMS subdomain and sets HSTS and the other security headers.
PostgreSQL, Strapi and Nuxt publish no ports of their own.

docker-compose.dev.yml publishes the ports on localhost and drops Caddy for
local testing. It is a separate file rather than an override.yml so it can only
be applied when passed explicitly, never by accident in production.
2026-08-25 11:42:24 +02:00

79 lines
1.9 KiB
YAML

services:
database:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
cms:
build: ./cms
restart: unless-stopped
depends_on:
database:
condition: service_healthy
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: 1337
DATABASE_CLIENT: postgres
DATABASE_HOST: database
DATABASE_PORT: 5432
DATABASE_NAME: ${POSTGRES_DB}
DATABASE_USERNAME: ${POSTGRES_USER}
DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
APP_KEYS: ${APP_KEYS}
API_TOKEN_SALT: ${API_TOKEN_SALT}
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
TRANSFER_TOKEN_SALT: ${TRANSFER_TOKEN_SALT}
JWT_SECRET: ${JWT_SECRET}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
STRAPI_URL: https://${CMS_DOMAIN}
volumes:
- cms-uploads:/app/public/uploads
frontend:
build: ./frontend
restart: unless-stopped
depends_on:
- cms
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: 3000
NUXT_STRAPI_URL: ${STRAPI_URL}
NUXT_PUBLIC_SITE_URL: ${PUBLIC_SITE_URL}
NUXT_PUBLIC_STRAPI_URL: ${PUBLIC_STRAPI_URL}
caddy:
image: caddy:2-alpine
restart: unless-stopped
depends_on:
- frontend
- cms
ports:
- "80:80"
- "443:443"
environment:
PUBLIC_DOMAIN: ${PUBLIC_DOMAIN}
CMS_DOMAIN: ${CMS_DOMAIN}
ACME_EMAIL: ${ACME_EMAIL}
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
volumes:
postgres-data:
cms-uploads:
caddy-data:
caddy-config: