Fetch the registry token from the public address, not the runner's
The builder on the host's network (the last change here) didn't help: the next publish failed exactly as before. Looking on the host showed why. Both builders resolve git.coffeylabs.org publicly; the token isn't fetched by the builder at all. buildx fetches registry tokens on the client side, in the job container, and on ci-net the name git.coffeylabs.org belongs to the gitlab container itself (172.30.0.2) -- which is how the runner clones over plain HTTP, and which has nothing on 443. So every push asked https://git.coffeylabs.org/jwt/auth for a token and was refused. The login before it worked because the host's daemon does the login, and the host resolves the name publicly. For the publish job only, the name now points at its public address in the job's /etc/hosts, looked up from a public resolver, as the host sees it. /etc/hosts wins over Docker's DNS, and nothing else in the job is affected: the checkout is done, and image layers go to the registry's own DNS-only name, not this one. The builder goes back to the shared ci-builder; its network was never the problem. The lookup and the /etc/hosts write were tried in the job's own image (docker:28-cli, same digest): it picks the first public IPv4 address and getent then returns it.
This commit is contained in:
+14
-10
@@ -87,16 +87,20 @@ publish:
|
|||||||
echo "VERSION=$VERSION" > version.env
|
echo "VERSION=$VERSION" > version.env
|
||||||
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
|
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
|
||||||
- docker run --privileged --rm tonistiigi/binfmt --install arm64
|
- docker run --privileged --rm tonistiigi/binfmt --install arm64
|
||||||
# The builder runs as a container on the host's daemon and does the push
|
# The registry hands out push tokens from https://git.coffeylabs.org/jwt/auth,
|
||||||
# itself, including fetching a registry token from git.coffeylabs.org.
|
# and buildx fetches them here, in the job, not in its builder. On ci-net
|
||||||
# On the runner's network that name resolves to an internal address
|
# that name is the gitlab container itself (172.30.0.2), which serves
|
||||||
# (172.30.0.2) with nothing on 443, so the token request was refused and
|
# plain HTTP to the runner and nothing on 443, so every push failed at the
|
||||||
# every push failed at the last step -- here and in ihasmail alike. On the
|
# last step with "connection refused". The login above works because the
|
||||||
# host's network the name resolves as it does for `docker login` above.
|
# host's daemon does it, and the host resolves the name publicly. So, for
|
||||||
# Only the token request uses it; layers still go to the registry's own
|
# this job only, point the name at its public address the same way. Only
|
||||||
# DNS-only name. A new name, because `ci-builder` is a long-lived container
|
# the token request uses it; layers go to the registry's own DNS-only name.
|
||||||
# shared between jobs and would keep whatever network it was created on.
|
- |
|
||||||
- docker buildx create --use --name ci-builder-host --driver docker-container --driver-opt network=host || docker buildx use ci-builder-host
|
public="$(nslookup "$CI_SERVER_HOST" 1.1.1.1 2>/dev/null | awk '/^Address: / && $2 !~ /:/ { print $2; exit }')"
|
||||||
|
if [ -z "$public" ]; then echo "Could not resolve $CI_SERVER_HOST publicly" >&2; exit 1; fi
|
||||||
|
echo "$public $CI_SERVER_HOST" >> /etc/hosts
|
||||||
|
echo "$CI_SERVER_HOST -> $public for the registry token"
|
||||||
|
- docker buildx create --use --name ci-builder --driver docker-container || docker buildx use ci-builder
|
||||||
script:
|
script:
|
||||||
- . ./version.env
|
- . ./version.env
|
||||||
# Attestations are off, as they were in publish.yml: they add manifests of
|
# Attestations are off, as they were in publish.yml: they add manifests of
|
||||||
|
|||||||
Reference in New Issue
Block a user