Files
OJ2/docker/compose.debian.yml
T
xuyueandClaude Opus 5.5 625bd49801
Deploy / deploy (push) Canceled after 0s
chore(部署): 服务器的数据库和 Redis 改由 OJ2 自己起,不用再改 OJDeploy 下的 compose;附一次性搬家脚本
compose.debian.yml 去掉外接形态,postgres / redis 固定由本栈起(PostgreSQL 18、Redis 8)。
docker/move-db-into-oj2.sh 把服务器上旧栈的 16 / 7 倒进来:先编镜像、确认机房已断开、
备份、恢复时剥掉 dump 里的 md5 口令(18 只认 SCRAM)、核对行数和网络登录,最后交给 deploy.sh。

生产库口令原来是默认的 onlinejudge(超级用户、5445 对公网开着),脚本要求换成强口令才执行。

本机按线上「之前」的状态完整演练过:停机到恢复 36 秒,行数一致,登录态保住,提交照常判题。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 21:10:09 +08:00

164 lines
6.4 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.
# 服务器(oj.xuyue.cc)。数据库在这里,机房那套连的就是这里的 5445。
#
# docker/deploy.sh # 平时走这个(自检 → 构建 → 迁移 → 起栈 → 冒烟)
#
# 构建上下文是仓库根,所以 build.context 写 ..(相对本文件)。
#
# **服务器上的全部容器都由这一个文件起**,包括 postgres 和 redis。以前库和 redis 是旧栈
# 那份 /root/OJDeploy/docker-compose.yml 起的、这里通过 DB_HOST 外接过去,升级它们就得去
# 改那份文件;2026-10 起收了进来(搬家用 docker/move-db-into-oj2.sh,一次性的)。
#
# ⚠️ `DATA_DIR` 默认值 `../data` 解析出来是 **`OJ2/data`**,不是部署目录的 `data/`。
# 不设它的话 postgres 会在空目录上初始化一个全新的空库,测试点和题面图片也全都不在,
# 而且**不报错**。`deploy.sh` 为此专门设了自检。
services:
oj-postgres:
image: postgres:18-alpine
container_name: oj-postgres
restart: always
# 18 起镜像的数据目录是 /var/lib/postgresql/18/docker,挂载点要是上一级,
# 还挂 .../data 的话 18 直接拒绝启动。宿主机目录叫 `postgresql/`,和旧栈 16 的
# `postgres/` 分开:18 读不了 16 的目录,分开放才留得住老库做回退
volumes:
- ${DATA_DIR:-../data}/postgresql:/var/lib/postgresql
environment:
POSTGRES_DB: onlinejudge
POSTGRES_USER: onlinejudge
# 只在空目录上初始化时用一次,之后改它不会改库里的口令(要 ALTER ROLE)。
# 这个账号是超级用户、端口又对公网开着,必须是 openssl rand -hex 32 那种强口令
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?请在 docker/.env 里设置 POSTGRES_PASSWORD}
# 机房那套要连这个端口,必须对外暴露
ports:
- "5445:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U onlinejudge -d onlinejudge"]
interval: 5s
timeout: 3s
retries: 10
oj-redis:
image: redis:8-alpine
container_name: oj-redis
restart: always
# 会话存在这里:谁能连上它,谁就能写一条 session:<token> 冒充超管。所以必须带密码,
# 端口也只发布在本机(api / worker 走 compose 网络连 oj-redis,用不着宿主机端口)。
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD:?}"]
environment:
# redis-cli 认这个变量,healthcheck 和 docker exec 进来的 redis-cli 都不用再带 -a
REDISCLI_AUTH: ${REDIS_PASSWORD:?}
volumes:
- ${DATA_DIR:-../data}/redis:/data
ports:
- "127.0.0.1:5446:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
oj-judge:
# 自己构建的判题沙箱(上游 JudgeServer 1.6.1 + 新工具链,见 docker/judge/)。
# 上游停更在 2024-04,registry 上的 1.6.1 == latest,没有新版可拉。
# ⚠️ 这个 tag 不在任何 registry 上:本机 docker/judge/build.sh 构建,
# 服务器/机房用 docker load 装。镜像不在本地时 compose 会去 pull 然后报找不到。
image: oj2-judge-2
container_name: oj-judge
restart: always
read_only: true
cap_drop:
- SETPCAP
- MKNOD
- NET_BIND_SERVICE
- SYS_CHROOT
- SETFCAP
- FSETID
tmpfs:
- /tmp
volumes:
- ${DATA_DIR:-../data}/backend/test_case:/test_case:ro
# 判题机的运行状态目录。默认跟着 DATA_DIR 走,和旧栈是同一份 ——
# 一次性切换时无所谓(旧判题机已经停了),但**并行试跑时必须单独设 JUDGE_STATE_DIR**,
# 否则新旧两个 judger 同时往一个 run/log 目录里写。
- ${JUDGE_STATE_DIR:-${DATA_DIR:-../data}/judge_server}/log:/log
- ${JUDGE_STATE_DIR:-${DATA_DIR:-../data}/judge_server}/run:/judger
environment:
SERVICE_URL: http://oj-judge:8080
# 心跳路径跟着新后端改了:judge_server_heartbeat/ → judge-server/heartbeat
BACKEND_URL: http://oj-api:3000/api/judge-server/heartbeat
TOKEN: ${OJ2_JUDGE_TOKEN:?请在 docker/.env 里设置 OJ2_JUDGE_TOKEN}
mem_limit: 512m
oj-api:
build: &build
context: ..
dockerfile: docker/Dockerfile
target: api
# 产物来源,见 docker/Dockerfile 顶部。默认 build(服务器自己编);
# CI 传 ARTIFACTS=prebuilt 用 runner 编好的产物。
args:
ARTIFACTS: ${ARTIFACTS:-build}
image: oj2-api:latest
container_name: oj-api
restart: always
depends_on:
oj-postgres:
condition: service_healthy
oj-redis:
condition: service_healthy
volumes:
- ${DATA_DIR:-../data}/backend:/data
environment: &api-env
DATABASE_URL: postgres://onlinejudge:${POSTGRES_PASSWORD:?}@oj-postgres:5432/onlinejudge
# 密码拼进 URL,所以只能用 URL 安全的字符 —— 用 openssl rand -hex 32 生成
REDIS_URL: redis://:${REDIS_PASSWORD:?请在 docker/.env 里设置 REDIS_PASSWORD}@oj-redis:6379
JUDGE_SERVER_URL: http://oj-judge:8080
JUDGE_SERVER_TOKEN: ${OJ2_JUDGE_TOKEN:?}
JUDGE_CONCURRENCY: ${JUDGE_CONCURRENCY:-2}
TRIAL_CONCURRENCY: ${TRIAL_CONCURRENCY:-2}
AI_KEY: ${AI_KEY:-}
AI_HINT_DIAGNOSE: ${AI_HINT_DIAGNOSE:-}
# 走 NPM 终止 TLS,浏览器侧是 https,Cookie 必须带 Secure
COOKIE_SECURE: "true"
healthcheck:
test: ["CMD", "oj2-api", "healthcheck"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
mem_limit: 512m
oj-worker:
build: *build
image: oj2-api:latest
container_name: oj-worker
restart: always
depends_on:
- oj-api
volumes:
- ${DATA_DIR:-../data}/backend:/data
environment: *api-env
# 同一个镜像,换个子命令就是判题消费者
command: ["oj2-api", "worker"]
mem_limit: 512m
oj-web:
build:
context: ..
dockerfile: docker/Dockerfile
target: web
args:
ARTIFACTS: ${ARTIFACTS:-build}
image: oj2-web:latest
container_name: oj-web
restart: always
depends_on:
- oj-api
volumes:
# Caddy 只往这里写访问日志,静态资源在镜像里
- ${DATA_DIR:-../data}/backend/log:/data/log
ports:
# 并行试跑(oj2.xuyue.cc)时换一个端口,8080 还被旧 backend 占着。
- "0.0.0.0:${WEB_PORT:-8080}:8000"
mem_limit: 256m