# ACCESS Core — Staging Docker Compose (standalone stack, not an override) # Usage: docker compose -f docker-compose.staging.yml up -d db web # # Notes: # - Runs the production-style image target with access_core.settings.staging. # - This compose flow has no KMS; set PHI_LOCAL_ENCRYPTION_KEY (base64 32-byte) # in your .env before starting `web`, or every write to an encrypted field fails. # - The CMS mock server is intentionally not included: staging talks to the real # CMS sandbox API via CMS_API_BASE_URL. services: web: build: context: . target: runtime command: > sh -c "python manage.py migrate --noinput && exec gunicorn access_core.wsgi:application --bind 0.0.0.0:${PORT:-8000} --workers ${GUNICORN_WORKERS:-2} --threads ${GUNICORN_THREADS:-2} --timeout ${GUNICORN_TIMEOUT:-120} --access-logfile - --error-logfile -" environment: DJANGO_SETTINGS_MODULE: access_core.settings.staging DJANGO_SECRET_KEY: ${DJANGO_STAGING_SECRET_KEY:?set DJANGO_STAGING_SECRET_KEY in .env (synthetic data only)} DJANGO_DEBUG: "false" ALLOWED_HOSTS: ${STAGING_ALLOWED_HOSTS:-staging.access-core.example.com,localhost} DB_ENGINE: django.db.backends.postgresql DB_NAME: ${DB_NAME:-access_core} DB_USER: ${DB_USER:-access_staging} DB_PASSWORD: ${DB_PASSWORD:?set DB_PASSWORD in .env (synthetic data only)} DB_HOST: db DB_PORT: "5432" PHI_LOCAL_ENCRYPTION_KEY: ${PHI_LOCAL_ENCRYPTION_KEY:?set PHI_LOCAL_ENCRYPTION_KEY in .env (base64 32-byte key; this compose flow has no KMS)} CMS_API_BASE_URL: https://sandbox.bcda.cms.gov CMS_FHIR_VERSION_PATH: "R4" CMS_POST_MAX_RETRIES: "3" CMS_REQUEST_TIMEOUT_SECONDS: "120" depends_on: db: condition: service_healthy ports: - "8000:8000" db: image: docker.io/postgres:16-alpine environment: POSTGRES_DB: ${DB_NAME:-access_core} POSTGRES_USER: ${DB_USER:-access_staging} POSTGRES_PASSWORD: ${DB_PASSWORD:?set DB_PASSWORD in .env (synthetic data only)} volumes: - staging_db_data:/var/lib/postgresql/data ports: # Loopback only: web reaches db over the compose network, so exposing # Postgres on every host interface (LAN/public IP) gains nothing and # leaves it protected by a password alone. Use `docker exec -it psql` # or ssh-tunnel for remote access instead. - "127.0.0.1:5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-access_staging} -d ${DB_NAME:-access_core}"] interval: 10s timeout: 5s retries: 5 volumes: staging_db_data: driver: local