|
1 | | -FROM klakegg/hugo:ext-alpine |
| 1 | +# Build image for the static site. |
| 2 | +# |
| 3 | +# docker build -t vfb-static-builder . |
| 4 | +# docker run --rm -v "$PWD:/src" -v vfb_cache:/tmp vfb-static-builder |
| 5 | +# |
| 6 | +# Pinned to Hugo 0.122.0 rather than the newest release. That is a deliberate |
| 7 | +# step backwards and the reason is measured, not suspected. |
| 8 | +# |
| 9 | +# The content tree is ~763k generated term pages, ~650k of them in a single |
| 10 | +# directory (content/en/blog/ontologies/vfb), reached over NFSv3 from a Synology |
| 11 | +# volume whose btrfs metadata sits on RAID5 spinning disks. Measured on that |
| 12 | +# volume: plain readdir runs at 5-29k entries/s, but readdir+stat runs at |
| 13 | +# 253/s — ~4ms per inode, a disk seek, nothing cached. NFSv3 uses READDIRPLUS, |
| 14 | +# so the server stats every entry it enumerates. Per-page filesystem cost is |
| 15 | +# therefore the dominant term in this build, far above template or render cost. |
| 16 | +# |
| 17 | +# Hugo's per-page filesystem cost rose at v0.123.0, which rewrote page assembly. |
| 18 | +# Counted with strace over an identical 25k-page corpus on local disk: |
| 19 | +# |
| 20 | +# 0.122.0 75,658 openat 76,997 newfstatat 3.06 stat/page |
| 21 | +# 0.128.0 100,788 openat 101,527 newfstatat 4.04 stat/page |
| 22 | +# 0.140.2 100,813 openat 101,485 newfstatat 4.03 stat/page |
| 23 | +# 0.164.0 100,844 openat 101,488 newfstatat 4.03 stat/page |
| 24 | +# |
| 25 | +# Flat from 0.128 onward, so this is one regression at 0.123, not a drift. At |
| 26 | +# 763k pages and 253 stat/s that extra stat per page is ~49 min on top of a |
| 27 | +# build already costing ~2.6h of pure metadata I/O. |
| 28 | +# |
| 29 | +# 0.122.0 is the last version known to complete this build: the live term pages |
| 30 | +# carry `generator: Hugo 0.122.0` and were written 2026-08-05 17:59. No 0.16x |
| 31 | +# build has ever finished — each ran 17h+ with one thread in uninterruptible |
| 32 | +# sleep on the vfb/ directory and not a single page written. |
| 33 | +# |
| 34 | +# This pin is a workaround. The fix is to stop holding 650k files in one |
| 35 | +# directory (shard vfbterms.py's output) and to pin the volume's btrfs metadata |
| 36 | +# to its SSD cache. When either lands, raise HUGO_VERSION — it is an ARG so that |
| 37 | +# is a one-line change. |
| 38 | +# |
| 39 | +# Debian rather than Alpine, and the tarball rather than ghcr.io/gohugoio/hugo: |
| 40 | +# that registry has no v0.122.0 tag (it begins around v0.140), and the extended |
| 41 | +# release binary is glibc-linked — `ldd` gives /lib64/ld-linux-x86-64.so.2 plus |
| 42 | +# libstdc++.so.6 — so musl with gcompat is not a safe host for it. |
| 43 | +# |
| 44 | +# Extended edition, matching the rcourt/docsy-builder:Feb2023 that produced the |
| 45 | +# last good site. The theme ships plain CSS and needs no Sass, so the standard |
| 46 | +# edition would also serve and is statically linked; keeping extended here |
| 47 | +# changes one variable at a time relative to the last build known to work. |
| 48 | +# |
| 49 | +# The theme declares min_version 0.128.0 for `[pagination] pagerSize`, so 0.122 |
| 50 | +# emits one WARN and falls back to 10 items per page. Nothing on the site |
| 51 | +# paginates today, so that is latent rather than active. |
| 52 | +FROM debian:bookworm-slim |
2 | 53 |
|
3 | | -RUN apk add git && \ |
4 | | - git config --global --add safe.directory /src |
| 54 | +ARG HUGO_VERSION=0.122.0 |
| 55 | + |
| 56 | +# bash and find are already in the base image. rsync is for deploy.sh, which |
| 57 | +# stages the build and syncs it into the served directory rather than writing |
| 58 | +# there directly. libstdc++6 is what the extended Hugo binary links against. |
| 59 | +RUN apt-get update \ |
| 60 | + && apt-get install -y --no-install-recommends rsync ca-certificates libstdc++6 \ |
| 61 | + && rm -rf /var/lib/apt/lists/* |
| 62 | + |
| 63 | +ADD https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz /tmp/hugo.tgz |
| 64 | +RUN tar xzf /tmp/hugo.tgz -C /usr/local/bin hugo \ |
| 65 | + && rm -f /tmp/hugo.tgz \ |
| 66 | + && hugo version |
| 67 | + |
| 68 | +# Deliberately root. The published tree on the NFS volume is owned by root from |
| 69 | +# the klakegg-era builds, so an unprivileged rsync could not overwrite it. |
| 70 | +USER root |
| 71 | + |
| 72 | +# deploy.sh uses ${HUGO_CACHEDIR:-/tmp/hugo_cache}, so this must be set |
| 73 | +# explicitly: Rancher mounts the workspace at /src and the cache volume at /tmp. |
| 74 | +ENV HUGO_CACHEDIR=/tmp/hugo_cache |
| 75 | +WORKDIR /src |
| 76 | + |
| 77 | +ENTRYPOINT [] |
| 78 | +CMD ["/bin/bash", "/src/deploy.sh"] |
0 commit comments