Deploy / deploy (push) Waiting to run
上游 QingdaoU/JudgeServer 停更在 2024-04(registry 上的 latest 和 1.6.1 是同一份 镜像,编译器停在 gcc-13),没有新版可拉,所以自己重编。docker/judge/ 是只改工具链 的 Dockerfile 分叉,server/ 和 Judger/ 从上游固定 commit b28aa56 拉,一行没动。 镜像 oj2-judge-2(不在任何 registry 上:本机 build.sh --save → scp → docker load) - gcc/g++ 13 → 14.2,Python 3.12 → 3.13.5,都是 trixie 默认 - Go / JDK / Node 整套删掉:前端的题目语言复选框从来只给 C / C++ / Python / SQL, 12 万条提交里 Java 44 条、Golang 15、JavaScript 3,全是很早以前的 - 体积 1.1GB → 433MB;默认走清华源,构建 12 分钟 → 40 秒(--no-mirror 换回官方) - deploy.sh 加一道自检:镜像不在本机就中止,并打印该跑的三条命令 C 的编译参数加三个 -Wno-error(implicit-function-declaration / int-conversion / incompatible-pointer-types):gcc-14 把它们从 warning 提成了 error,而 -w 压不住。 语言值统一成 Python(迁移 0019 / 0020) - 0019:Python3(104527 条提交)与 Python2(3 条)并成 Python,一并改掉 937 道题的 languages、75 个 template 键、15 个 ast_rules 键、257 条 answers、1235 个用户的 成就指标 _languages(languages_used 重算,总和 1928 → 1925,少的 3 个是同时用过 两种 Python 的人) - 0020:把 Java / JavaScript / Golang 从 84 道题的可选语言里摘掉 —— 不摘的话那些题 的语言下拉还能选 Java,提交必 SYSTEM_ERROR - 契约新增 normalizeLanguage() 别名表,判题侧一律走 judgeConfigFor():旧客户端 localStorage 里的 Python3、迁移前排进队列的任务都还能判;协作的语言归一也走它, 否则上线那一刻学生页面里的 Python3 会静默落到 C - 回滚要连数据一起回,只滚代码会让所有 Python 提交变 SYSTEM_ERROR 实跑 - 判题冒烟 docker/judge/smoke.ts 13 条全过:三种语言、六种状态码、gcc 宽松度 - 拿备份里的真实代码逐文件比对新旧镜像的编译结果,0 差异:C 提交 1951 份 (1725 过 / 226 CE)、C++ 882 份、Python 2000 份、20 篇 C 教程的 93 个代码块。 不加那三个 -Wno-error 的话,C 有 26 份会从能过变成 CE - 迁移在灌了 12.4 万行真实数据的一次性库里跑过:0 残留、没有题目被清空; dev 库用真正的执行器跑通 - check:ast 56 个 target 全过,前后端 typecheck 均 0 顺带记下一个升级之前就有的坑(现在随 Go 一起消失,写在 README 里):GOCACHE 指向 容器的 tmpfs,判题机重启后第一次 Go 提交是冷构建,Go 1.22 要 5.6 秒 CPU、超过 3 秒 的编译预算,于是重启后第一个交 Go 的学生必吃一次 CE,后面的人缓存热了又都正常。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
149 lines
6.2 KiB
Docker
149 lines
6.2 KiB
Docker
# 判题沙箱镜像。**这是 QingdaoU/JudgeServer 官方 Dockerfile 的分叉**,
|
||
# 只改工具链版本,server/ 和 Judger/ 的代码一行都没动(构建时从上游仓库
|
||
# 的固定 commit 拉,见 build.sh)。
|
||
#
|
||
# 为什么要分叉:上游停更在 2024-04-05(b28aa56,也就是 1.6.1 这个 tag),
|
||
# registry 上的 `latest` 和 `1.6.1` 是同一份镜像,没有新版可升。想要新编译器
|
||
# 只能自己构建。
|
||
#
|
||
# 相对上游的全部改动:
|
||
# gcc/g++ 13 → 14 (trixie 默认)
|
||
# Python 3.12 → 3.13 (trixie 默认)
|
||
# Go / JDK / Node → **整套删掉**(见下)
|
||
#
|
||
# 只留 C / C++ / Python3 的工具链:前端的语言复选框从来只给这三种加 SQL,
|
||
# 生产库 12 万条提交里 Java/Golang/JavaScript 一共 62 条、全是很早以前的。
|
||
# 删掉 golang-1.24-go、temurin-25-jdk、nodejs 之后镜像从 1.16GB 掉到 ~500MB,
|
||
# 构建也少了 NodeSource 那个 39MB 的 deb(它没有可用的国内镜像,最慢的一块)。
|
||
# 想恢复某种语言:这里加回包 + alternatives,同时改 apps/api/src/judge/languages.ts。
|
||
#
|
||
# ⚠️ 语言的编译/运行命令**不在这个文件里**,在 apps/api/src/judge/languages.ts。
|
||
# 升 gcc 大版本要同步看那边的开关(gcc-14 把 implicit-function-declaration
|
||
# 等提成了 error,languages.ts 里有三个 -Wno-error 把它压回去)。
|
||
|
||
# 镜像源。默认走国内镜像 —— 官方源在这边实测 197 KB/s,清华 3.9 MB/s,
|
||
# 整个构建从 12 分钟掉到 2 分钟出头。出国内网络环境用 build.sh --no-mirror 关掉。
|
||
#
|
||
# ⚠️ debian 这两个只能用 **http**:改 sources 这一步发生在装 ca-certificates 之前,
|
||
# base 镜像里没有 CA 根证书,https 一律 `certificate verify failed`。
|
||
# PyPI 那条是 pip 自己请求的,pip 内置 certifi,不依赖系统 CA。
|
||
ARG APT_MIRROR=http://mirrors.tuna.tsinghua.edu.cn/debian
|
||
ARG APT_SECURITY_MIRROR=http://mirrors.tuna.tsinghua.edu.cn/debian-security
|
||
ARG PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
|
||
|
||
FROM debian:trixie-slim AS builder
|
||
ARG TARGETARCH
|
||
ARG TARGETVARIANT
|
||
ARG APT_MIRROR
|
||
ARG APT_SECURITY_MIRROR
|
||
ARG PIP_INDEX_URL
|
||
|
||
ENV DEBIAN_FRONTEND=noninteractive
|
||
WORKDIR /app
|
||
|
||
RUN --mount=type=cache,target=/var/cache/apt,id=apt-cahce-1-$TARGETARCH$TARGETVARIANT-builder,sharing=locked \
|
||
--mount=type=cache,target=/var/lib/apt,id=apt-cahce-2-$TARGETARCH$TARGETVARIANT-builder,sharing=locked \
|
||
<<EOS
|
||
set -ex
|
||
rm -f /etc/apt/apt.conf.d/docker-clean
|
||
echo 'Binary::apt::APT::Keep-Downloaded-Packages "1";' > /etc/apt/apt.conf.d/keep-cache
|
||
echo 'APT::Install-Recommends "0";' > /etc/apt/apt.conf.d/no-recommends
|
||
echo 'APT::AutoRemove::RecommendsImportant "0";' >> /etc/apt/apt.conf.d/no-recommends
|
||
# 换镜像源。debian-security 必须先换:它的 URI 以 debian 的 URI 为前缀,
|
||
# 反过来的话第二条 sed 会把它改成 <镜像>/debian-security,路径不存在。
|
||
sed -i "s|http://deb.debian.org/debian-security|$APT_SECURITY_MIRROR|; s|http://deb.debian.org/debian|$APT_MIRROR|" /etc/apt/sources.list.d/debian.sources
|
||
apt-get update
|
||
apt-get install -y libtool make cmake libseccomp-dev gcc python3 python3-venv
|
||
EOS
|
||
|
||
COPY Judger/ /app/
|
||
RUN <<EOS
|
||
set -ex
|
||
mkdir /app/build
|
||
cmake -S . -B build
|
||
cmake --build build --parallel $(nproc)
|
||
EOS
|
||
|
||
RUN <<EOS
|
||
set -ex
|
||
cd bindings/Python
|
||
python3 -m venv .venv
|
||
.venv/bin/pip3 install -i "$PIP_INDEX_URL" build
|
||
.venv/bin/python3 -m build -w
|
||
EOS
|
||
|
||
FROM debian:trixie-slim
|
||
ARG TARGETARCH
|
||
ARG TARGETVARIANT
|
||
ARG APT_MIRROR
|
||
ARG APT_SECURITY_MIRROR
|
||
ARG PIP_INDEX_URL
|
||
|
||
ENV DEBIAN_FRONTEND=noninteractive
|
||
WORKDIR /app
|
||
|
||
RUN --mount=type=cache,target=/var/cache/apt,id=apt-cahce-1-$TARGETARCH$TARGETVARIANT-final,sharing=locked \
|
||
--mount=type=cache,target=/var/lib/apt,id=apt-cahce-2-$TARGETARCH$TARGETVARIANT-final,sharing=locked \
|
||
<<EOS
|
||
set -ex
|
||
rm -f /etc/apt/apt.conf.d/docker-clean
|
||
echo 'Binary::apt::APT::Keep-Downloaded-Packages "1";' > /etc/apt/apt.conf.d/keep-cache
|
||
echo 'APT::Install-Recommends "0";' > /etc/apt/apt.conf.d/no-recommends
|
||
echo 'APT::AutoRemove::RecommendsImportant "0";' >> /etc/apt/apt.conf.d/no-recommends
|
||
needed="python3.13-minimal \
|
||
python3.13-venv \
|
||
libpython3.13-stdlib \
|
||
libpython3.13-dev \
|
||
gcc-14 \
|
||
g++-14 \
|
||
strace"
|
||
savedAptMark="$(apt-mark showmanual) $needed"
|
||
# 换镜像源。debian-security 必须先换:它的 URI 以 debian 的 URI 为前缀,
|
||
# 反过来的话第二条 sed 会把它改成 <镜像>/debian-security,路径不存在。
|
||
sed -i "s|http://deb.debian.org/debian-security|$APT_SECURITY_MIRROR|; s|http://deb.debian.org/debian|$APT_MIRROR|" /etc/apt/sources.list.d/debian.sources
|
||
apt-get update
|
||
apt-get install -y $needed
|
||
# languages.ts 里的编译/运行命令写的是绝对路径(/usr/bin/gcc、/usr/bin/python3 …),
|
||
# 全靠下面这几条 alternatives 挂出来。换包名必须同步改,漏一条的表现是 CE 而不是报错。
|
||
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 14
|
||
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 14
|
||
update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.13 13
|
||
apt-mark auto '.*' > /dev/null
|
||
apt-mark manual $savedAptMark
|
||
apt-get purge -y --auto-remove
|
||
EOS
|
||
|
||
COPY --from=builder --chmod=755 --link /app/output/libjudger.so /usr/lib/judger/libjudger.so
|
||
COPY --from=builder /app/bindings/Python/dist/ /app/
|
||
RUN --mount=type=cache,target=/root/.cache/pip,id=pip-cahce-$TARGETARCH$TARGETVARIANT-final \
|
||
<<EOS
|
||
set -ex
|
||
python3 -m venv .venv
|
||
CC=gcc .venv/bin/pip3 install -i "$PIP_INDEX_URL" --compile --no-cache-dir flask gunicorn idna psutil requests
|
||
.venv/bin/pip3 install *.whl
|
||
EOS
|
||
|
||
COPY server/ /app/
|
||
RUN <<EOS
|
||
set -ex
|
||
chmod -R u=rwX,go=rX /app/
|
||
chmod +x /app/entrypoint.sh
|
||
gcc -shared -fPIC -o unbuffer.so unbuffer.c
|
||
useradd -u 901 -r -s /sbin/nologin -M compiler
|
||
useradd -u 902 -r -s /sbin/nologin -M code
|
||
useradd -u 903 -r -s /sbin/nologin -M -G code spj
|
||
mkdir -p /usr/lib/judger
|
||
EOS
|
||
|
||
# 构建期自检:这五行任何一个不是预期版本,说明上面的包名或 alternatives 配错了。
|
||
RUN <<EOS
|
||
set -ex
|
||
gcc --version
|
||
g++ --version
|
||
python3 --version
|
||
EOS
|
||
|
||
HEALTHCHECK --interval=5s CMD [ "/app/.venv/bin/python3", "/app/service.py" ]
|
||
EXPOSE 8080
|
||
ENTRYPOINT [ "/app/entrypoint.sh" ]
|