hp-studios-ai-content-agent/docker-compose.prod.yml
DJP 5a7d1f0636 Prod deploy binds to 127.0.0.1 only + drops postgres/redis host publish
Symptom: Docker refused to bind :::$PORT on a fresh, provably free
port — a known stuck-IPv6-reservation bug on shared Docker hosts.
Fixes the root cause by only asking Docker to bind the IPv4 loopback.

- docker-compose.prod.yml
    postgres/redis: !override ports: []
      (not reachable from host; intra-compose calls still work)
    api/frontend:   !override 127.0.0.1:$PORT:$INTERNAL_PORT
      (Apache is the only caller; reaches them via loopback)

- deploy.sh is_port_free: probe IPv4 loopback only. The old IPv6 bind
  check was correct in principle but rejected usable ports on this host
  because stale :::PORT reservations don't collide with an IPv4-only
  bind.

Security upgrade too: postgres, redis, api are no longer exposed to
the server's public interface.
2026-04-22 15:49:29 -04:00

49 lines
1.5 KiB
YAML

# Production overrides for docker-compose.yml.
# Use: docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
#
# Differences from the dev compose file:
# - Frontend is built with the `prod` target (nginx serving dist/)
# - No dev volume mounts for hot-reload
# - Frontend listens on port 80 internally; host port still configurable
# - Build args for VITE_API_URL and VITE_BASE_PATH come from .env
name: hp-studios-ai-content-agent
# Production binds all host ports to 127.0.0.1 only — Apache is the only
# caller and reaches the containers via loopback. This also sidesteps a
# recurring Docker IPv6 "port already allocated" bug on shared hosts where
# stale reservations on :::PORT block fresh binds.
#
# Postgres + Redis don't need host publication at all in prod; intra-service
# calls use the internal compose network.
services:
postgres:
ports: !override []
redis:
ports: !override []
api:
volumes:
- ./data:/app/data
# Prod uvicorn: no --reload, controlled concurrency
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2
ports: !override
- "127.0.0.1:${API_HOST_PORT}:8000"
worker:
volumes:
- ./data:/app/data
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
target: prod
args:
VITE_API_URL: ${VITE_API_URL}
VITE_BASE_PATH: ${VITE_BASE_PATH}
ports: !override
- "127.0.0.1:${FRONTEND_HOST_PORT}:80"
volumes: []