services: api: build: context: . target: runtime image: fastapi-modulith:local restart: unless-stopped ports: - "${APP_PORT:-8000}:8000" env_file: - .env environment: APP_ENV: production DATABASE_URL: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}@db:5432/${POSTGRES_DB:-todo_db} REDIS_URL: redis://:${REDIS_PASSWORD:?Set REDIS_PASSWORD in .env}@redis:6379/0 OTEL_ENABLED: "true" OTEL_SERVICE_NAME: "fastapi-modulith" OTEL_EXPORTER_OTLP_ENDPOINT: "http://otel-collector:4318/v1/traces" depends_on: db: condition: service_healthy redis: condition: service_healthy healthcheck: test: [ "CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=3).read()", ] interval: 30s timeout: 5s retries: 3 start_period: 30s db: image: postgres:17-alpine restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env} POSTGRES_DB: ${POSTGRES_DB:-todo_db} 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 redis: image: redis:8-alpine restart: unless-stopped command: [ "redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD:?Set REDIS_PASSWORD in .env}", ] volumes: - redis_data:/data healthcheck: test: [ "CMD", "redis-cli", "-a", "${REDIS_PASSWORD:?Set REDIS_PASSWORD in .env}", "ping", ] interval: 10s timeout: 5s retries: 5 prometheus: image: prom/prometheus:latest restart: unless-stopped ports: - "${PROMETHEUS_PORT:-9090}:9090" volumes: - ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus_data:/prometheus command: - "--config.file=/etc/prometheus/prometheus.yml" - "--storage.tsdb.path=/prometheus" - "--storage.tsdb.retention.time=30d" depends_on: api: condition: service_healthy otel-collector: image: otel/opentelemetry-collector-contrib:latest restart: unless-stopped ports: - "${OTEL_COLLECTOR_PORT:-4318}:4318" volumes: - ./docker/otel-collector/config.yaml:/etc/otelcol-contrib/config.yaml:ro depends_on: api: condition: service_healthy volumes: postgres_data: redis_data: prometheus_data: