services: postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-wedding} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB:-wedding} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-wedding} -d ${POSTGRES_DB:-wedding}"] interval: 10s timeout: 5s retries: 10 minio: image: minio/minio:latest restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} volumes: - minio_data:/data healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 15s timeout: 10s retries: 10 minio-init: image: minio/mc:latest restart: "no" depends_on: minio: condition: service_healthy environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} S3_BUCKET: ${S3_BUCKET:-wedding-media} entrypoint: - /bin/sh - -c - | set -e mc alias set local http://minio:9000 "$$MINIO_ROOT_USER" "$$MINIO_ROOT_PASSWORD" mc mb --ignore-existing local/"$$S3_BUCKET" mc anonymous set download local/"$$S3_BUCKET" mc cors set local/"$$S3_BUCKET" /tmp/cors.json || true echo "minio init done" volumes: - ./infra/minio-cors.json:/tmp/cors.json:ro app: build: context: . dockerfile: Dockerfile restart: unless-stopped depends_on: postgres: condition: service_healthy minio: condition: service_healthy environment: DATABASE_URL: postgres://${POSTGRES_USER:-wedding}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-wedding} S3_ENDPOINT: ${S3_INTERNAL_ENDPOINT:-https://${MEDIA_DOMAIN}} S3_BUCKET: ${S3_BUCKET:-wedding-media} S3_REGION: ${S3_REGION:-us-east-1} S3_ACCESS_KEY_ID: ${MINIO_ROOT_USER} S3_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD} S3_PUBLIC_BASE_URL: https://${MEDIA_DOMAIN}/${S3_BUCKET:-wedding-media} S3_FORCE_PATH_STYLE: "true" COUPLE_NAMES: ${COUPLE_NAMES:-Stefanie & Leandro} EVENT_DATE: ${EVENT_DATE:-} PUBLIC_BASE_URL: https://${DOMAIN} ADMIN_PASSWORD: ${ADMIN_PASSWORD} SESSION_SECRET: ${SESSION_SECRET} ALLOWED_ADMIN_EMAILS: ${ALLOWED_ADMIN_EMAILS} AUTO_MIGRATE: "true" NODE_ENV: production PORT: 3000 expose: - "3000" caddy: image: caddy:2-alpine restart: unless-stopped ports: - "80:80" - "443:443" - "443:443/udp" environment: DOMAIN: ${DOMAIN} MEDIA_DOMAIN: ${MEDIA_DOMAIN} ACME_EMAIL: ${ACME_EMAIL} volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config depends_on: - app - minio postgres-backup: image: prodrigestivill/postgres-backup-local:16-alpine restart: unless-stopped depends_on: postgres: condition: service_healthy environment: POSTGRES_HOST: postgres POSTGRES_DB: ${POSTGRES_DB:-wedding} POSTGRES_USER: ${POSTGRES_USER:-wedding} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_EXTRA_OPTS: "--clean --if-exists" SCHEDULE: ${BACKUP_SCHEDULE_DB:-@daily} BACKUP_KEEP_DAYS: ${BACKUP_KEEP_DAYS:-14} BACKUP_KEEP_WEEKS: ${BACKUP_KEEP_WEEKS:-4} BACKUP_KEEP_MONTHS: ${BACKUP_KEEP_MONTHS:-6} TZ: ${TZ:-America/Sao_Paulo} volumes: - ./backups/postgres:/backups media-backup: image: alpine:3.20 restart: unless-stopped depends_on: minio: condition: service_healthy environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} S3_BUCKET: ${S3_BUCKET:-wedding-media} BACKUP_SCHEDULE_MEDIA: ${BACKUP_SCHEDULE_MEDIA:-0 3 * * *} BACKUP_REMOTE_ENDPOINT: ${BACKUP_REMOTE_ENDPOINT:-} BACKUP_REMOTE_ACCESS_KEY: ${BACKUP_REMOTE_ACCESS_KEY:-} BACKUP_REMOTE_SECRET_KEY: ${BACKUP_REMOTE_SECRET_KEY:-} BACKUP_REMOTE_BUCKET: ${BACKUP_REMOTE_BUCKET:-} TZ: ${TZ:-America/Sao_Paulo} volumes: - ./backups/media:/backups - ./infra/backup:/scripts:ro entrypoint: ["/bin/sh", "/scripts/media-backup-entrypoint.sh"] volumes: postgres_data: minio_data: caddy_data: caddy_config: