Docker fails to login when using htpasswd with latest registry 3.0

  • docker-ce-cli: 5:29.1.3-1~ubuntu.25.10~questing
  • registry: latest (3.0)

Here are the basic steps of my workflow:

docker-compose.yml:

services:
  registry:
    image: 'registry:latest'
    ports:
      - "5000:5000"
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry
    volumes:
      - type: bind
        source: ../auth
        target: /auth
        read_only: True

Folders below $hub_path:

├── auth
│   └── htpasswd
├── docker-compose
│   └── docker-compose.yml
├── images

Adding a user credentials to the Docker registry with:

echo "$hub_password" | htpasswd -b -i -B -c "${hub_path}/auth/htpasswd" $hub_user

Building, creating and starting the Docker hub registry container with the images mount as read only with:

cd "${hub_path}/docker-compose"
docker compose -f docker-compose.yml -f docker-compose.yml up --detach

Restarting the Docker hub registry:

docker compose restart
sleep 30

Testing user credentials over the Docker registry:

echo “$hub_password” | docker login --username $hub_user --password-stdin 127.0.0.1:5000
error saving credentials: error storing credentials - err: exit status 1, out: `pass not initialized: exit status 1: Error: password store is empty. Try "pass init".`

There was no such issue with registry 2.8.

Any suggestion? It looks like something has changed with registry 3.0 that triggers that issue, but what?

It doesn’t look relatd to registry versions. The error message appears when the docker login command depends on “pass” to store the credentials. That can be set in the docker client settings in $HOME/.docker/config.json. If “credsStore” is pass and you don’t have “pass” installed or its path is not available in $PATH, you will get that error message.

https://docs.docker.com/reference/cli/docker/login/#credential-stores

I used your files (thank youf or shating your config to reproduce the issue) and it worked for me until I deleted /usr/bin/pass.

I understand that you wrote it worked before, but something must have happaned that changed your setting or you didn’t remember that you did something differently compared to what you did before. I tried this with Docker CE 29.1..2 and then with 29.1.3 after an upgrade.

Except that:

  • there is no $HOME/.docker/config.json defined.
  • pass is available in /usr/bin/pass in the $PATH
  • what is the required configuration in config.json to tell docker to use the credentials already defined in /auth/htpasswd?

I used your files (thank youf or shating your config to reproduce the issue) and it worked for me until I deleted /usr/bin/pass

You must have done something else to make it work, please share.

OK, so it seems it is now absolutely necessary to initialize “pass” using a gpg key and set a .$HOME/.docker/config.json with “credsStore”: “pass”.

In the past, it was not necessary with older docker releases.

I feel there should be no required configuration except not configuring “pass” as credential store. I understand your situation that it looks like it is caused by the registry, but you would have the same issue with other registries, including Docker Hub, unless the password is already added to the config.json.

I wanted to show you what exactly I did and that there is nothing different, and I got the error message. So I tried to figure out why and it feels like a client bug. The login worked for me when I tested it first, because I started the testing with a renamed “pass” binary, so Dcoker couldn’t find it. It logged in and the plain text password was added to the config json. Next time the password was read from it when I restored the original “pass” binary.

It looks like the Docker client detects /usr/bin/pass and also /usr/local/bin/docker-credential-pass. When both are available, it automatically wants to use “pass”. I tried to change it by setting "credsStore": "" in the config json, but didn’t help. Then I tried the “credHelpers” config.

{
	"credHelpers": {
		"127.0.0.1:5000": ""
	}
}

Then it worked. The “credHelpers” parameter can set a credential helper for specific registry which than uses a specific credential store. In this case we manually disable using any credential helper. I’m not sure why it is needed, but you can use it as a workaround..

1 Like

I’m surprised you couldn’t login with pass set as credsStore as explained in my previous post.

Because once setup that way, it worked perfectly fine. The only trap I encountered is when I tried to import an existing private GPG key from another computer to be used with pass init; I discovered later on that I had to import its owner trus( as well to be able to use it in this setup.

Bottom line,

  • it is now required to initialize $HOME/.docker/config.json to be able to login with the latest docker binaries
  • it is possible to docker login with pass as credsStore as long as it is initialized first with a trusted GPG key.
  • you showed that it can also be initialized using a specific setting for credHelpers.
  • the latest registry 3.0 is not linked to this issue

I don’t think I wrote that. I am sorry if I was confusing. I had no problem with logging in with pass, I just explained that it should not be required. The only thing I could not do first is disabling pass when the binaries were on my system. Everything I wrote in my previous post was do demonstrate that and how I eventually found out the right config to disable that.

Of course, if you wan to use pass, thats okay. If it causes any trouble to you in the future, I hope my previous post can still help.