diff --git a/Dockerfile.railway b/Dockerfile.railway index f0b0a27..a305fd8 100644 --- a/Dockerfile.railway +++ b/Dockerfile.railway @@ -55,11 +55,52 @@ # to move in lockstep with this pin. # --------------------------------------------------------------------------- -ARG RUST_VERSION=1.98.1 +# BASE-IMAGE TAG vs TOOLCHAIN PIN — they are two different things, and only +# one of them has to exist on Docker Hub. +# +# This file previously read `ARG RUST_VERSION=1.98.1` and used it BOTH as the +# toolchain version and as the base-image tag. That build fails outright: +# +# failed to solve: docker.io/library/rust:1.98.1-slim-bookworm: not found +# +# Measured against the registry: `rust:1.98.1-slim-bookworm` is a 404, while +# `rust:1.98-slim-bookworm` and `rust:1.98.0-slim-bookworm` are both 200 — and +# `https://static.rust-lang.org/dist/channel-rust-1.98.1.toml` is a 200 too. +# So 1.98.1 IS a real Rust release; what does not exist is a docker-library +# IMAGE for that patch. The official-images repo does not tag every point +# release and lags the ones it does. A toolchain pin can therefore be valid +# while its same-numbered image tag is absent, and a Dockerfile that conflates +# them inherits an availability constraint it never meant to take on. +# +# (The failure surfaces confusingly: BuildKit resolves every stage's base in +# parallel, so the last line printed is often the HEALTHY one — +# `load metadata for docker.io/library/debian:bookworm-slim`, which resolves +# fine. Read the `failed to solve:` line, not the last `load metadata` line.) +# +# The fix separates the two concerns: +# * the base image floats on the MINOR tag, which docker-library always +# publishes; +# * the exact toolchain comes from `rust-toolchain.toml`, which rustup +# honours automatically and which is already this repo's single source of +# truth for the pin. +# +# That also closes a real gap this file had independently of the 404: +# `rust-toolchain.toml` was NEVER COPIED into the builder, so the image's +# toolchain was whatever the base tag shipped and the pin file had no effect +# here at all — precisely the cross-file drift that file was added to end. +# Copying it before the sources also means a pin bump invalidates the +# toolchain layer and nothing below it. +# +# Consequence worth stating: bumping the pin is now a ONE-line edit in +# `rust-toolchain.toml`. Touch `RUST_IMAGE_TAG` only when the MINOR moves +# (1.98 -> 1.99), and never to a patch-level tag — that is the shape that +# broke. + +ARG RUST_IMAGE_TAG=1.98-slim-bookworm ARG BIN_NAME=a2ui-paint-web # ── builder ──────────────────────────────────────────────────────────────── -FROM rust:${RUST_VERSION}-slim-bookworm AS builder +FROM rust:${RUST_IMAGE_TAG} AS builder ARG BIN_NAME # git: the OGAR / lance-graph dependencies are fetched as git deps by cargo. @@ -75,6 +116,12 @@ WORKDIR /src # Copy the manifest first so the dependency build layer caches independently of # source edits. The lock is deliberately NOT copied — see the note above the # build step. +# The pin file FIRST, on its own layer: rustup reads it and materialises the +# exact channel + components, so the toolchain in this image is the one the +# repo declares rather than whatever the base tag happens to ship. +COPY rust-toolchain.toml ./ +RUN rustup show + COPY Cargo.toml ./ COPY crates ./crates diff --git a/Dockerfile.solid.railway b/Dockerfile.solid.railway index 753b7de..23e7dcb 100644 --- a/Dockerfile.solid.railway +++ b/Dockerfile.solid.railway @@ -36,11 +36,52 @@ # workspace. Do not cite this line as evidence that something requires 1.98.1. # --------------------------------------------------------------------------- -ARG RUST_VERSION=1.98.1 +# BASE-IMAGE TAG vs TOOLCHAIN PIN — they are two different things, and only +# one of them has to exist on Docker Hub. +# +# This file previously read `ARG RUST_VERSION=1.98.1` and used it BOTH as the +# toolchain version and as the base-image tag. That build fails outright: +# +# failed to solve: docker.io/library/rust:1.98.1-slim-bookworm: not found +# +# Measured against the registry: `rust:1.98.1-slim-bookworm` is a 404, while +# `rust:1.98-slim-bookworm` and `rust:1.98.0-slim-bookworm` are both 200 — and +# `https://static.rust-lang.org/dist/channel-rust-1.98.1.toml` is a 200 too. +# So 1.98.1 IS a real Rust release; what does not exist is a docker-library +# IMAGE for that patch. The official-images repo does not tag every point +# release and lags the ones it does. A toolchain pin can therefore be valid +# while its same-numbered image tag is absent, and a Dockerfile that conflates +# them inherits an availability constraint it never meant to take on. +# +# (The failure surfaces confusingly: BuildKit resolves every stage's base in +# parallel, so the last line printed is often the HEALTHY one — +# `load metadata for docker.io/library/debian:bookworm-slim`, which resolves +# fine. Read the `failed to solve:` line, not the last `load metadata` line.) +# +# The fix separates the two concerns: +# * the base image floats on the MINOR tag, which docker-library always +# publishes; +# * the exact toolchain comes from `rust-toolchain.toml`, which rustup +# honours automatically and which is already this repo's single source of +# truth for the pin. +# +# That also closes a real gap this file had independently of the 404: +# `rust-toolchain.toml` was NEVER COPIED into the builder, so the image's +# toolchain was whatever the base tag shipped and the pin file had no effect +# here at all — precisely the cross-file drift that file was added to end. +# Copying it before the sources also means a pin bump invalidates the +# toolchain layer and nothing below it. +# +# Consequence worth stating: bumping the pin is now a ONE-line edit in +# `rust-toolchain.toml`. Touch `RUST_IMAGE_TAG` only when the MINOR moves +# (1.98 -> 1.99), and never to a patch-level tag — that is the shape that +# broke. + +ARG RUST_IMAGE_TAG=1.98-slim-bookworm ARG BIN_NAME=a2ui-solid-web # ── builder ──────────────────────────────────────────────────────────────── -FROM rust:${RUST_VERSION}-slim-bookworm AS builder +FROM rust:${RUST_IMAGE_TAG} AS builder ARG BIN_NAME # git for the OGAR / lance-graph git dependencies pulled by sibling crates in @@ -51,6 +92,12 @@ RUN apt-get update \ WORKDIR /src +# The pin file FIRST, on its own layer: rustup reads it and materialises the +# exact channel + components, so the toolchain in this image is the one the +# repo declares rather than whatever the base tag happens to ship. +COPY rust-toolchain.toml ./ +RUN rustup show + COPY Cargo.toml ./ COPY crates ./crates diff --git a/rust-toolchain.toml b/rust-toolchain.toml index a1a2759..98d71fb 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -41,6 +41,20 @@ channel = "1.98.1" # and `cargo fmt --check` were both clean before and # after the fix. # +# 1.98.1 (image fix, no channel change) The two Dockerfiles used this same +# version string as their base-image TAG +# (`rust:1.98.1-slim-bookworm`), and that image does not +# exist: docker-library does not tag every point release. +# Measured — that tag is a 404 while `1.98` / `1.98.0` are +# 200, and `channel-rust-1.98.1.toml` is a 200, so the +# CHANNEL above was always valid and only the IMAGE was +# absent. Both files now float their base on the MINOR tag +# and COPY this file into the builder, so rustup +# materialises the channel there instead of the tag +# deciding it. That also closes a gap this file could not +# previously reach: it was never copied into either image, +# so the pin had no effect on a Railway build at all. +# # Never auto-track `stable` — bump explicitly when a future version is # reviewed and the workspace's fmt/clippy/test gates pass clean. #