Files
backend/docker-compose.prod.yml
T
34047007@qq.com a6cd99a4ca
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
feat: initial commit - oncology literature search platform
OncoLit: a multi-tenant oncology literature search, feed, and
collaboration platform. Built with FastAPI + Vue 3 + PostgreSQL.
Includes PubMed pipeline, drug approvals, AI summaries, and
systematic review tools.
2026-07-27 07:59:18 +08:00

267 lines
6.9 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SciLit 生产环境 Docker Compose
#
# 使用方式:
# cp .env.example .env # 填入实际值
# docker compose -f docker-compose.prod.yml --env-file .env up -d
#
# HTTPS 终止建议使用上游反向代理(Caddy / Nginx / ALB),
# 前端 Nginx 容器本身仅提供 HTTP 服务。
version: "3.9"
networks:
scilit:
driver: bridge
services:
postgres:
image: pgvector/pgvector:pg16
networks:
- scilit
environment:
POSTGRES_DB: scilit
POSTGRES_USER: scilit
POSTGRES_PASSWORD: ${PG_PASSWORD}
ports: []
volumes:
- pgdata:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U scilit"]
interval: 10s
timeout: 5s
retries: 5
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
redis:
image: redis:7-alpine
networks:
- scilit
command: redis-server --requirepass ${REDIS_PASSWORD}
ports: []
volumes:
- redisdata:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
retries: 5
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
elasticsearch:
image: elasticsearch:8.11.0
networks:
- scilit
environment:
discovery.type: single-node
xpack.security.enabled: "false"
"ES_JAVA_OPTS": "-Xms1g -Xmx1g"
bootstrap.memory_lock: "true"
ports: []
volumes:
- esdata:/usr/share/elasticsearch/data
restart: unless-stopped
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test: ["CMD-SHELL", "curl -s http://localhost:9200/_cluster/health | grep -qE 'green|yellow'"]
interval: 15s
timeout: 10s
retries: 5
start_period: 30s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
minio:
image: minio/minio:latest
command: server /data --console-address ":9001"
networks:
- scilit
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-minioadmin}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-minioadmin}
ports: []
volumes:
- miniodata:/data
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:9000/minio/health/live || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 10s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
migrate:
build: ./backend
networks:
- scilit
command: alembic -c alembic/alembic.ini upgrade head
environment:
DATABASE_URL: postgresql+asyncpg://scilit:${PG_PASSWORD}@postgres:5432/scilit
JWT_SECRET: ${JWT_SECRET}
SPECIALTY: ${SPECIALTY:-oncology}
DEBUG: "false"
depends_on:
postgres:
condition: service_healthy
restart: "no"
backend:
build: ./backend
networks:
- scilit
# ENTRYPOINT 自动执行迁移,CMD 启动 uvicorn4 workers + proxy-headers
# 无需额外 command
environment:
DATABASE_URL: postgresql+asyncpg://scilit:${PG_PASSWORD}@postgres:5432/scilit
REDIS_URL: redis://default:${REDIS_PASSWORD}@redis:6379
ES_URL: http://elasticsearch:9200
S3_ENDPOINT: ${S3_ENDPOINT}
S3_ACCESS_KEY: ${S3_ACCESS_KEY}
S3_SECRET_KEY: ${S3_SECRET_KEY}
S3_BUCKET: ${S3_BUCKET:-scilit-files}
COS_SECRET_ID: ${COS_SECRET_ID:-}
COS_SECRET_KEY: ${COS_SECRET_KEY:-}
COS_REGION: ${COS_REGION:-ap-guangzhou}
COS_BUCKET: ${COS_BUCKET:-scilit-files}
JWT_SECRET: ${JWT_SECRET}
SPECIALTY: ${SPECIALTY:-oncology}
DEBUG: "false"
SMTP_HOST: ${SMTP_HOST}
SMTP_PORT: ${SMTP_PORT:-587}
SMTP_USER: ${SMTP_USER}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_FROM: ${SMTP_FROM}
SENTRY_DSN: ${SENTRY_DSN}
AI_API_KEY: ${AI_API_KEY}
AI_BASE_URL: ${AI_BASE_URL}
AI_MODEL: ${AI_MODEL}
PUBMED_API_KEY: ${PUBMED_API_KEY}
CORS_ORIGINS: ${CORS_ORIGINS}
PUBLIC_BASE_URL: ${PUBLIC_BASE_URL}
ports:
- "127.0.0.1:8000:8000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
elasticsearch:
condition: service_started
minio:
condition: service_healthy
migrate:
condition: service_completed_successfully
healthcheck:
test: ["CMD-SHELL", "curl -sf http://localhost:8000/health || exit 1"]
interval: 15s
timeout: 5s
retries: 3
start_period: 20s
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
worker:
build: ./backend
networks:
- scilit
# 通过 CMD 覆写默认的 uvicorn 启动,改为 ARQ worker(异步任务消费)
# 迁移由独立的 migrate 服务完成(depends_on 确保顺序)
command: arq app.tasks.worker.WorkerSettings
healthcheck:
test: ["CMD-SHELL", "grep -q arq /proc/1/cmdline"]
interval: 30s
timeout: 5s
start_period: 30s
retries: 3
environment:
DATABASE_URL: postgresql+asyncpg://scilit:${PG_PASSWORD}@postgres:5432/scilit
REDIS_URL: redis://default:${REDIS_PASSWORD}@redis:6379
ES_URL: http://elasticsearch:9200
S3_ENDPOINT: ${S3_ENDPOINT}
S3_ACCESS_KEY: ${S3_ACCESS_KEY}
S3_SECRET_KEY: ${S3_SECRET_KEY}
S3_BUCKET: ${S3_BUCKET:-scilit-files}
COS_SECRET_ID: ${COS_SECRET_ID:-}
COS_SECRET_KEY: ${COS_SECRET_KEY:-}
COS_REGION: ${COS_REGION:-ap-guangzhou}
COS_BUCKET: ${COS_BUCKET:-scilit-files}
JWT_SECRET: ${JWT_SECRET}
SPECIALTY: ${SPECIALTY:-oncology}
DEBUG: "false"
SMTP_HOST: ${SMTP_HOST}
SMTP_PORT: ${SMTP_PORT:-587}
SMTP_USER: ${SMTP_USER}
SMTP_PASSWORD: ${SMTP_PASSWORD}
SMTP_FROM: ${SMTP_FROM}
AI_API_KEY: ${AI_API_KEY}
AI_BASE_URL: ${AI_BASE_URL}
AI_MODEL: ${AI_MODEL}
PUBMED_API_KEY: ${PUBMED_API_KEY}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
minio:
condition: service_healthy
migrate:
condition: service_completed_successfully
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.prod
networks:
- scilit
environment:
VITE_API_BASE: /api/v1
ports:
- "80:80"
volumes:
- /var/log/scilit/nginx:/var/log/nginx
depends_on:
backend:
condition: service_started
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
volumes:
pgdata:
redisdata:
esdata:
miniodata: