services: db: image: docker.io/library/postgres:16-alpine container_name: metamorph-db restart: unless-stopped environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - metamorph_db:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] interval: 5s timeout: 5s retries: 10 networks: - metamorph # No ports exposed on the host: the api reaches it on the internal network. api: build: context: ./backend dockerfile: Dockerfile target: runtime container_name: metamorph-api restart: unless-stopped environment: APP_ENV: ${APP_ENV} POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_HOST: ${POSTGRES_HOST} POSTGRES_PORT: ${POSTGRES_PORT} JWT_SECRET: ${JWT_SECRET} LOG_LEVEL: ${LOG_LEVEL} FRONT_ORIGIN: ${FRONT_ORIGIN} EVIDENCE_DIR: ${EVIDENCE_DIR} volumes: - metamorph_evidence:/data/evidence depends_on: db: condition: service_healthy ports: - "${HOST_API_PORT:-8000}:8000" healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/api/v1/health',timeout=2).status==200 else 1)\""] interval: 30s timeout: 5s retries: 3 start_period: 10s networks: - metamorph front: build: context: ./frontend dockerfile: Dockerfile args: VITE_API_BASE_URL: ${VITE_API_BASE_URL} container_name: metamorph-front restart: unless-stopped depends_on: - api ports: - "${HOST_FRONT_PORT:-8080}:80" healthcheck: test: ["CMD-SHELL", "wget -qO- http://127.0.0.1/healthz | grep -q ok"] interval: 30s timeout: 3s retries: 3 start_period: 5s networks: - metamorph volumes: metamorph_db: metamorph_evidence: networks: metamorph: driver: bridge