name: personal-lifecycle-tracker-prod
services:
db:
image: postgres:16-alpine
container_name: personal-lifecycle-tracker-db-prod
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-postgres}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
POSTGRES_DB: ${POSTGRES_DB:-lifecycle}
volumes:
- postgres_data_prod:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-lifecycle}"]
interval: 5s
timeout: 5s
retries: 5
start_period: 5s
backend:
image: ${BACKEND_IMAGE:-personal-lifecycle-tracker-backend:latest}
build:
context: ./backend
dockerfile: Dockerfile
target: base
container_name: personal-lifecycle-tracker-backend-prod
environment:
PORT: 8000
PYTHONUNBUFFERED: "1"
CORS_ORIGINS: "http://localhost:8088"
DATABASE_URL: "${DATABASE_URL:-postgresql://postgres:postgres@db:5432/lifecycle}"
APP_ENV: "${APP_ENV:-production}"
APP_VERSION: "${APP_VERSION:-1.0.0}"
OTEL_SERVICE_NAME: "api-backend"
OTEL_EXPORTER_OTLP_ENDPOINT: "${OTEL_EXPORTER_OTLP_ENDPOINT:-}"
OTEL_RESOURCE_ATTRIBUTES: "service.name=api-backend,deployment.environment=${APP_ENV:-production},service.version=${APP_VERSION:-1.0.0}"
networks:
- default
- observability-net
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://127.0.0.1:8000/health"]
interval: 5s
timeout: 5s
retries: 5
start_period: 5s
restart: unless-stopped
frontend:
image: ${FRONTEND_IMAGE:-personal-lifecycle-tracker-frontend:prod}
build:
context: ./frontend
dockerfile: Dockerfile
target: prod
container_name: personal-lifecycle-tracker-frontend-prod
environment:
PORT: 80
BACKEND_URL: backend:8000
ports:
- "${PROD_PORT:-8088}:80"
networks:
- default
depends_on:
backend:
condition: service_healthy
healthcheck:
test: ["CMD", "caddy", "validate", "--config", "/etc/caddy/Caddyfile"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
volumes:
postgres_data_prod:
networks:
default:
observability-net:
name: ${OBSERVABILITY_NET:-personal-lifecycle-observability-net}
external: true