social-mi-bi/deploy/docker-compose.prod.yml

186 lines
6.6 KiB
YAML

# Production compose — fronted by Apache on the host.
#
# Everything binds to 127.0.0.1 so Apache is the only public entry point.
# DB + Redis have no host ports at all; only the API and MinIO S3 endpoint
# are loopback-exposed so Apache can proxy them.
#
# Run from the repo root:
# docker compose -f deploy/docker-compose.prod.yml --env-file deploy/.env.prod up -d --build
# Pin the compose project name so containers and volumes are namespaced as
# `social-mi-bi_*` regardless of which directory compose is invoked from.
# Without this, two repos that both keep their compose file under deploy/
# end up sharing the project name "deploy" and fighting over the same
# containers and volumes.
name: social-mi-bi
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 5s
timeout: 3s
retries: 40
restart: unless-stopped
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 40
restart: unless-stopped
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
# Tells MinIO what its public URL is so presigned URLs match when
# Apache reverse-proxies /<subpath>/s3/ to this container.
MINIO_SERVER_URL: ${MINIO_SERVER_URL}
ports:
# Loopback only — Apache fronts us via /<subpath>/s3/.
- "127.0.0.1:${MINIO_PORT}:9000"
volumes:
- minio-data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 5s
timeout: 3s
retries: 40
restart: unless-stopped
minio-init:
image: minio/mc:latest
depends_on:
minio:
condition: service_healthy
entrypoint: >
/bin/sh -c "
mc alias set local http://minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD} &&
mc mb --ignore-existing local/${MINIO_BUCKET_UPLOADS} &&
mc mb --ignore-existing local/${MINIO_BUCKET_ARTEFACTS} &&
mc mb --ignore-existing local/${MINIO_BUCKET_REPORTS} &&
echo 'MinIO buckets ready.'
"
restart: "no"
api:
build:
context: ..
dockerfile: deploy/Dockerfile.prod
args:
GIT_SHA: ${GIT_SHA:-unknown}
environment:
- APP_ENV=prod
- LOG_LEVEL=${LOG_LEVEL:-INFO}
- TZ=${TZ:-Europe/London}
- DATABASE_URL=${DATABASE_URL}
- ALEMBIC_DATABASE_URL=${ALEMBIC_DATABASE_URL}
- REDIS_URL=${REDIS_URL}
- MINIO_ENDPOINT=${MINIO_ENDPOINT}
- MINIO_PUBLIC_ENDPOINT=${MINIO_PUBLIC_ENDPOINT}
- MINIO_REGION=${MINIO_REGION}
- MINIO_ROOT_USER=${MINIO_ROOT_USER}
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
- MINIO_BUCKET_UPLOADS=${MINIO_BUCKET_UPLOADS}
- MINIO_BUCKET_ARTEFACTS=${MINIO_BUCKET_ARTEFACTS}
- MINIO_BUCKET_REPORTS=${MINIO_BUCKET_REPORTS}
- SESSION_SECRET=${SESSION_SECRET}
- SESSION_COOKIE_NAME=${SESSION_COOKIE_NAME}
- SESSION_MAX_AGE_SECONDS=${SESSION_MAX_AGE_SECONDS}
- BOOTSTRAP_ADMIN_EMAIL=${BOOTSTRAP_ADMIN_EMAIL}
- BOOTSTRAP_ADMIN_PASSWORD=${BOOTSTRAP_ADMIN_PASSWORD}
- BOOTSTRAP_ADMIN_NAME=${BOOTSTRAP_ADMIN_NAME}
- FRONTEND_ORIGIN=${FRONTEND_ORIGIN}
- API_PUBLIC_URL=${API_PUBLIC_URL}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- ANTHROPIC_MODEL_DATA_MAPPER=${ANTHROPIC_MODEL_DATA_MAPPER}
- ANTHROPIC_MODEL_INPUT_COLLECTOR=${ANTHROPIC_MODEL_INPUT_COLLECTOR}
- ANTHROPIC_MODEL_STRATEGY_WRITER=${ANTHROPIC_MODEL_STRATEGY_WRITER}
- ANTHROPIC_MODEL_REPORT_BUILDER=${ANTHROPIC_MODEL_REPORT_BUILDER}
- ANTHROPIC_MAX_OUTPUT_TOKENS=${ANTHROPIC_MAX_OUTPUT_TOKENS}
- APIFY_API_TOKEN=${APIFY_API_TOKEN}
- APIFY_ACTOR_TIKTOK=${APIFY_ACTOR_TIKTOK}
- APIFY_ACTOR_INSTAGRAM=${APIFY_ACTOR_INSTAGRAM}
- APIFY_CACHE_TTL_HOURS=${APIFY_CACHE_TTL_HOURS}
- APIFY_CAP_CENTS_PER_REPORT=${APIFY_CAP_CENTS_PER_REPORT}
- REPORT_MAX_HTML_BYTES=${REPORT_MAX_HTML_BYTES}
ports:
- "127.0.0.1:${API_PORT}:8000"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
minio:
condition: service_healthy
restart: unless-stopped
worker:
build:
context: ..
dockerfile: deploy/Dockerfile.prod
args:
GIT_SHA: ${GIT_SHA:-unknown}
command: arq app.workflow.queue.WorkerSettings
environment:
- APP_ENV=prod
- LOG_LEVEL=${LOG_LEVEL:-INFO}
- TZ=${TZ:-Europe/London}
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=${REDIS_URL}
- MINIO_ENDPOINT=${MINIO_ENDPOINT}
- MINIO_PUBLIC_ENDPOINT=${MINIO_PUBLIC_ENDPOINT}
- MINIO_REGION=${MINIO_REGION}
- MINIO_ROOT_USER=${MINIO_ROOT_USER}
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
- MINIO_BUCKET_UPLOADS=${MINIO_BUCKET_UPLOADS}
- MINIO_BUCKET_ARTEFACTS=${MINIO_BUCKET_ARTEFACTS}
- MINIO_BUCKET_REPORTS=${MINIO_BUCKET_REPORTS}
- SESSION_SECRET=${SESSION_SECRET}
- SESSION_COOKIE_NAME=${SESSION_COOKIE_NAME}
- SESSION_MAX_AGE_SECONDS=${SESSION_MAX_AGE_SECONDS}
- BOOTSTRAP_ADMIN_EMAIL=${BOOTSTRAP_ADMIN_EMAIL}
- BOOTSTRAP_ADMIN_PASSWORD=${BOOTSTRAP_ADMIN_PASSWORD}
- BOOTSTRAP_ADMIN_NAME=${BOOTSTRAP_ADMIN_NAME}
- FRONTEND_ORIGIN=${FRONTEND_ORIGIN}
- API_PUBLIC_URL=${API_PUBLIC_URL}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- ANTHROPIC_MODEL_DATA_MAPPER=${ANTHROPIC_MODEL_DATA_MAPPER}
- ANTHROPIC_MODEL_INPUT_COLLECTOR=${ANTHROPIC_MODEL_INPUT_COLLECTOR}
- ANTHROPIC_MODEL_STRATEGY_WRITER=${ANTHROPIC_MODEL_STRATEGY_WRITER}
- ANTHROPIC_MODEL_REPORT_BUILDER=${ANTHROPIC_MODEL_REPORT_BUILDER}
- ANTHROPIC_MAX_OUTPUT_TOKENS=${ANTHROPIC_MAX_OUTPUT_TOKENS}
- APIFY_API_TOKEN=${APIFY_API_TOKEN}
- APIFY_ACTOR_TIKTOK=${APIFY_ACTOR_TIKTOK}
- APIFY_ACTOR_INSTAGRAM=${APIFY_ACTOR_INSTAGRAM}
- APIFY_CACHE_TTL_HOURS=${APIFY_CACHE_TTL_HOURS}
- APIFY_CAP_CENTS_PER_REPORT=${APIFY_CAP_CENTS_PER_REPORT}
- REPORT_MAX_HTML_BYTES=${REPORT_MAX_HTML_BYTES}
- WORKER_CONCURRENCY=${WORKER_CONCURRENCY:-2}
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
minio:
condition: service_healthy
restart: unless-stopped
volumes:
pgdata:
redis-data:
minio-data: