I’ve recently moved some of my FOSS projects to Codeberg, and I’m using self-hosted runners for continuous integration. From time to time, I was experiencing some errors like:
#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile:
#1 transferring dockerfile: 2.14kB done
#1 DONE 0.8s
#2 [internal] load metadata for docker.io/library/node:24-alpine
#2 ERROR: failed to copy: httpReadSeeker: failed open: failed to do request:
Get "https://docker-images-prod.6aa30f8b08e16409b46e0173d6de2f56.r2.cloudflarestorage.com/registry-v2/docker/registry/v2/blobs/[...]":
tls: failed to verify certificate: x509: certificate is not valid for any names, but wanted to match docker-images-prod.6aa30f8b08e16409b46e0173d6de2f56.r2.cloudflarestorage.com
These errors started happening out of the blue. I don’t know the root cause yet, but here goes what I did to fix it in case I need it in the future. Note to self: TIL posts are not guides but quick notes for future me written in under 15 minutes.
After reading I was being man-in-the-middled, I started making some other tests in my server. This error was happening inside a docker-in-docker container used by Forgejo to run docker-related commands, but I didn’t have this from the docker host, so there was definitely something off with my docker networking.
I continued comparing side-by-side the output of curl -v on the aforementioned URL, and verified the DNS resolution was identical. Against all odds, it was not DNS this time. The DNS resolution returned two addresses, an IPv4 and an IPv6. In the host, the request was made using the IPv6 and everything ran smoothly. However, in the docker container, trying to connect via IPv6 gave some network unreachable error, so it fall back to the IPv4. I have no idea why things worked with the IPv6 but not IPv4, but hey, I had found a difference that most likely explained the problem.
From the host, I ran docker network inspect <my-networ>, and observed IPv4 was enabled but IPv6 wasn’t. I had to:
docker compose down
docker network rm <my-network>
docker network create --ipv6 <my-network>
docker compose up -d
After this change, the curl -v from the container started running smoothly, and operations in my codeberg runners was resumed.
I hope I don’t have to come back to these notes, but if I have to, I’ll be glad I ever wrote them.