Files
OJ2/docker/compose.debian.yml
yuetsh dd6a6a04eb
Some checks failed
Deploy / deploy (push) Has been cancelled
refactor(密码): 删掉 PASSWORD_HASH_UPGRADE,无条件写 argon2
上一个 commit 把五个写入点收进 hashPassword,顺手把开关默认值翻成了 true 并
留下 false 分支当退路。这个退路是假的,删掉。

**开关只能拦住将来,修不了已经发生的。** 等真到了要把旧站拉回来的那天,活跃
账号早就都被登录/重置密码升成 argon2 了,这时候设 `=false` 一个也救不回来。
正经退路是切换手册「万一已经改坏了」那节的脚本 —— 拿 `raw_password` 重算
Django 的 `make_password`,能修已经变成 argon2 的账号。留着一个永远轮不到它
上场的开关,只是给后来人多一件要读懂的东西。

删掉的:`config.passwordHashUpgrade`、`hashDjangoPbkdf2` 和它那套 Django 参数
(1200000 迭代 / 22 位 salt / RANDOM_STRING_CHARS)、两个 compose 里的
`PASSWORD_HASH_UPGRADE` env。auth.ts 的登录升级变成无条件。

保留的:

- `hashPassword()` —— 虽然现在只是一行 argon2,但「只有一个地方写密码」正是上
  一个 commit 的重点。五处各写各的才是当初那个 bug 的根。
- `verifyPassword` 的 **pbkdf2 分支** —— 生产库 1710 个账号全是 Django 写的
  pbkdf2(迭代次数 120000~1200000),只会在各自下次登录时才迁移。删了就是
  全站登不上。代码注释里写死了这句话。
- 切换手册里的 `raw_password` 恢复脚本,以及回滚流程里新加的「密码要额外处理」
  那一步。

## 验证

改完重跑了一遍关键路径(临时造一个 Django 生成的 120000 迭代老哈希):

- 存量账号登录 200 → 哈希变成 argon2 → 再登 200 → 错密码 401
- 后台重置密码 → argon2 → 新密码能登录
- 注册 → argon2 → 能登录

tsc(apps/api) 0 error、check:routes 168 条无遮蔽、vue-tsc 0 error、build 通过、
两个 compose `config -q` 通过。测试用户已删干净。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 23:50:55 -06:00

183 lines
7.1 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.
# 服务器xuyue.cc。数据库在这里机房那套连的就是这里的 5445。
#
# docker compose -f docker/compose.debian.yml --env-file docker/.env up -d --build
#
# 构建上下文是仓库根,所以 build.context 写 ..(相对本文件)。
#
# 和旧的 docker-compose.debian.yml 的对应关系:
# oj-backendsupervisord 跑 caddy+gunicorn+dramatiq→ 拆成 oj-web + oj-api + oj-worker
# 端口、数据目录、判题机配置全部保持不变,这样回滚只是换回旧 compose。
#
# ## 两种形态
#
# **自带数据**演练用的就是这个postgres 和 redis 也由本文件起,要显式加 profile。
#
# docker compose -f docker/compose.debian.yml --env-file docker/.env --profile local-data up -d
#
# **只换前后端**(默认,上线用这个):旧栈的 postgres / redis 容器继续跑,
# 这里只起 api / worker / web / judge
# 通过 env 指过去。切换当天数据库进程根本不重启,库和文件都不用挪位置。
#
# docker compose -f docker/compose.debian.yml --env-file docker/.env up -d
#
# 后者要在 env 里设 `DB_HOST` / `REDIS_HOST` / `DATA_DIR`,见 `.env.example` 末尾。
#
# **并行试跑**(新站挂在 oj2.xuyue.cc、旧站原样不动是「只换前后端」再加两个变量
# `WEB_PORT`8080 被旧 backend 占着)和 `JUDGE_STATE_DIR`(两个判题机不能共用运行目录)。
# 这种形态下旧栈一个容器都不用停。见手册第四节。
#
# ⚠️ `DATA_DIR` 默认值 `../data` 解析出来是 **`OJ2/data`**,不是部署目录的 `data/`。
# 旧栈用的是 `<部署目录>/data/`,两者不是一个地方 —— 直接用默认值切过去postgres 会在
# 空目录上初始化一个全新的空库,测试点和题面图片也全都不在。**用旧数据就必须设 `DATA_DIR`。**
services:
oj-postgres:
image: postgres:16-alpine
container_name: oj-postgres
restart: always
# 只在「自带数据」形态下启动。用旧栈的库时不启动它 —— 否则 5445 端口会和
# 旧的 postgres 撞,而且两个进程开同一个数据目录本来也起不来。
profiles: ["local-data"]
volumes:
- ${DATA_DIR:-../data}/postgres:/var/lib/postgresql/data
environment:
POSTGRES_DB: onlinejudge
POSTGRES_USER: onlinejudge
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:7-alpine
container_name: oj-redis
restart: always
# 同上:旧栈的 redis 也发布了 5446两个一起跑会撞端口。
# redis 里没有非丢不可的东西(会话、判题队列),用旧的那个也无所谓 ——
# 旧后端已经停了,新后端独占它,剩下的 Django / dramatiq 残留键前缀不同,互不干扰。
profiles: ["local-data"]
volumes:
- ${DATA_DIR:-../data}/redis:/data
ports:
- "5446:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
oj-judge:
image: registry.cn-hongkong.aliyuncs.com/oj-image/judge:1.6.1
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:
# required: false —— 「只换前后端」时这两个服务不在启动集合里profile 未启用),
# 严格的 depends_on 会让整个 project 直接判定 invalid实测过不是猜的
# 代价:自带数据形态下 postgres 起不来时compose 只警告不中止oj-api 照样起,
# 然后自己 crash 循环。看 `docker compose ps`oj-api 会是 unhealthy。
oj-postgres:
condition: service_healthy
required: false
oj-redis:
condition: service_healthy
required: false
# 用旧栈的库时,库在宿主机上(旧 postgres 发布了 5445走 host-gateway 过去,
# 不出本机、不走公网。DB_HOST 填 host.docker.internal 即可。
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ${DATA_DIR:-../data}/backend:/data
environment: &api-env
DATABASE_URL: postgres://onlinejudge:${POSTGRES_PASSWORD:?}@${DB_HOST:-oj-postgres}:${DB_PORT:-5432}/onlinejudge
REDIS_URL: redis://${REDIS_HOST:-oj-redis}:${REDIS_PORT:-6379}
JUDGE_SERVER_URL: http://oj-judge:8080
JUDGE_SERVER_TOKEN: ${OJ2_JUDGE_TOKEN:?}
JUDGE_CONCURRENCY: ${JUDGE_CONCURRENCY:-2}
AI_KEY: ${AI_KEY:-}
# 走 NPM 终止 TLS浏览器侧是 httpsCookie 必须带 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
extra_hosts:
- "host.docker.internal:host-gateway"
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