services: backend: build: context: ../backend dockerfile: Dockerfile target: production restart: unless-stopped ports: - "8091:8000" environment: DATABASE_URL: "postgresql+asyncpg://demo_app:${DB_PASSWORD}@postgres:5432/demodb" REDIS_URL: "redis://:${REDIS_PASSWORD}@redis:6379/0" ENCRYPTION_KEY: "${ENCRYPTION_KEY}" BACKUP_PASSPHRASE: "not-used-in-demo" ENVIRONMENT: "${ENVIRONMENT:-production}" ALLOW_REGISTRATION: "false" BASE_CURRENCY: "GBP" DEMO_MODE: "true" DEMO_SNAPSHOT_PATH: "/app/demo_data/demo_snapshot.sql.gz" volumes: - ../secrets:/run/secrets:ro - demo_snapshot:/app/demo_data:rw - demo_uploads:/app/uploads depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - frontend_net - backend_net security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"] interval: 30s timeout: 10s retries: 3 start_period: 90s frontend: build: context: ../frontend dockerfile: Dockerfile target: production restart: unless-stopped ports: - "4001:3000" networks: - frontend_net security_opt: - no-new-privileges:true read_only: true tmpfs: - /tmp - /var/cache/nginx - /var/run postgres: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_DB: demodb POSTGRES_USER: demo_app POSTGRES_PASSWORD: "${DB_PASSWORD}" volumes: - demo_postgres:/var/lib/postgresql/data - ../postgres/init:/docker-entrypoint-initdb.d:ro networks: - backend_net security_opt: - no-new-privileges:true healthcheck: test: ["CMD-SHELL", "pg_isready -U demo_app -d demodb"] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine restart: unless-stopped command: redis-server --requirepass "${REDIS_PASSWORD}" networks: - backend_net security_opt: - no-new-privileges:true healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"] interval: 10s timeout: 5s retries: 3 resetter: image: alpine:3.19 restart: unless-stopped environment: DATABASE_URL: "postgresql://demo_app:${DB_PASSWORD}@postgres:5432/demodb" DEMO_SNAPSHOT_PATH: "/snapshot/demo_snapshot.sql.gz" BACKEND_URL: "http://backend:8000" volumes: - demo_snapshot:/snapshot:ro - demo_uploads:/uploads:rw - ./reset.sh:/reset.sh:ro networks: - backend_net depends_on: backend: condition: service_healthy entrypoint: > sh -c " apk add --no-cache postgresql-client curl && echo '0 * * * * sh /reset.sh >> /var/log/reset.log 2>&1' | crontab - && crond -f -l 6 " security_opt: - no-new-privileges:true volumes: demo_postgres: demo_snapshot: demo_uploads: networks: frontend_net: driver: bridge backend_net: driver: bridge internal: true