Configure mainland build mirrors and persist BuildKit apt and pip caches

This commit is contained in:
Pigway
2026-10-07 17:37:33 +08:00
parent 1e13977ec2
commit d88c88f876
8 changed files with 83 additions and 8 deletions
+4
View File
@@ -10,3 +10,7 @@ config
*.egg-info *.egg-info
build build
dist dist
.mypy_cache
**/__pycache__
**/*.pyc
+5
View File
@@ -28,3 +28,8 @@ BUILD_TIME=unknown
# Login in the photo-source editor; only the session is saved in /config (mode 0600). # Login in the photo-source editor; only the session is saved in /config (mode 0600).
SYNOLOGY_PHOTOS_URL= SYNOLOGY_PHOTOS_URL=
SYNOLOGY_PHOTOS_CERT_SHA256= SYNOLOGY_PHOTOS_CERT_SHA256=
# Build-only mirror hosts; official defaults work outside mainland China.
# For mainland NAS builds: source ./deploy/build-cn.env before build-verify.sh.
DEBIAN_MIRROR=deb.debian.org
DEBIAN_SECURITY_MIRROR=deb.debian.org
+5 -2
View File
@@ -3,6 +3,9 @@ on: [push, pull_request, workflow_dispatch]
jobs: jobs:
verify: verify:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
DEBIAN_MIRROR: ${{ vars.DEBIAN_MIRROR }}
DEBIAN_SECURITY_MIRROR: ${{ vars.DEBIAN_SECURITY_MIRROR }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
@@ -22,8 +25,8 @@ jobs:
p=Path('.env') p=Path('.env')
p.write_text(p.read_text().replace('FRAME_FLOW_TOKEN=\n', 'FRAME_FLOW_TOKEN='+secrets.token_urlsafe(32)+'\n')) p.write_text(p.read_text().replace('FRAME_FLOW_TOKEN=\n', 'FRAME_FLOW_TOKEN='+secrets.token_urlsafe(32)+'\n'))
PY PY
docker compose config --quiet . ./deploy/build-cn.env
docker compose build --pull ./scripts/build-verify.sh
mkdir -p data/images data/generated data/cache config mkdir -p data/images data/generated data/cache config
sudo chown -R 10333:10333 data config sudo chown -R 10333:10333 data config
docker compose up -d docker compose up -d
+13 -6
View File
@@ -1,12 +1,19 @@
ARG PYTHON_BASE=python:3.14.5-slim-bookworm@sha256:ec58d916f9e24a6035cab2bdf07f6206c4cc092a16613c60597534711332d9d6 ARG PYTHON_BASE=python:3.14.5-slim-bookworm@sha256:ec58d916f9e24a6035cab2bdf07f6206c4cc092a16613c60597534711332d9d6
FROM ${PYTHON_BASE} FROM ${PYTHON_BASE}
ARG DEBIAN_MIRROR=deb.debian.org ARG DEBIAN_MIRROR=deb.debian.org
ARG DEBIAN_SECURITY_MIRROR=deb.debian.org
ARG TARGETARCH
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 TZ=Asia/Shanghai \ ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 TZ=Asia/Shanghai \
DATA_DIR=/data CONFIG_DIR=/config DATA_DIR=/data CONFIG_DIR=/config
WORKDIR /app WORKDIR /app
# CJK fonts intentionally retained for readable Chinese rendering. # CJK fonts intentionally retained for readable Chinese rendering.
RUN --mount=type=bind,source=build-cache/debs,target=/build-debs,readonly sed -i "s|http://deb.debian.org|https://${DEBIAN_MIRROR}|g" /etc/apt/sources.list.d/debian.sources \ RUN --mount=type=cache,id=frameflow-bookworm-apt-${TARGETARCH},target=/var/cache/apt,sharing=locked \
&& apt-get update \ --mount=type=cache,id=frameflow-bookworm-lists-${TARGETARCH},target=/var/lib/apt/lists,sharing=locked \
--mount=type=bind,source=build-cache/debs,target=/build-debs,readonly \
rm -f /etc/apt/apt.conf.d/docker-clean \
&& printf 'Binary::apt::APT::Keep-Downloaded-Packages "true";\n' > /etc/apt/apt.conf.d/keep-cache \
&& sed -i "s|http://deb.debian.org/debian-security|https://${DEBIAN_SECURITY_MIRROR}/debian-security|g; s|http://deb.debian.org/debian|https://${DEBIAN_MIRROR}/debian|g" /etc/apt/sources.list.d/debian.sources \
&& apt-get -o Acquire::Retries=3 -o Acquire::https::Timeout=60 update \
&& if [ -f /build-debs/fonts-noto-cjk.deb ]; then \ && if [ -f /build-debs/fonts-noto-cjk.deb ]; then \
font_version=$(apt-cache policy fonts-noto-cjk | awk '$1=="Candidate:" {print $2}'); \ font_version=$(apt-cache policy fonts-noto-cjk | awk '$1=="Candidate:" {print $2}'); \
font_sha=$(apt-cache show "fonts-noto-cjk=$font_version" | awk '$1=="SHA256:" {print $2;exit}'); \ font_sha=$(apt-cache show "fonts-noto-cjk=$font_version" | awk '$1=="SHA256:" {print $2;exit}'); \
@@ -15,16 +22,16 @@ RUN --mount=type=bind,source=build-cache/debs,target=/build-debs,readonly sed -i
apt-get install -y --no-install-recommends tzdata; \ apt-get install -y --no-install-recommends tzdata; \
dpkg -i /build-debs/fonts-noto-cjk.deb; \ dpkg -i /build-debs/fonts-noto-cjk.deb; \
else apt-get install -y --no-install-recommends fonts-noto-cjk tzdata; fi \ else apt-get install -y --no-install-recommends fonts-noto-cjk tzdata; fi \
&& rm -rf /var/lib/apt/lists/* \
&& groupadd --gid 10333 frameflow && useradd --uid 10333 --gid 10333 --no-create-home frameflow \ && groupadd --gid 10333 frameflow && useradd --uid 10333 --gid 10333 --no-create-home frameflow \
&& mkdir -p /data/images /data/generated /data/cache /config \ && mkdir -p /data/images /data/generated /data/cache /config \
&& chown -R 10333:10333 /data /config && chown -R 10333:10333 /data /config
COPY requirements.lock ./ COPY requirements.lock ./
RUN --mount=type=bind,source=build-cache/wheels,target=/build-wheels,readonly \ RUN --mount=type=cache,id=frameflow-pip-py314-${TARGETARCH},target=/root/.cache/pip,sharing=locked \
--mount=type=bind,source=build-cache/wheels,target=/build-wheels,readonly \
if [ -f /build-wheels/SHA256SUMS ]; then \ if [ -f /build-wheels/SHA256SUMS ]; then \
(cd /build-wheels && sha256sum -c SHA256SUMS) \ (cd /build-wheels && sha256sum -c SHA256SUMS) \
&& pip install --no-cache-dir --no-index --find-links=/build-wheels -r requirements.lock; \ && pip install --no-index --find-links=/build-wheels -r requirements.lock; \
else pip install --no-cache-dir -r requirements.lock; fi else pip install -r requirements.lock; fi
COPY pigway_frame_flow ./pigway_frame_flow COPY pigway_frame_flow ./pigway_frame_flow
COPY vendor ./vendor COPY vendor ./vendor
ARG BUILD_COMMIT=development ARG BUILD_COMMIT=development
+47
View File
@@ -237,3 +237,50 @@ Gallery supports read-only NAS folders and HTTPS WebDAV sources, random photo
preview, and device-bound scheduled random photos. Source definitions are persisted preview, and device-bound scheduled random photos. Source definitions are persisted
in SQLite. See [setup and limits](docs/PHOTO_SOURCES.md). in SQLite. See [setup and limits](docs/PHOTO_SOURCES.md).
NAS 本地目录需要显式只读挂载;网盘先支持通用 WebDAV,也可使用同步到 NAS 的目录。 NAS 本地目录需要显式只读挂载;网盘先支持通用 WebDAV,也可使用同步到 NAS 的目录。
### Build networking and cache
The Dockerfile retains the pinned Python base, locked Python dependencies,
`fonts-noto-cjk`, Debian repository signature checks, and offline artifact
SHA256 verification. Both production and CI use `scripts/build-verify.sh`,
which enables BuildKit and retains `docker compose build --pull`.
APT mirror hosts are configurable through `DEBIAN_MIRROR` and
`DEBIAN_SECURITY_MIRROR` (hosts only, without scheme or path). Defaults are
`deb.debian.org`; HTTPS is used for both Debian and security repositories.
For mainland-China NAS builds, use the shared profile:
```sh
. ./deploy/build-cn.env
./scripts/build-verify.sh
```
CI loads this same profile, using Tsinghua TUNA for both repositories unless
Gitea repository variables `DEBIAN_MIRROR` / `DEBIAN_SECURITY_MIRROR` override
it. Production may also set the two hosts directly in `.env` when calling the
build script without the profile. An alternate mainland mirror is
`mirrors.ustc.edu.cn`; availability and throughput depend on the Runner network.
No fallback disables signature verification or removes packages.
Layer order stays: pinned base → APT/font dependencies → `requirements.lock`
→ pip dependencies → application/vendor source → build metadata.
A source-only change therefore reuses the APT and pip layers, provided the
same builder, base digest, mirror arguments, and optional offline artifacts
are used. Changing the lockfile rebuilds pip and later layers, not APT.
Changing the mirror or APT instructions rebuilds APT and later layers.
Previously an APT layer miss redownloaded indexes/packages, and pip used
`--no-cache-dir`. Now locked BuildKit mounts retain APT indexes, downloaded
`.deb` files, and pip downloads/wheels outside the final image. Debian's
`docker-clean` hook is disabled so it cannot discard cached packages.
Re-executed APT steps still run `apt-get update` and validate repository
signatures; cached packages and pip artifacts can avoid repeat large downloads.
The initial build after this Dockerfile change will miss dependency layers;
subsequent builds benefit. No measured speedup is claimed before CI completes.
Caches belong to the Docker builder, not the ephemeral CI workspace. Keep the
NAS Runner's builder storage across jobs; removing the builder, pruning caches,
or using a fresh Docker daemon loses the benefit. Cache mounts are disposable:
an empty cache still builds correctly. `--pull` remains enabled; a pinned base
digest check alone does not invalidate dependency layers. To deliberately
refresh installed APT versions, use `docker compose build --pull --no-cache`.
+5
View File
@@ -0,0 +1,5 @@
# Shared mainland-China build profile; source this file before Compose builds.
# Nonempty environment / Gitea repository variables override these defaults.
DEBIAN_MIRROR=${DEBIAN_MIRROR:-mirrors.tuna.tsinghua.edu.cn}
DEBIAN_SECURITY_MIRROR=${DEBIAN_SECURITY_MIRROR:-mirrors.tuna.tsinghua.edu.cn}
export DEBIAN_MIRROR DEBIAN_SECURITY_MIRROR
+2
View File
@@ -7,6 +7,8 @@ services:
build: build:
context: . context: .
args: args:
DEBIAN_MIRROR: ${DEBIAN_MIRROR:-deb.debian.org}
DEBIAN_SECURITY_MIRROR: ${DEBIAN_SECURITY_MIRROR:-deb.debian.org}
BUILD_COMMIT: ${BUILD_COMMIT:-development} BUILD_COMMIT: ${BUILD_COMMIT:-development}
BUILD_TIME: ${BUILD_TIME:-unknown} BUILD_TIME: ${BUILD_TIME:-unknown}
restart: unless-stopped restart: unless-stopped
+2
View File
@@ -1,5 +1,7 @@
#!/bin/sh #!/bin/sh
set -eu set -eu
export DOCKER_BUILDKIT=1
export COMPOSE_DOCKER_CLI_BUILD=1
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
DOCKER_BIN=${DOCKER_BIN:-docker} DOCKER_BIN=${DOCKER_BIN:-docker}
"$DOCKER_BIN" info >/dev/null "$DOCKER_BIN" info >/dev/null