Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUILDKIT ignores "insecure-registries". server gave HTTP response to HTTPS client. x509: certificate error #1642

Closed
HectorB-2020 opened this issue Feb 21, 2023 · 36 comments · Fixed by moby/moby#45992
Labels
area/feature-parity kind/bug Something isn't working

Comments

@HectorB-2020
Copy link

Hello! After upgrading to Docker Engine v23.0.1 our CI process started failing due to errors accessing internal Harbor registry.
As I see BuildKit became default in versions 23+.

Unfortunately Docker BuildKit disregards configuration insecure-registries in /etc/docker/daemon.json.

All attempts to build image fail with the following errors. Needless to say that address of our Harbor registry was added to insecure-registries. It used to work normally with previous versions of Docker.

Error getting v2 registry: Get \"https://harbor.company.local/v2/\/": http: server gave HTTP response to HTTPS client"
ERROR: failed to solve: harbor.company.local/hub/library/node:16.17.0-alpine3.16: failed to do request: Head "https://harbor.company.local/v2/hub/library/node/manifests/16.17.0-alpine3.16":
 x509: certificate is valid for ingress.local, not harbor.company.local
 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

If we place commands like

docker pull harbor.company.local/hub/library/node:16.17.0-alpine3.16`

before docker build, all images are pulled successfully, which is proves that docker daemon is configured correctly and all other processes keep working.

Thanks to the discussion in #1613, we managed to implement a workaround with setting BUILDKIT_NO_CLIENT_TOKEN=true. 👍
For the sake of completeness, I have to mention another issue #1589, which is related to the same or very similar problem I believe.

Another workaround was to export DOCKER_BUILDKIT=0.
When this variable is set, the following message appear in the logs, which is expected, I'm convinced.

DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
BuildKit is currently disabled; enable it by removing the DOCKER_BUILDKIT=0 environment-variable.

Anyway, we still shall appreciate if you can fix this behaviour and make BuildKit rely on insecure-registries in /etc/docker/daemon.json.

@jedevc
Copy link
Collaborator

jedevc commented Apr 4, 2023

Hm, I'm really struggling to reproduce this actually. I can seem to get something very similar to this if the target image doesn't exist - then when using the base image in a FROM, I get the HTTPS error instead of the expected not-found error - but you seem to be able to pull the image after, so it doesn't seem to be this problem.

Could you please share (redact any confidential information):

  • The contents of your /etc/docker/daemon.json
  • The output of docker version
  • The exact docker build command you're using

@crazy-max
Copy link
Member

Can you also post the output of docker buildx ls please?

@HectorB-2020
Copy link
Author

Hello @crazy-max and @jedevc!
Let me explain to eliminate confusion. docker pull command was used in the CI process merely for testing to ensure that Docker credentials are passed normally and actually used in the script on the node where CI is running. And since pure docker pullrespects insecure-registries, it worked as expected. But the other commands used for real building fail on version 23.0.1 with DOCKER_BUILDKIT=1 set by default. We've tried all the following variants, all fail.

docker build -t some-tag  .
docker build -t some-tag  --build-arg VAR1 .
docker build -t some-tag  --pull --build-arg VAR1 .

Here are our versions below.
docker version

Client: Docker Engine - Community
 Version:           23.0.1
 API version:       1.42
 Go version:        go1.19.5
 Git commit:        a5ee5b1
 Built:             Thu Feb  9 19:46:56 2023
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          23.0.1
  API version:      1.42 (minimum version 1.12)
  Go version:       go1.19.5
  Git commit:       bc3805a
  Built:            Thu Feb  9 19:46:56 2023
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.16
  GitCommit:        31aa4358a36870b21a992d3ad2bef29e1d693bec
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

docker buildx ls

NAME/NODE DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default * docker
  default default         running 23.0.1   linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386

@alejandro-du
Copy link

Getting exactly the same error. Using a Docker registry on a Raspberry Pi 4.

@seedrick
Copy link

seedrick commented May 5, 2023

Another +1, didn't realize this was the same issue.

@jedevc
Copy link
Collaborator

jedevc commented May 9, 2023

Does anyone here have a reproducible example? I've managed to repro in the case if "the target image doesn't exist" - but at least from the above, it looks like people are having other issues.

If anyone could share a reproducible example (e.g. a docker compose setup, or a github repo, or anything really), or even just indicate what the registry used is and how it's setup would massively help in tracking this down. Without that, it's kind of just guessing in the dark, there's so many different setups and registry combinations, that it's impossible to just try them all 😢

@alejandro-du
Copy link

@jedevc, thanks a lot for your help. I have this GitHub repo. It's not a MRE, but I hope it helps.

Use the build.sh and then publish.sh scripts. Specify the custom Docker Registry host as a parameter. Also, you might want to comment out some of the lines in these files to avoid building and pushing more than what's necessary to reproduce this issue.

My Docker Registry runs on a Raspberry Pi and I'm building and pushing from a Mac M1, if that info helps.

@Re4zOon
Copy link

Re4zOon commented Jun 6, 2023

Happens for our devs as well. Interestingly our jenkins servers are not hitting this issue (even tho I just upgraded OS, hence docker on them a week ago).

@TheUbuntuGuy
Copy link

We are seeing this in our CI which builds many containers in parallel using DinD. We have a local pull-through cache which currently is HTTP only for reasons. What is interesting is that the problem is intermittent. The same builder will pull the base image (specified in the FROM directive) just fine in one job and fail the exact same base image in the next. Even retrying our jobs immediately after usually succeeds.

For example, a success:

...
#3 [internal] load metadata for docker.io/library/debian:bullseye-slim
#3 DONE 0.7s
#4 [1/3] FROM docker.io/library/debian:bullseye-slim@sha256:924df86f8aad741a0134b2de7d8e70c5c6863f839caadef62609c1be1340daf5
#4 resolve docker.io/library/debian:bullseye-slim@sha256:924df86f8aad741a0134b2de7d8e70c5c6863f839caadef62609c1be1340daf5 done
#4 sha256:924df86f8aad741a0134b2de7d8e70c5c6863f839caadef62609c1be1340daf5 1.85kB / 1.85kB done
...

and a failure on the same base image, using the same build command and Dockerfile:

...
#3 [internal] load metadata for docker.io/library/debian:bullseye-slim
#3 ERROR: failed to copy: httpReadSeeker: failed open: failed to do request: Get "https://registrycache.<redacted>.com:5001/v2/library/debian/manifests/sha256:29015f4c1aa9e8f594741b13060529b778b443fba1550a23bdf284cdf9686beb?ns=docker.io": http: server gave HTTP response to HTTPS client
...

This had worked reliably before we switched to buildkit.

Our server's daemon.json:

"insecure-registries": [ "http://registrycache.<redacted>.com:5001"],
"registry-mirrors": ["http://registrycache.<redacted>.com:5001"],

(and yes I know http:// shouldn't be in the insecure-registries section, but that gets stripped out and doesn't seem to be the issue).

and the DinD service container entrypoint shares the same config:

services:
    - name: docker:24-dind
      alias: docker
      entrypoint: ["dockerd-entrypoint.sh"]
      command:
        [
          "--insecure-registry",
          "registrycache.<redacted>.com:5001",
          "--registry-mirror",
          "http://registrycache.<redacted>.com:5001",
        ]

I will see if I can narrow down a self-contained MRE but for now I will have to disable buildkit in my environment.

@HectorB-2020
Copy link
Author

I'm afraid at the moment there is only one option - to set export DOCKER_BUILDKIT=0. Frankly, I'm not excited with this choice as BuildKit has plenty of real advantages.
And the more disturbing fact is we don't know what Docker developers think about this issue. Do they truly believe its hasn't been proved yet? If the issue is considered confirmed, are there any plans to fix it?

@tianon
Copy link
Contributor

tianon commented Jul 6, 2023

The last report from the maintainers here was that they couldn't reproduce the specific error (only related ones), so it's not exactly fair to characterize them as not caring about it; they're a fairly busy team and likely just haven't had a chance to get back to this yet and try to reproduce again. 😅 ❤️

This happens to be something I ran into recently, so I was able to get the same error with the following minimal reproducer for the two related problems here (insecure-registry from Docker not applying to BuildKit and insecure registry-mirror from Docker in BuildKit): 👀

# set up a registry and start up Docker-in-Docker
docker network create --internal foo # internal so Docker/BuildKit can't hit the internet and we can be certain it's using our registry/mirror for sure
docker run -dit --rm --network foo --name foo-registry registry
docker run -dit --rm --network foo --name foo-dind --privileged docker:dind dockerd --insecure-registry foo-registry:5000 --registry-mirror http://foo-registry:5000

# validate our configuration
docker exec foo-dind docker info | grep -B2 foo-registry

# running crane on the host network so we can copy in an image to test/run with
registry="$(docker container inspect --format '{{ .NetworkSettings.Networks.foo.IPAddress }}' foo-registry)"
docker run --rm --network host gcr.io/go-containerregistry/crane cp --insecure docker.io/library/hello-world:linux "$registry:5000/library/hello-world:linux" &> /dev/null

# make sure it works with Docker
docker exec foo-dind docker run --rm foo-registry:5000/library/hello-world:linux > /dev/null
docker exec foo-dind docker rmi foo-registry:5000/library/hello-world:linux
docker exec foo-dind docker run --rm hello-world:linux > /dev/null
docker exec foo-dind docker rmi hello-world:linux

# test BuildKit (both of these should fail)
printf 'FROM foo-registry:5000/library/hello-world:linux\nRUN ["/hello"]' | docker exec -i foo-dind docker buildx build --no-cache -
printf 'FROM hello-world:linux\nRUN ["/hello"]' | docker exec -i foo-dind docker buildx build --no-cache -
Failing Output:
c0e1321ec9a61c25f72f7c8a6fe44324594e70dac5b09c2dbf8607668029c286
94a25edc05815f711bf175f1ed932040f5506b87a206bc6c0707bb21b8d9510d
a934704a869b3ebcf72e59d13b37b72475ba15e967610c3bd73e75530d044110
WARNING: No blkio throttle.read_bps_device support
WARNING: No blkio throttle.write_bps_device support
WARNING: No blkio throttle.read_iops_device support
WARNING: No blkio throttle.write_iops_device support
 Experimental: false
 Insecure Registries:
  foo-registry:5000
  127.0.0.0/8
 Registry Mirrors:
  http://foo-registry:5000/
Unable to find image 'foo-registry:5000/library/hello-world:linux' locally
linux: Pulling from library/hello-world
719385e32844: Pulling fs layer
719385e32844: Verifying Checksum
719385e32844: Download complete
719385e32844: Pull complete
Digest: sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
Status: Downloaded newer image for foo-registry:5000/library/hello-world:linux
Untagged: foo-registry:5000/library/hello-world:linux
Untagged: foo-registry:5000/library/hello-world@sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
Deleted: sha256:9c7a54a9a43cca047013b82af109fe963fde787f63f9e016fdc3384500c2823d
Deleted: sha256:01bb4fce3eb1b56b05adf99504dafd31907a5aadac736e36b27595c8b92f07f1
Unable to find image 'hello-world:linux' locally
linux: Pulling from library/hello-world
719385e32844: Pulling fs layer
719385e32844: Verifying Checksum
719385e32844: Download complete
719385e32844: Pull complete
Digest: sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
Status: Downloaded newer image for hello-world:linux
Untagged: hello-world:linux
Untagged: hello-world@sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
Deleted: sha256:9c7a54a9a43cca047013b82af109fe963fde787f63f9e016fdc3384500c2823d
Deleted: sha256:01bb4fce3eb1b56b05adf99504dafd31907a5aadac736e36b27595c8b92f07f1
#0 building with "default" instance using docker driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 74B done
#1 DONE 0.0s

#2 [internal] load .dockerignore
#2 transferring context: 2B done
#2 DONE 0.0s

#3 [internal] load metadata for docker.io/library/hello-world:linux
#3 ERROR: failed to do request: Head "https://foo-registry:5000/v2/library/hello-world/manifests/linux?ns=docker.io": http: server gave HTTP response to HTTPS client
------
 > [internal] load metadata for docker.io/library/hello-world:linux:
------
Dockerfile:1
--------------------
   1 | >>> FROM hello-world:linux
   2 |     RUN ["/hello"]
--------------------
ERROR: failed to solve: hello-world:linux: failed to do request: Head "https://foo-registry:5000/v2/library/hello-world/manifests/linux?ns=docker.io": http: server gave HTTP response to HTTPS client

It's noted in some of the previous comments, and it's not mentioned on https://docs.docker.com/engine/reference/commandline/dockerd/#insecure-registries, but https://docs.docker.com/registry/insecure/ does suggest that insecure-registry can also accept a protocol, presumably as a way to differentiate between "use TLS, but accept an insecure certificate" vs "use the insecure HTTP protocol" that insecure-registry otherwise technically means "both" of (as seen by Docker itself not needing a protocol specified; cc @thaJeztah @neersighted @dvdksn, maybe something to document more consistently?)

When I update --insecure-registry to include the http:// prefix (dockerd --insecure-registry http://foo-registry:5000 --registry-mirror http://foo-registry:5000), this example does work for me, and gets all the way through both builds successfully. 🎉

Successful Output:
1b4f558bf37fbd97f0543da03c39196b838cf5fe477f5c056987228377efe92d
0ae051678f3216a64e55bd2439237e22060c1d9afd2a425aed2c5a9a5c6ef483
9f5072a5b80e41ef027c731464cc07aebd6ff559a9f40266a15791f63cc41ffc
WARNING: No blkio throttle.read_bps_device support
WARNING: No blkio throttle.write_bps_device support
WARNING: No blkio throttle.read_iops_device support
WARNING: No blkio throttle.write_iops_device support
 Experimental: false
 Insecure Registries:
  foo-registry:5000
  127.0.0.0/8
 Registry Mirrors:
  http://foo-registry:5000/
Unable to find image 'foo-registry:5000/library/hello-world:linux' locally
linux: Pulling from library/hello-world
719385e32844: Pulling fs layer
719385e32844: Verifying Checksum
719385e32844: Download complete
719385e32844: Pull complete
Digest: sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
Status: Downloaded newer image for foo-registry:5000/library/hello-world:linux
Untagged: foo-registry:5000/library/hello-world:linux
Untagged: foo-registry:5000/library/hello-world@sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
Deleted: sha256:9c7a54a9a43cca047013b82af109fe963fde787f63f9e016fdc3384500c2823d
Deleted: sha256:01bb4fce3eb1b56b05adf99504dafd31907a5aadac736e36b27595c8b92f07f1
Unable to find image 'hello-world:linux' locally
linux: Pulling from library/hello-world
719385e32844: Pulling fs layer
719385e32844: Verifying Checksum
719385e32844: Download complete
719385e32844: Pull complete
Digest: sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
Status: Downloaded newer image for hello-world:linux
Untagged: hello-world:linux
Untagged: hello-world@sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
Deleted: sha256:9c7a54a9a43cca047013b82af109fe963fde787f63f9e016fdc3384500c2823d
Deleted: sha256:01bb4fce3eb1b56b05adf99504dafd31907a5aadac736e36b27595c8b92f07f1
#0 building with "default" instance using docker driver

#1 [internal] load .dockerignore
#1 transferring context: 2B done
#1 DONE 0.0s

#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 74B done
#2 DONE 0.0s

#3 [internal] load metadata for docker.io/library/hello-world:linux
#3 DONE 0.1s

#4 [1/2] FROM docker.io/library/hello-world:linux@sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
#4 resolve docker.io/library/hello-world:linux@sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d 0.0s done
#4 extracting sha256:719385e32844401d57ecfd3eacab360bf551a1491c05b85806ed8f1b08d792f6 done
#4 sha256:719385e32844401d57ecfd3eacab360bf551a1491c05b85806ed8f1b08d792f6 2.46kB / 2.46kB done
#4 sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d 2.07kB / 2.07kB done
#4 sha256:7e9b6e7ba2842c91cf49f3e214d04a7a496f8214356f41d81a6e6dcad11f11e3 525B / 525B done
#4 sha256:9c7a54a9a43cca047013b82af109fe963fde787f63f9e016fdc3384500c2823d 1.47kB / 1.47kB done
#4 DONE 0.1s

#5 [2/2] RUN ["/hello"]
#5 0.218
#5 0.218 Hello from Docker!
#5 0.218 This message shows that your installation appears to be working correctly.
#5 0.218
#5 0.218 To generate this message, Docker took the following steps:
#5 0.218  1. The Docker client contacted the Docker daemon.
#5 0.218  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
#5 0.218     (amd64)
#5 0.218  3. The Docker daemon created a new container from that image which runs the
#5 0.218     executable that produces the output you are currently reading.
#5 0.218  4. The Docker daemon streamed that output to the Docker client, which sent it
#5 0.218     to your terminal.
#5 0.218
#5 0.218 To try something more ambitious, you can run an Ubuntu container with:
#5 0.218  $ docker run -it ubuntu bash
#5 0.218
#5 0.218 Share images, automate workflows, and more with a free Docker ID:
#5 0.218  https://hub.docker.com/
#5 0.218
#5 0.218 For more examples and ideas, visit:
#5 0.218  https://docs.docker.com/get-started/
#5 0.218
#5 DONE 0.2s

#6 exporting to image
#6 exporting layers 0.0s done
#6 writing image sha256:ccf2e23200821ad83198e15400f250a69c4d9eabd8948eeaedb0dd2131509dc1 done
#6 DONE 0.0s
#0 building with "default" instance using docker driver

#1 [internal] load .dockerignore
#1 transferring context: 2B done
#1 DONE 0.0s

#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 100B done
#2 DONE 0.0s

#3 [internal] load metadata for foo-registry:5000/library/hello-world:linux
#3 DONE 0.0s

#4 [1/2] FROM foo-registry:5000/library/hello-world:linux@sha256:726023f73a8fc5103fa6776d48090539042cb822531c6b751b1f6dd18cb5705d
#4 CACHED

#5 [2/2] RUN ["/hello"]
#5 0.220
#5 0.220 Hello from Docker!
#5 0.220 This message shows that your installation appears to be working correctly.
#5 0.220
#5 0.220 To generate this message, Docker took the following steps:
#5 0.220  1. The Docker client contacted the Docker daemon.
#5 0.220  2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
#5 0.220     (amd64)
#5 0.220  3. The Docker daemon created a new container from that image which runs the
#5 0.220     executable that produces the output you are currently reading.
#5 0.220  4. The Docker daemon streamed that output to the Docker client, which sent it
#5 0.220     to your terminal.
#5 0.220
#5 0.220 To try something more ambitious, you can run an Ubuntu container with:
#5 0.220  $ docker run -it ubuntu bash
#5 0.220
#5 0.220 Share images, automate workflows, and more with a free Docker ID:
#5 0.220  https://hub.docker.com/
#5 0.220
#5 0.220 For more examples and ideas, visit:
#5 0.220  https://docs.docker.com/get-started/
#5 0.220
#5 DONE 0.2s

#6 exporting to image
#6 exporting layers done
#6 writing image sha256:8c9eada21969c3a185c994222d584698cee2ad8015347dd2df38a3c8a6dce78b done
#6 DONE 0.0s

I'm not sure why the example above with daemon.json showing the same configuration didn't work, but maybe worth testing again and being certain both flags/config values include http:// explicitly?

(There is arguably a bug here where BuildKit is interpreting Docker's configuration in a slightly different way from Docker itself, but it's not unfair for BuildKit to have not wanted to implement the same "which type of insecure?" heuristic as Docker did because it is not the most reliable/efficient thing to try and detect correctly, which is why I think this might be more of a documentation issue since Docker doesn't mind the protocol prefix and BuildKit works correctly with it. 😅)

@tonistiigi
Copy link
Member

To highlight from @tianon 's comment:

If you hit this error with insecure-registries: check if you have defined protocol in the URL. http:// if the insecure server is using plain HTTP and https:// if server is using self-signed certificates with TLS. If you still hit an issue, we need extra information about the case and the exact versions, ideally a runnable reproducer.

@jedevc
Copy link
Collaborator

jedevc commented Jul 17, 2023

So as it turns out, apparently using http and https in insecure-registries is deprecated? moby/moby#29988, I think we want a docs update in https://docs.docker.com/registry/insecure/ to reflect this?

Also, apparently insecure-registries supports CIDR notation - I haven't seen this a lot in the wild, but I imagine we probably want to support this case as well for containerd/buildkit (looks like the new containerd snapshotter and buildkit share the same codepath here).

@jedevc
Copy link
Collaborator

jedevc commented Jul 24, 2023

To anyone coming across this in the future - this issue should now be resolved by moby/moby#45992, which will be released as part of moby 25.0.

@victornoel
Copy link

victornoel commented Jan 24, 2024

Hey @jedevc, I just tried docker 25 and when using in dind (started with both --registry-mirror and --insecure-registry) (docker:25-dind) + docker buildx in a separate container (docker:25) connecting to dind for the daemon and it does not seem to work at all, the registry mirror is simply ignored when I look at the debug logs of buildx.

Is this meant to work following your change or am I confused about all of this?

Some versioning information:

$ docker info
Client:
 Version:    25.0.0
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.12.1
    Path:     /usr/local/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.24.2
    Path:     /usr/local/libexec/docker/cli-plugins/docker-compose
Server:
 Server Version: 25.0.0
 containerd version: 71909c1814c544ac47ab91d2e8b84718e517bb99
 Insecure Registries:
  dockerproxy:6000
  127.0.0.0/8
 Registry Mirrors:
  http://dockerproxy:6000/
...

I see also a dependency to buidkit when building:

$ docker buildx build --pull --push --platform linux/arm64,linux/amd64 --tag $CI_REGISTRY_IMAGE/server:$CI_COMMIT_REF_SLUG .
#0 building with "multiarch-builder" instance using docker-container driver
#1 [internal] booting buildkit
#1 pulling image moby/buildkit:buildx-stable-1

The only way I found to make it work is to use the following buildkit.toml passed to docker buildx create --config buildkit.toml

[registry."docker.io"]
  mirrors = ["dockerproxy:6000"]
[registry."dockerproxy:6000"]
  http = true

@woshikid
Copy link

As 25.0, it's still not fixed.
@victornoel Thank you for the solution. It works for me.

@thaJeztah
Copy link
Member

@victornoel @woshikid The case described above by @victornoel (#1642 (comment)) is expected; looking at the build progress output, that is a build running in a container-builder;

#0 building with "multiarch-builder" instance using docker-container driver

When creating a container builder, you're creating an isolated BuildKit instance that runs inside a container; such a container has no direct relation with the daemon it's running on, and does not inherit configuration from the daemon (only using configuration options as passed by the user when creating the container / containerised builder).

The Moby pull-request that closed this ticket (moby/moby#45992) fixed this issue when using the BuildKit builder that's embedded in the Docker Engine Daemon; this builder is configured using the daemon-configuration options set for the Docker Engine Daemon, and therefore will be configured with the insecure registry settings that are set in the daemon config. Perhaps it's possible for buildx to provide an option to make this easier to set up, but it would very likely remain opt in (e.g. it could be a docker buildx create --copy-daemon-settings or something along those lines), but that would have to be discussed.

I should add that Docker Engine v25 allows you to use containerd's image store instead of the "graph-driver" store for containers and images; https://docs.docker.com/storage/containerd/. When using the Docker Daemon with the containerd image store ("snapshotters") enabled, the Docker Engine gains support for storing multi-arch / multi-platform images. If you're creating a container-builder for that reason (to be able to build multi-arch images with multiple architectures), it may be worth giving that option a try.

I should add some disclaimers;

  • The containerd image store integration uses a separate storage location from the non-containerd store. It does not remove the existing content (images, container filesystems), but won't be able to use those. So it's best to use on a machine where you can start "from scratch" (no existing images and containers).
  • There are still some UX improvements to make (the API and CLI were not designed for images with multiple architectures present, so commands like docker inspect will only show a single architecture, even if content has multiple architectures stored).

@victornoel
Copy link

@thaJeztah thank you for the explanation, I knew I was most certainly missing something :P so when is this buildkit embedded in docker used? When I call docker build? Is it going to behave differently from docker buildx build?

if I understand correctly what you are saying, I can use containred image store + docker build to build multi-arch images instead of using docker buildx build, correct? All of this is running as a CI job in Gitlab, so I think what you mention in the disclaimer should not be an issue… maybe?

Sorry to turn this ticket into a support thread :P

@victornoel
Copy link

Ok, it seems I "just" need not to execute docker buildx create before executing docker buildx build and it won't use a dedicated builder.

Now I "just" need to understand how to enable containerd image store from the command line because I don't have much control on the daemon.json file unfortunately.

@thaJeztah
Copy link
Member

So docker build and docker buildx build are the same since docker 23.0. When you run docker build with BuildKit enabled (default), then the Docker ClI executes buildx build behind the scenes. The only exception is that buildx does not support the legacy (non-buildkit) builder, so when you run docker build with the DOCKER_BUILDKIT=0 environment variable set, it falls back to using the legacy builder.

The builder that's used is configurable; by default, docker build (and thus docker buildx build) will use the default BuildKit builder in the Docker Engine you're using (but which engine that is can be switched using docker context, so in some cases you may need to switch the context as well). You can configure which builder to use. For example, if you create a container-builder, and set the --use option while doing so, then buildx creates a new container builder AND switches the build commands to use that as builder.

If you type docker builder ls (or docker buildx ls), you'll see a list of builders that are available. It also shows a asterisk (*) to show which of those is currently set as your builder; in the example below, I'm currently using the multi-arch-builder builder;

docker builder ls
NAME/NODE             DRIVER/ENDPOINT  STATUS   BUILDKIT             PLATFORMS
custom-net-build      docker-container
  custom-net-build0   desktop-linux    inactive
multi-arch-builder *  docker-container
  multi-arch-builder0 desktop-linux    inactive
default               docker
  default             default          running  v0.12.4+3b6880d2a00f linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64
desktop-linux         docker
  desktop-linux       desktop-linux    running  v0.12.4+3b6880d2a00f linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64
remote                docker
  remote              remote           running  v0.10.6+d52b2d5      linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

You can switch the builder to use using docker builder use / docker buildx use; in my case, I'm running docker desktop, and the engine is accessible throug the desktop-linux context, so I can switch my builder to use that builder;

docker builder use desktop-linux

After that, it should show as the currently selected builder;

docker builder ls
NAME/NODE             DRIVER/ENDPOINT  STATUS   BUILDKIT             PLATFORMS
custom-net-build      docker-container
  custom-net-build0   desktop-linux    inactive
multi-arch-builder    docker-container
  multi-arch-builder0 desktop-linux    inactive
default               docker
  default             default          running  v0.12.4+3b6880d2a00f linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64
desktop-linux *       docker
  desktop-linux       desktop-linux    running  v0.12.4+3b6880d2a00f linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64
remote                docker
  remote              remote           running  v0.10.6+d52b2d5      linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

You can also inspect the builder to get more information about the features it provides. In my case, I have the containerd image-store integration enabled, and the builder shows that it uses the overlayfs containerd snapshotter;

docker builder inspect desktop-linux
Name:          desktop-linux
Driver:        docker
Last Activity: 2024-01-26 15:08:49 +0000 UTC

Nodes:
Name:      desktop-linux
Endpoint:  desktop-linux
Status:    running
Buildkit:  v0.12.4+3b6880d2a00f
Platforms: linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64
Labels:
 org.mobyproject.buildkit.worker.containerd.namespace: moby
 org.mobyproject.buildkit.worker.containerd.uuid:      1cc22aa9-1955-4d97-96a7-b6153b61614b
 org.mobyproject.buildkit.worker.executor:             containerd
 org.mobyproject.buildkit.worker.hostname:             docker-desktop
 org.mobyproject.buildkit.worker.moby.host-gateway-ip: 192.168.65.254
 org.mobyproject.buildkit.worker.network:              host
 org.mobyproject.buildkit.worker.selinux.enabled:      false
 org.mobyproject.buildkit.worker.snapshotter:          overlayfs
GC Policy rule#0:
 All:           false
 Filters:       type==source.local,type==exec.cachemount,type==source.git.checkout
 Keep Duration: 48h0m0s
 Keep Bytes:    2.764GiB
GC Policy rule#1:
 All:           false
 Keep Duration: 1440h0m0s
 Keep Bytes:    20GiB
GC Policy rule#2:
 All:        false
 Keep Bytes: 20GiB
GC Policy rule#3:
 All:        true
 Keep Bytes: 20GiB

@victornoel
Copy link

Thank you again for sharing all this knowledge 👍

@nikelborm
Copy link

For people using buildkitd in docker-container here is simple way how to get it working with http:
create buildkitd.toml in CWD in terminal with following content:

root = "/var/lib/buildkit"
insecure-entitlements = [ "network.host", "security.insecure" ]

[log]
  format = "text"

[registry."YOUR_HOST:YOUR_PORT"]
  http = true
  insecure = true

And then run this bash

init_docker_builder() {
  export DOCKER_BUILDKIT=1
  export COMPOSE_DOCKER_CLI_BUILD=1
  docker run --rm --privileged -d --name buildx_buildkit_my_builder0 --volume ./buildkitd.toml:/buildkitd.toml --network host moby/buildkit:latest --config /buildkitd.toml
  docker run --privileged --rm tonistiigi/binfmt --install all
  docker buildx create --name my_builder --platform=linux/arm64,linux/amd64 --driver=docker-container
  export BUILDKIT_HOST=docker-container://buildx_buildkit_my_builder0
  export BUILDX_BUILDER=my_builder
  docker buildx install
  docker buildx use --builder my_builder --default --global
}
init_docker_builder

I faced error http: server gave HTTP response to HTTPS client because buildkitd in container has no idea about /etc/docker/daemon.json and my insecure-registries there seemed to have no effect. When I mounted config into container error went away.

@tianon-sso
Copy link
Member

Any reason you're not just using the --config flag to docker buildx create to pass it your config file? 👀

@nikelborm
Copy link

@tianon
because buildkitd provided as buildx is v0.11.7+d3e6c1360f6e and I want latest buildkitd provided by container which is v0.12.5

@tianon-sso
Copy link
Member

I think that's just --driver-opt image=moby/buildkit:latest, right? 😅

@nikelborm
Copy link

I think that's just --driver-opt image=moby/buildkit:latest, right? 😅

Oh, I didn't know it. Now I do. Thank you!

@tonistiigi
Copy link
Member

because buildkitd provided as buildx is v0.11.7+d3e6c1360f6e

Sorry, what? Where do you see this? Buildx defaults to using latest release of buildkit when it deploys container builders (sometimes we give couple of extra days of testing after a release before switching buildx default, but that is an exception).

@nikelborm
Copy link

nikelborm commented Feb 6, 2024

@tonistiigi this seems like some issue with Arch packaging system.
I've always seen v0.11.7+d3e6c1360f6e as version of default builder in output of docker builder ls and it didn't change even after updates of the system. Now out of curiosity I reinstalled docker with buildx (sudo pacman -Syu docker docker-buildx) and suddenly I have the latest version v0.12.5. I honestly don't have any idea what is going on here, I'm just glad it is updated now

If I accidentally called things not by their names, I'm sorry

@nikelborm
Copy link

nikelborm commented Feb 6, 2024

Luckily I did btrfs snapshot before update so I can investigate a bit
This is what I see booted from this snapshot:

$ docker builder ls
NAME/NODE DRIVER/ENDPOINT STATUS  BUILDKIT             PLATFORMS
default * docker                                       
  default default         running v0.11.7+d3e6c1360f6e linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386

I entered sudo pacman -Syu --noconfirm --needed --color always; and it showed me that docker will be updated (And it actually didn't matter that I REinstalled it in my previous message with sudo pacman -Syu docker docker-buildx )

Package (16)            Old Version     New Version  Net Change  Download Size
extra/docker            1:24.0.7-1      1:25.0.2-1     7.06 MiB      28.39 MiB

Since I update my system quite often, it seems like docker packaged in arch is really lagging behind and only now they decided to update it.
After this update and restarting docker I again see the newest version v0.12.5:

docker builder ls
NAME/NODE DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default * docker                           
  default default         running v0.12.5  linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386

@tonistiigi
Copy link
Member

@nikelborm That is the buildkit that is embedded into docker daemon(see driver==docker). You updated docker to 25 and that comes with buildkit v0.12.5 . If you use docker buildx create like in the commands in the previous examples, that creates a buildkit builder inside a container using moby/buildkit image. Buildx will always default to the latest release version of that image, no matter what is your local docker or buildx version.

@uliss3s
Copy link

uliss3s commented May 13, 2024

Just installed Docker 26.1.2 in an VM with Oracle Linux 8.9 and the problem remains. Executing the command "docker build ." results in failure if the base image is in an insecure registry. Looks like the "insecure-registries" property in the file "/etc/docker/daemon.json" is still being ignored.

I can manually pull the same image without problem.

Using "export DOCKER_BUILDKIT=0" still works.

docker builder version
github.com/docker/buildx v0.14.0 171fcbe

[user@host]# docker compose --verbose up -d --build --force-recreate
TRAC[0000] Docker Desktop integration not enabled       
DEBU[0000] using default config store "/home/user/.docker/buildx" 
[+] Building 0.0s (2/2) FINISHED                                                                                                                                                                    docker:default
 => [app internal] load build definition from Dockerfile                                                                                                                                                      0.0s
 => => transferring dockerfile: 439B                                                                                                                                                                          0.0s
 => ERROR [app internal] load metadata for my.private.registry:1234/docker/amazoncorretto:17                                                                                                              0.0s
------
 > [app internal] load metadata for my.private.registry:1234/docker/amazoncorretto:17:
------
DEBU[0000] using default config store "/home/user/.docker/buildx" 
DEBU[0000] serving grpc connection                      
DEBU[0000] stopping session                              span="load buildkit capabilities"
DEBU[0000] serving grpc connection                      
DEBU[0000] stopping session                             
DEBU[0000] serving grpc connection                      
DEBU[0000] stopping session                             
failed to solve: my.private.registry:1234/docker/amazoncorretto:17: failed to resolve source metadata for my.private.registry:1234/docker/amazoncorretto:17: failed to do request: Head "https://my.private.registry:1234/v2/docker/amazoncorretto/manifests/17": remote error: tls: unrecognized name

@alejandro-du
Copy link

I'm still getting "http: server gave HTTP response to HTTPS client" with Docker version 27.1.1, build 6312585.

@picolino
Copy link

Same. Issue is not fixed

@MatteoGalletta
Copy link

I fixed using sudo docker ...

@woshikid
Copy link

woshikid commented Aug 27, 2024

It seems to be fixed in v27.1.2

Update:
only works for docker linux and docker-in-docker image
still have this issue on Docker Desktop for Windows

@procinger
Copy link

procinger commented Oct 1, 2024

It seems to be broken again with v27.3.1

DOCKER_HOST=tcp://0.0.0.0:2375 docker version
Client:
 Version:           27.3.1
 API version:       1.47
 Go version:        go1.22.7
 Git commit:        ce12230
 Built:             Fri Sep 20 11:39:44 2024
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          27.3.1
  API version:      1.47 (minimum version 1.24)
  Go version:       go1.22.7
  Git commit:       41ca978
  Built:            Fri Sep 20 11:41:02 2024
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.7.22
  GitCommit:        7f7fdf5fed64eb6a7caf99b3e12efcf9d60e311c
 runc:
  Version:          1.1.14
  GitCommit:        v1.1.14-0-g2c9f560
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/feature-parity kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.