186 lines
6.6 KiB
YAML
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:
|