neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
Stop the EL9 stage from depending on its own curl binary
369e3b3 · Gabriel Morell · 2026-09-19 03:07
Message
{commit_body(@commit)}
Files changed
modified
cli/Dockerfile
+29
−29
@@ -98,48 +98,48 @@ RUN set -eux; \
| 98 | 98 | |
| 99 | 99 | # ── .rpm, on EL9 ───────────────────────────────────────────────────── |
| 100 | 100 | |
| 101 | −# A CA bundle this stage can actually read. | |
| 101 | +# The EL9 stage does not download its own toolchain, because the `curl` | |
| 102 | +# binary in that image cannot load a CA file on the forge's runner: | |
| 102 | 103 | # |
| 103 | −# EL9 ships one, and on a developer's machine it works — but on the | |
| 104 | −# forge's own runner every HTTPS fetch out of this image dies with | |
| 105 | −# `curl: (77) error setting certificate file`, with ca-certificates | |
| 106 | −# installed at the same version and `update-ca-trust extract` run first. | |
| 107 | −# The Debian stage downloads happily on that same host, so it is this | |
| 108 | −# image's trust store specifically, not the network: EL9 assembles that | |
| 109 | −# bundle out of hardlinks, and a snapshotter that mishandles them (an | |
| 110 | −# overlayfs with metacopy on, say) leaves a file present and unreadable | |
| 111 | −# exactly like this. | |
| 104 | +# curl: (77) error setting certificate file: <any path> | |
| 112 | 105 | # |
| 113 | −# Rather than keep guessing at the host, the stage carries its own | |
| 114 | −# bundle, taken from the image the .deb is built with — already pulled, | |
| 115 | −# and it demonstrably reaches the network. (debian:trixie-slim would be | |
| 116 | −# the tidier source and ships no ca-certificates at all.) | |
| 117 | −# CURL_CA_BUNDLE covers curl and cargo's libcurl; SSL_CERT_FILE covers | |
| 118 | −# rustup and anything OpenSSL- or rustls-based. | |
| 119 | −FROM docker.io/rust:${RUST_VERSION}-trixie AS certs | |
| 106 | +# Not the file and not the network. In the same RUN, one command | |
| 107 | +# earlier, dnf pulls 50 MB of metadata and 279 packages over HTTPS | |
| 108 | +# through libcurl using this very bundle; the same image does it | |
| 109 | +# happily on a developer's machine. So the toolchain is copied in whole | |
| 110 | +# from the Debian stage instead — the official x86_64-unknown-linux-gnu | |
| 111 | +# builds target glibc 2.17, so rustc and cargo run here unmodified, and | |
| 112 | +# cargo's own libcurl is not the binary that's broken. | |
| 113 | +FROM docker.io/rust:${RUST_VERSION}-trixie AS toolchain | |
| 120 | 114 | |
| 121 | 115 | FROM docker.io/rockylinux/rockylinux:9 AS rpm-builder |
| 122 | 116 | |
| 123 | −COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/pki/ca-trust/gg-ca-bundle.pem | |
| 124 | −ENV CURL_CA_BUNDLE=/etc/pki/ca-trust/gg-ca-bundle.pem \ | |
| 125 | − SSL_CERT_FILE=/etc/pki/ca-trust/gg-ca-bundle.pem | |
| 126 | − | |
| 127 | −# EL9's own rust is far older than this crate's edition, so the | |
| 128 | −# toolchain comes from rustup — the same split the server image makes | |
| 129 | −# for the NIF crates on trixie. | |
| 130 | −ARG RUST_VERSION | |
| 131 | 117 | ENV RUSTUP_HOME=/usr/local/rustup \ |
| 132 | 118 | CARGO_HOME=/usr/local/cargo \ |
| 133 | 119 | PATH=/usr/local/cargo/bin:${PATH} |
| 120 | +COPY --from=toolchain /usr/local/rustup /usr/local/rustup | |
| 121 | +COPY --from=toolchain /usr/local/cargo /usr/local/cargo | |
| 122 | + | |
| 123 | +# A CA bundle from an image that demonstrably reaches the network on | |
| 124 | +# that host, for everything here that still fetches: dnf, and cargo | |
| 125 | +# pulling crates. | |
| 126 | +COPY --from=toolchain /etc/ssl/certs/ca-certificates.crt /etc/pki/ca-trust/gg-ca-bundle.pem | |
| 127 | +ENV CURL_CA_BUNDLE=/etc/pki/ca-trust/gg-ca-bundle.pem \ | |
| 128 | + SSL_CERT_FILE=/etc/pki/ca-trust/gg-ca-bundle.pem \ | |
| 129 | + CARGO_HTTP_CAINFO=/etc/pki/ca-trust/gg-ca-bundle.pem | |
| 130 | + | |
| 131 | +# The curl line is a probe, not a dependency: it records in the build | |
| 132 | +# log whether this host still has the fault, and nothing below needs it | |
| 133 | +# to pass. (Comments can't live inside the RUN — a Dockerfile joins | |
| 134 | +# continued lines into one, and a `#` would swallow the rest.) | |
| 134 | 135 | RUN set -eux; \ |
| 135 | 136 | dnf -y install gcc gcc-c++ make cmake perl; \ |
| 136 | 137 | dnf clean all; \ |
| 137 | − curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs -o /tmp/rustup-init.sh; \ | |
| 138 | − sh /tmp/rustup-init.sh -y --no-modify-path --profile minimal \ | |
| 139 | − --default-toolchain "${RUST_VERSION}"; \ | |
| 140 | − rm /tmp/rustup-init.sh; \ | |
| 141 | 138 | rustc --version; \ |
| 142 | 139 | cargo --version; \ |
| 140 | + { curl -sSf -o /dev/null https://static.rust-lang.org/ \ | |
| 141 | + && echo "probe: the curl binary works here" \ | |
| 142 | + || echo "probe: the curl binary cannot load a CA file here"; }; \ | |
| 143 | 143 | cargo install --locked cargo-generate-rpm |
| 144 | 144 | |
| 145 | 145 | WORKDIR /src/cli |
Parents: c90ac30