Files
qwen-code/Dockerfile
易良 aaf523cfc4 fix(ci): probe the apt mirror so mainland E2E hosts can build the sandbox image (#16218)
* fix(ci): probe the apt mirror so mainland E2E hosts can build the sandbox image

The docker E2E leg builds the sandbox image per push under a SHA-scoped tag, so
on any host whose image store no longer holds a recent build, the two apt-get
layers are downloaded again. deb.debian.org serves the Hong Kong hosts at MB/s
and the mainland-China hosts at 11-20 kB/s, which turns that build into 2-3
hours against the job's 60-minute cap. Over the past week 97 of 127 docker legs
on the ecs-qwen-hz* hosts were cancelled this way, and the run reports
`cancelled` instead of a verdict.

Probe rather than pin a mirror or a host-name map: the build measures
deb.debian.org and two domestic mirrors, and passes --build-arg APT_MIRROR only
when the default is slower than 250 kB/s and a mirror beats it by 4x. The image
keeps deb.debian.org as its default source, so release builds, local sandbox
builds and the healthy Hong Kong hosts are unchanged, and no fleet inventory
needs to be maintained.

The probe's measurements are logged, so the next slow build can be diagnosed
from its own output.

Refs #16214

* fix(ci): require an absolutely fast mirror before overriding the apt source

The relative guard alone only asked a mirror to be 4x faster than the default,
so on a host where both endpoints were slow the mirror still "won" and moved
the host onto a source it never needed. Require 1 MB/s in absolute terms too:
below that the build is slow either way, and the extra cache key is not worth
it.

* test(ci): pin the apt-probe threshold values, not just the gate structure

The new contract test asserted the gate variables and comparisons but not
their values: mutating slow_default 10x up or fast_mirror 10x down left the
suite green while flipping the both-slow host shape onto a still-slow mirror
(review finding on #16218). Pin both literals with a word boundary — a plain
substring pin would still match the 10x-up mutation — and witness both
mutations reddening the suite before restoring the values.

* test(ci): require the mirror ARG in both Dockerfile stages

A single-match assertion survived deleting the runtime-stage ARG APT_MIRROR
(R1-1, mutation-witnessed by review): the builder declaration satisfied the
regex while the runtime apt layer silently kept the slow default. Count both
declarations instead; deleting either stage's ARG now reddens the suite.
2026-11-04 05:52:30 +08:00

105 lines
3.3 KiB
Docker

# Build stage
# Digest-pinned: integration_docker builds on the shared ECS pool, whose
# docker daemon image store persists across jobs — a co-resident job can
# retag a mutable base tag with a poisoned image, but a digest cannot be
# moved by `docker tag`. Bump the digest together with the tag.
# ratchet:docker.io/library/node:22-slim
FROM docker.io/library/node:22-slim@sha256:83f487e0a63425e5b4d146fb5e5be574bcbe1b7b843d3ebafdd95eaf7767a7e5 AS builder
# Optional apt mirror for the layer below. Empty keeps deb.debian.org, which is
# what release builds and local sandbox builds use; the E2E leg passes a
# regional mirror only on hosts where its probe found the default CDN path to be
# far slower (#16214).
ARG APT_MIRROR=
# Install build dependencies
RUN set -e; \
if [ -n "${APT_MIRROR}" ]; then \
for sources in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources; do \
if [ -f "${sources}" ]; then sed -i "s|deb.debian.org|${APT_MIRROR}|g" "${sources}"; fi; \
done; \
fi; \
apt-get update && apt-get install -y --no-install-recommends \
python3 \
make \
g++ \
git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Set up npm global package folder
RUN mkdir -p /usr/local/share/npm-global
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
ENV PATH=$PATH:/usr/local/share/npm-global/bin
# Copy source code
COPY . /home/node/app
WORKDIR /home/node/app
# Install dependencies, build workspaces, bundle into a single distributable, and pack.
# QWEN_SKIP_PREPARE=1 stops the install's prepare script from building and bundling —
# the explicit build and bundle steps below already do that.
RUN QWEN_SKIP_PREPARE=1 corepack pnpm install --frozen-lockfile --reporter=append-only \
&& npm run build \
&& npm run bundle \
&& npm run prepare:package \
&& cd dist && npm pack
# Runtime stage
# Digest-pinned for the same reason as the builder stage above.
# ratchet:docker.io/library/node:22-slim
FROM docker.io/library/node:22-slim@sha256:83f487e0a63425e5b4d146fb5e5be574bcbe1b7b843d3ebafdd95eaf7767a7e5
ARG SANDBOX_NAME="qwen-code-sandbox"
ARG CLI_VERSION_ARG
# Same optional override as the builder stage: a stage cannot inherit an ARG
# declared before its own FROM.
ARG APT_MIRROR=
ENV SANDBOX="$SANDBOX_NAME"
ENV CLI_VERSION=$CLI_VERSION_ARG
# Install runtime dependencies
RUN set -e; \
if [ -n "${APT_MIRROR}" ]; then \
for sources in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources; do \
if [ -f "${sources}" ]; then sed -i "s|deb.debian.org|${APT_MIRROR}|g" "${sources}"; fi; \
done; \
fi; \
apt-get update && apt-get install -y --no-install-recommends \
python3 \
man-db \
curl \
dnsutils \
less \
jq \
bc \
gh \
git \
unzip \
rsync \
ripgrep \
procps \
psmisc \
lsof \
socat \
ca-certificates \
fonts-dejavu-core \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Set up npm global package folder
RUN mkdir -p /usr/local/share/npm-global
ENV NPM_CONFIG_PREFIX=/usr/local/share/npm-global
ENV PATH=$PATH:/usr/local/share/npm-global/bin
# Copy bundled package from builder stage
COPY --from=builder /home/node/app/dist/*.tgz /tmp/
# Install built packages globally
RUN npm install -g /tmp/*.tgz \
&& npm cache clean --force \
&& rm -rf /tmp/*.tgz
# Default entrypoint when none specified
CMD ["qwen"]