Files
backend/docker-compose.prod.yml
34047007@qq.com 036494ae35
CI / backend (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
chore: add Gitea service to docker-compose, fix gitignore
- Gitea (postgres-backed) on ports 3000/2222
- Exclude .claude/ dir and *.db from git
- Update CLAUDE.md with Gitea remote info
2026-07-27 08:13:53 +08:00

292 lines
7.6 KiB
YAML
Raw Permalink 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"
gitea:
image: gitea/gitea:latest-rootless
restart: unless-stopped
networks:
- scilit
volumes:
- gitea_data:/var/lib/gitea
environment:
GITEA__database__DB_TYPE: postgres
GITEA__database__HOST: postgres:5432
GITEA__database__NAME: gitea
GITEA__database__USER: gitea
GITEA__database__PASSWD: gitea_pass_2026
GITEA__server__DOMAIN: 123.207.9.209
GITEA__server__HTTP_PORT: 3000
GITEA__server__ROOT_URL: http://123.207.9.209:3000
GITEA__server__START_SSH_SERVER: "true"
GITEA__server__SSH_DOMAIN: 123.207.9.209
GITEA__server__SSH_PORT: 2222
GITEA__server__SSH_LISTEN_PORT: 22
ports:
- "3000:3000"
- "2222:22"
volumes:
pgdata:
redisdata:
esdata:
miniodata:
gitea_data: