buildx icon indicating copy to clipboard operation
buildx copied to clipboard

`docker build` fails to authenticate with private repository

Open alexhendel opened this issue 2 years ago • 37 comments

Description

I have noticed an issue using private repositories with authentication since upgrading to the latest docker version with Docker Engine v23.

Using basic auth (no credential helper) docker pull can pull the image from the private repository (Nexus in my case) after running docker login. But running docker build . fails with the following error:

] Building 0.1s (3/3) FINISHED                                                                                                                                                                                  
 => [internal] load build definition from Dockerfile                                                                                                                                                         0.0s
 => => transferring dockerfile: 100B                                                                                                                                                                         0.0s
 => [internal] load .dockerignore                                                                                                                                                                            0.0s
 => => transferring context: 2B                                                                                                                                                                              0.0s
 => ERROR [internal] load metadata for ***/moembed/runtime:4.0.0-arm64v8                                                                                                                       0.1s
------
 > [internal] load metadata for ***/moembed/runtime:4.0.0-arm64v8:
------
Dockerfile:1
--------------------
   1 | >>> FROM ***/moembed/runtime:4.0.0-arm64v8
   2 |     CMD echo
   3 |     
--------------------
ERROR: failed to solve: ***/moembed/runtime:4.0.0-arm64v8: pulling from host *** failed with status code [manifests 4.0.0-arm64v8]: 401 Unauthorized

Since docker pull will pull the image from the private registry after docker login the following steps will lead to a successful build:

  • docker login some.registry.com
  • docker pull some.registry.com/image
  • docker build .

I found that the behavior is similar to docker/cli#3716 but only started for me after installing docker with Docker Engine v23.

Reproduce

  1. docker login some.registry.com
  2. Create Dockerfile with relevant content (with FROM clause referring to a private registry image)
  3. docker build .

Expected behavior

docker build should use the given credentials after a docker login and successfully pull the referenced image from the given registry.

docker version

Client: Docker Engine - Community
 Version:           23.0.0
 API version:       1.42
 Go version:        go1.19.5
 Git commit:        e92dd87
 Built:             Wed Feb  1 17:46:28 2023
 OS/Arch:           linux/arm64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          23.0.0
  API version:      1.42 (minimum version 1.12)
  Go version:       go1.19.5
  Git commit:       d7573ab
  Built:            Wed Feb  1 17:46:28 2023
  OS/Arch:          linux/arm64
  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 info

Client:
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.10.2
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.15.1
    Path:     /usr/libexec/docker/cli-plugins/docker-compose

Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 3
 Server Version: 23.0.0
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 31aa4358a36870b21a992d3ad2bef29e1d693bec
 runc version: v1.1.4-0-g5fd4c4d
 init version: de40ad0
 Security Options:
  apparmor
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 5.15.0-58-generic
 Operating System: Ubuntu 22.04.1 LTS
 OSType: linux
 Architecture: aarch64
 CPUs: 3
 Total Memory: 5.779GiB
 Name: ubuntu-vm
 ID: e8b9743c-f49f-407c-8d8f-e0c56ad58277
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

Additional Info

No response

alexhendel avatar Feb 08 '23 14:02 alexhendel

@crazy-max @jedevc PTAL; at a glance I don't see [auth] in the output (ISTR BuildKit includes that if it's handling authentication?). Should this be moved to the buildx issue tracker?

thaJeztah avatar Feb 08 '23 15:02 thaJeztah

@alexhendel out of curiosity, if you run with docker buildx build instead of just docker build (after making sure the image hasn't been pulled locally) does it still break?

jedevc avatar Feb 08 '23 17:02 jedevc

Actually shows the same result. buildx build will error out. But running docker pull will pull the image without errors and buildx build directly after that doesn't fail..

~/source/docker-test$ sudo docker buildx build .
[+] Building 0.1s (3/3) FINISHED                                                                                                                                                         
 => [internal] load .dockerignore                                                                                                                                                   0.0s
 => => transferring context: 2B                                                                                                                                                     0.0s
 => [internal] load build definition from Dockerfile                                                                                                                                0.0s
 => => transferring dockerfile: 100B                                                                                                                                                0.0s
 => ERROR [internal] load metadata for ***/moembed/runtime:4.0.0-arm64v8                                                                                              0.1s
------
 > [internal] load metadata for ***/moembed/runtime:4.0.0-arm64v8:
------
Dockerfile:1
--------------------
   1 | >>> FROM ***/moembed/runtime:4.0.0-arm64v8
   2 |     CMD echo
   3 |     
--------------------
ERROR: failed to solve: ***/moembed/runtime:4.0.0-arm64v8: pulling from host *** failed with status code [manifests 4.0.0-arm64v8]: 401 Unauthorized

~/source/docker-test$ sudo docker pull ***/moembed/runtime:4.0.0-arm64v8
4.0.0-arm64v8: Pulling from moembed/runtime
Digest: sha256:2fac5f0e2e94fbd4d03658b7f8aa840a7c6089bfe0ad4ceffd055ea0d649ffe2
Status: Downloaded newer image for ***/moembed/runtime:4.0.0-arm64v8
***/moembed/runtime:4.0.0-arm64v8

~/source/docker-test$ sudo docker buildx build .
[+] Building 0.0s (5/5) FINISHED                                                                                                                                                         
 => [internal] load .dockerignore                                                                                                                                                   0.0s
 => => transferring context: 2B                                                                                                                                                     0.0s
 => [internal] load build definition from Dockerfile                                                                                                                                0.0s
 => => transferring dockerfile: 100B                                                                                                                                                0.0s
 => [internal] load metadata for ***/moembed/runtime:4.0.0-arm64v8                                                                                                    0.0s
 => CACHED [1/1] FROM ***/moembed/runtime:4.0.0-arm64v8                                                                                                               0.0s
 => exporting to image                                                                                                                                                              0.0s
 => => exporting layers                                                                                                                                                             0.0s
 => => writing image sha256:a48d05fdcf8e508d0a8114f132f5ab2e4790e28ed425638a2ac04a0ee212b92

alexhendel avatar Feb 08 '23 18:02 alexhendel

@alexhendel what does your ~/.docker/config.json look like?

⚠️ ⚠️ the file may contain your credentials if you're not using a credentials helper, so be sure to sanitize those parts before posting

thaJeztah avatar Feb 08 '23 18:02 thaJeztah

The config json below (I replaced the actual values with ***):

The registry value is what I would expect and the auth value appears to be hashed string.

{
        "auths": {
                "***": {
                        "auth": "***"
                }
        }
}

alexhendel avatar Feb 08 '23 18:02 alexhendel

Thanks! Yes, that looks fairly standard (was curious if perhaps a credential-helper was in use somewhere).

Do you happen to know what kind of registry is running on your some.registry.com ? (of course, if you can disclose, just looking for information that could help investigate)

thaJeztah avatar Feb 08 '23 22:02 thaJeztah

@thaJeztah sounds good to move to buildx repo 🎉

jedevc avatar Feb 09 '23 00:02 jedevc

Done!

thaJeztah avatar Feb 09 '23 00:02 thaJeztah

Are you using a remote server and is it possible the registry does additional authentication based on IP? If yes, does setting BUILDKIT_NO_CLIENT_TOKEN=true make any difference?

"***": {

Is this a clean domain like in the reference you are pulling, or URL with some protocol/path?

tonistiigi avatar Feb 09 '23 00:02 tonistiigi

Are you using a remote server and is it possible the registry does additional authentication based on IP? If yes, does setting BUILDKIT_NO_CLIENT_TOKEN=true make any difference?

We are using Sonatype Nexus to host a private registry. I am not sure about the IP-based authentication.

Where would I configure BUILDKIT_NO_CLIENT_TOKEN=true?

"***": {

Is this a clean domain like in the reference you are pulling, or URL with some protocol/path?

This value is a clean domain. No path or protocol.

alexhendel avatar Feb 09 '23 06:02 alexhendel

We did some additional testing which might give some more details. We did try podman and ran:

podman pull
podman build .

This behaves like the previous Docker version, build and pull work fine. Checking the network traffic the only difference we could find was an additional HEAD request with v23 (which was not sent previously and is also not sent by podman).

alexhendel avatar Feb 09 '23 12:02 alexhendel

We have experienced the exactly same issue with docker 23.0.1 against private images in GitHubs ghcr.io-registry. Adding BUILDKIT_NO_CLIENT_TOKEN=true fixed the issue for us. Also downgrading to 20.x.x solved the issue.

posti-vpk avatar Feb 15 '23 13:02 posti-vpk

I can confirm that BUILDKIT_NO_CLIENT_TOKEN=1 works for us (we are using docker 23, and the private registry is artifactory with client certificate required for authentication).

tgquan67 avatar Mar 20 '23 09:03 tgquan67

I can confirm that BUILDKIT_NO_CLIENT_TOKEN=1 works for us (we are using docker 23, and the private registry is artifactory with client certificate required for authentication).

@tgquan67 What version of Artifactory are you using? I can't seem to get it to work with Artifactory 7.49.3.

krische avatar Jun 22 '23 18:06 krische

BUILDKIT_NO_CLIENT_TOKEN=1 suggests that the difference is in some network layer and only the daemon can connect to the auth server. The code itself should be identical.

tonistiigi avatar Jun 22 '23 19:06 tonistiigi

So BUILDKIT_NO_CLIENT_TOKEN=1 is supposed to be an environment variable for the daemon process? Not the client?

krische avatar Jun 22 '23 19:06 krische

No, on the client. BUILDKIT_NO_CLIENT_TOKEN=1 docker buildx build ...

tonistiigi avatar Jun 22 '23 19:06 tonistiigi

No, on the client. BUILDKIT_NO_CLIENT_TOKEN=1 docker buildx build ...

Yup, that's what I was trying but still no luck. What's odd for me is it does seem like my layers are pushed to my Artifactory successfully, but when it tries to push the manifest then Artifactory responds with a 403. And since I'm on a nearly 6 month old version of Artifactory, I'm not 100% certain the issue with is with buildkit/buidx.

I'll have to update my Artifactory and try again.

krische avatar Jun 22 '23 21:06 krische

@tonistiigi related to these?

  • https://github.com/containerd/containerd/issues/4982
  • https://github.com/containerd/containerd/pull/3913
  • https://github.com/containerd/containerd/pull/3912
  • https://github.com/containerd/containerd/pull/4983

Last one has further details (it was rejected at the time); https://github.com/containerd/containerd/pull/4983#issuecomment-798727645

thaJeztah avatar Jun 22 '23 21:06 thaJeztah

What version of Artifactory are you using? I can't seem to get it to work with Artifactory 7.49.3.

I'm on artifactory 7.41 and it worked. Btw, in my case I only test if it can pull the base image from artifactory, I did not try to push it with buildx. Maybe disable buildkit with DOCKER_BUILDKIT=0 and see if it works first, and then check how you authenticate with artifactory.

tgquan67 avatar Jun 22 '23 22:06 tgquan67

No, these seem to be about HTTP request methods,

tonistiigi avatar Jun 22 '23 22:06 tonistiigi

I updated my Artifactory to their newest version, but still no luck. However, I did try docker login with the admin account of my Artifactory and that worked. So I don't think my issue is with buildx but something with my Artifactory.

krische avatar Jun 23 '23 13:06 krische

Yup, it was just a permission issue on my Artifactory that caused the 403 when buildkit was trying to HEAD to see if the manifest was already there before the PUT to upload it. I fixed the permission issue and it worked. It even works for me without setting BUILDKIT_NO_CLIENT_TOKEN=1.

krische avatar Jun 23 '23 15:06 krische

Now I test it again on docker 24, it works even without BUILDKIT_NO_CLIENT_TOKEN=1 on the default builder; but if i create a new builder (for example with docker buildx create --name test --driver=docker-container), I have no way to make it work when this new builder is in use (with docker buildx use test).

tgquan67 avatar Jul 19 '23 12:07 tgquan67

Same issue here!

typoworx-de avatar Aug 24 '23 07:08 typoworx-de

The issue persists on docker 24.0.7 and buildx v0.11.2.

fredericoschardong avatar Jan 21 '24 15:01 fredericoschardong

I'm still seeing this on docker 25.0.3 and buildx v0.12.1

$ docker --version
Docker version 25.0.3, build 4debf41

$ docker buildx version
github.com/docker/buildx v0.12.1-desktop.4 6996841df2f61988c2794d84d33205368f96c317

ryan-ph avatar Apr 08 '24 23:04 ryan-ph

same issue here

marco-bertelli avatar May 24 '24 13:05 marco-bertelli

@alexhendel just curious if you ever resolved this on your side? We're using Nexus and facing the same thing. Works with legacy builder, just not BuildKit.

whitfin avatar May 31 '24 18:05 whitfin

Another update: at some point after docker 25 update, it started working in my case (artifactory 7.41) with BUILDKIT_NO_CLIENT_TOKEN=1. Also since I have client certificate requirement for my registry, I also have this file at /etc/buildkitd.toml:

debug = true
[registry."artifactory.myregistry.net"]
  ca=["/opt/myregistry/certs/ca.crt"]
  [[registry."artifactory.myregistry.net".keypair]]
    key="/opt/myregistry/certs/client.key"
    cert="/opt/myregistry/certs/client.pem"

Create a new builder with

docker buildx create --use --bootstrap --name basic-builder --driver docker-container --config /etc/buildkitd.toml

And I also export these 3 variables:

export BUILDKIT_NO_CLIENT_TOKEN=1
export DOCKER_BUILDKIT=1
export BUILDX_BUILDER=basic-builder

After this in dockerfiles I can pull from artifactory.myregistry.net using credentials I logged in with docker login artifactory.myregistry.net.

tgquan67 avatar Jun 06 '24 00:06 tgquan67