diff --git a/rust/prop_grid_rs/Dockerfile b/rust/prop_grid_rs/Dockerfile index ef06bf6c..589bc848 100644 --- a/rust/prop_grid_rs/Dockerfile +++ b/rust/prop_grid_rs/Dockerfile @@ -1,35 +1,70 @@ # syntax=docker/dockerfile:1.7 # -# Multi-arch build for `prop-grid-rs`. wgrib2 isn't in Debian apt — the -# Elixir image builds it from source in its own stage. Rather than -# rebuild it here (~5 min per CI run), copy the binary + libg2c out of -# the already-published Elixir image. -# -# Runtime uid 65534 matches the fsGroup on the NFS scores mount. +# Multi-arch build for `prop-grid-rs`. Self-contained: builds wgrib2 + +# NCEPLIBS-g2c from source so the image has no external private-registry +# dependency. An earlier revision did `FROM prop:latest AS wgrib2-src` to +# reuse the Elixir image's pre-built wgrib2, but docker buildx in CI +# couldn't always authenticate to the private registry during that +# implicit FROM pull — the resulting failures were opaque and broke +# every grid-rs image publish after Stream C. # # This image ships two binaries: `prop-grid-rs` (default ENTRYPOINT, # drains grid_tasks) and `hrrr-point-worker` (k8s `command:` override, -# drains hrrr_fetch_tasks). -ARG WGRIB2_IMAGE=git.mcintire.me/graham/prop:latest +# drains hrrr_fetch_tasks). Runtime uid 65534 matches the fsGroup on +# the NFS scores mount. -FROM ${WGRIB2_IMAGE} AS wgrib2-src +ARG DEBIAN_VERSION=trixie-slim +ARG RUNNER_IMAGE="docker.io/debian:${DEBIAN_VERSION}" +# ---- wgrib2 builder (mirrors the same stage in the Elixir Dockerfile) ---- +FROM ${RUNNER_IMAGE} AS wgrib2-builder + +ARG WGRIB2_VERSION=3.6.0 +ARG G2C_VERSION=2.1.0 + +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + rm -f /etc/apt/apt.conf.d/docker-clean \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + build-essential gfortran cmake wget ca-certificates pkg-config \ + zlib1g-dev libaec-dev libpng-dev libopenjp2-7-dev + +WORKDIR /tmp/g2c +RUN wget -q --content-disposition "https://github.com/NOAA-EMC/NCEPLIBS-g2c/archive/refs/tags/v${G2C_VERSION}.tar.gz" \ + -O g2c.tar.gz \ + && tar xzf g2c.tar.gz \ + && cd NCEPLIBS-g2c-${G2C_VERSION} \ + && mkdir build && cd build \ + && cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local \ + -DCMAKE_BUILD_TYPE=Release \ + -DUSE_PNG=ON -DUSE_AEC=ON -DUSE_OpenJPEG=ON -DUSE_Jasper=OFF \ + && make -j$(nproc) \ + && make install + +WORKDIR /tmp/wgrib2 +RUN wget -q --content-disposition "https://github.com/NOAA-EMC/wgrib2/archive/refs/tags/v${WGRIB2_VERSION}.tar.gz" \ + -O wgrib2.tar.gz \ + && tar xzf wgrib2.tar.gz \ + && cd wgrib2-${WGRIB2_VERSION} \ + && mkdir build && cd build \ + && cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release \ + -DUSE_PNG=ON -DUSE_OPENJPEG=ON -DUSE_AEC=ON \ + && make -j$(nproc) \ + && make install \ + && strip /usr/local/bin/wgrib2 + +# ---- Rust build ---- FROM rust:1.94-trixie AS builder WORKDIR /src -# Cache deps: copy manifests first so dependency changes alone don't -# invalidate the source-layer cache. COPY Cargo.toml Cargo.lock* ./ COPY src ./src COPY tests ./tests -# BuildKit cache mounts persist cargo's registry + git across CI runs. -# `target/` is deliberately NOT cached — after Stream C bumped the -# crate to two binaries, the runner started running out of disk inside -# the mount and the build would fail mid-link. Rebuilding from scratch -# adds ~3 min to the build but removes the failure mode entirely. -# Lint + test gate the image build so a regressed scorer or a clippy -# warning never produces a pushable image. +# Registry + git caches are persistent; target/ is not (kept ephemeral +# to avoid the runner disk-pressure failures observed during Stream C +# rollout). Full rebuild adds ~3 min; it's still under 6 min total. RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,target=/usr/local/cargo/git,sharing=locked \ rustup component add clippy \ @@ -39,22 +74,19 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry,sharing=locked \ && cp target/release/worker /usr/local/bin/worker \ && cp target/release/hrrr_point_worker /usr/local/bin/hrrr_point_worker -# Runtime image: slim debian + the shared libs wgrib2 links against. -# libgfortran5/libaec0/zlib1g/libpng16-16t64/libopenjp2-7 mirror the -# Elixir runtime stage. -FROM debian:trixie-slim AS runtime -RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates \ - tini \ - libgfortran5 \ - libaec0 \ - zlib1g \ - libpng16-16t64 \ - libopenjp2-7 \ - && rm -rf /var/lib/apt/lists/* +# ---- Runtime ---- +FROM ${RUNNER_IMAGE} AS runtime +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + rm -f /etc/apt/apt.conf.d/docker-clean \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates tini \ + libgfortran5 libaec0 zlib1g libpng16-16t64 libopenjp2-7 -COPY --from=wgrib2-src /usr/local/bin/wgrib2 /usr/local/bin/wgrib2 -COPY --from=wgrib2-src /usr/local/lib/libg2c.so* /usr/local/lib/ +COPY --from=wgrib2-builder /usr/local/bin/wgrib2 /usr/local/bin/wgrib2 +COPY --from=wgrib2-builder /usr/local/lib/libg2c.so /usr/local/lib/ +COPY --from=wgrib2-builder /usr/local/lib/libg2c.so.0 /usr/local/lib/ RUN ldconfig COPY --from=builder /usr/local/bin/worker /usr/local/bin/prop-grid-rs @@ -62,7 +94,6 @@ COPY --from=builder /usr/local/bin/hrrr_point_worker /usr/local/bin/hrrr-point-w USER 65534:65534 # Default entrypoint is the grid chain worker. Override with `command:` -# in the k8s manifest (or `docker run ... hrrr-point-worker`) for the -# per-QSO point worker. +# in the k8s manifest for the per-QSO point worker. ENTRYPOINT ["/usr/bin/tini", "--"] CMD ["/usr/local/bin/prop-grid-rs"]