# Production stack: Apache (on the host) terminates TLS and proxies to 127.0.0.1:4000. # # Helper script: ./scripts/deploy_prod.sh --help # # --- Local: build and push --- # cp .env.prod.example .env.prod && edit secrets # export TAG=0.2.0 # optional; relay/migrator use :latest if unset # docker login # ./scripts/deploy_prod.sh build-push # # --- Remote: pull and run --- # ./scripts/deploy_prod.sh deploy # # Images (repository: silberengel/gc-http-relay): # :${TAG} — Phoenix release (relay + migrator) # :setup — one-shot DB user bootstrap (tag is literal "setup") services: postgres: image: docker.io/apache/age:release_PG17_1.6.0 restart: unless-stopped user: 1000:1000 volumes: - pgdata:/var/lib/postgresql/data environment: POSTGRES_DB: ${POSTGRES_DB:?set POSTGRES_DB in .env.prod} POSTGRES_USER: ${POSTGRES_USER:?set POSTGRES_USER in .env.prod} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env.prod} command: > postgres healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] interval: 10s timeout: 5s retries: 5 deploy: resources: limits: cpus: "1.00" memory: 1G reservations: cpus: "0.50" memory: 512M networks: - internal setup: image: docker.io/silberengel/gc-http-relay:setup build: context: . dockerfile: ./docker/setup.Dockerfile command: ["/usr/local/bin/usersetup.sh"] restart: "no" depends_on: postgres: condition: service_healthy environment: POSTGRES_HOST: ${POSTGRES_HOST:-postgres} POSTGRES_USER: ${POSTGRES_USER:?set POSTGRES_USER in .env.prod} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env.prod} POSTGRES_DB: ${POSTGRES_DB:?set POSTGRES_DB in .env.prod} POSTGRES_RUNTIME_USER: ${POSTGRES_RUNTIME_USER:?set POSTGRES_RUNTIME_USER in .env.prod} POSTGRES_RUNTIME_PASSWORD: ${POSTGRES_RUNTIME_PASSWORD:?set POSTGRES_RUNTIME_PASSWORD in .env.prod} networks: - internal migrator: image: docker.io/silberengel/gc-http-relay:${TAG:-latest} build: context: . dockerfile: ./docker/server.Dockerfile command: ["/app/bin/migrate"] restart: "no" depends_on: postgres: condition: service_healthy setup: condition: service_completed_successfully environment: DATABASE_URL: "ecto://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST:-postgres}/${POSTGRES_DB}" SECRET_KEY_BASE: ${SECRET_KEY_BASE:?set SECRET_KEY_BASE in .env.prod} networks: - internal relay: image: docker.io/silberengel/gc-http-relay:${TAG:-latest} build: context: . dockerfile: ./docker/server.Dockerfile command: ["/app/bin/server"] restart: unless-stopped deploy: resources: limits: cpus: "1.00" memory: 1G reservations: cpus: "0.50" memory: 512M depends_on: postgres: condition: service_healthy migrator: condition: service_completed_successfully ports: - "127.0.0.1:4000:4000" environment: DATABASE_URL: "ecto://${POSTGRES_RUNTIME_USER}:${POSTGRES_RUNTIME_PASSWORD}@${POSTGRES_HOST:-postgres}/${POSTGRES_DB}" SECRET_KEY_BASE: ${SECRET_KEY_BASE:?set SECRET_KEY_BASE in .env.prod} PHX_HOST: ${PHX_HOST:?set PHX_HOST in .env.prod (public hostname, no scheme)} networks: - internal networks: internal: volumes: pgdata: