26

I have a system where I'm trying to run the docker logincommand, it is a headless linux system, but unfortunately only the Docker Credentials Helper docker-credential-secretservice is installed.

This means that I get the following error:

Error saving credentials: error storing credentials - err: exit status 1, out: `Cannot autolaunch D-Bus without X11 $DISPLAY`

It makes sense that I get this as:

By default, Docker looks for the native binary on each of the platforms, i.e. “osxkeychain” on macOS, “wincred” on windows, and “pass” on Linux. A special case is that on Linux, Docker will fall back to the “secretservice” binary if it cannot find the “pass” binary. If none of these binaries are present, it stores the credentials (i.e. password) in base64 encoding in the config files described above.

And since secretservice helper uses a GUI credentials store it tries to open a window, which it can't on the headless system.

I've no control over the system, so I can't remove the /usr/bin/docker-credential-secretservice file to force docker login to fall back to the config file rather than using the secretservice helper.

What I can do is create and list files in my user's home folder. I've tried to run the command as such:

docker --config ./docker login -u <user-name> -p <password> <repository>

I was under the impression that the login command would then create a config.json in the ./docker (I've noticed docker login will create the folder if it doesn't exist). This works on a system that doesn't have any helpers installed, but not on the system in question.

I've also tried to create a ~/.docker/config.json with something like:

echo '{"credStore":""}' > ~/.docker/config.json

Hoping that docker login would get the hint not to use any helpers for the credential store.

Is there a way for a non-admin to force docker login to fall back to:

stores the credentials (i.e. password) in base64 encoding in the config files described above. Without deleting the credentials helper?

(as a side note, I'll of course ask to have the /usr/bin/docker-credential-secretservice removed but, in case it's not possible or for future reference, are there any alternative solutions?)

Christian Eriksson
  • 2,038
  • 2
  • 22
  • 28

8 Answers8

19

Logging out the current user, before logging in with a different user name worked for me. Logging out removed the saved docker credentials.

docker logout <reponame> 
docker login <reponame> 
Maya
  • 191
  • 1
  • 3
13

To avoid using a credsStore and to store a plaintext auth token in your docker config (e.g. ~/.docker/config.json), delete the "credsStore" key from your docker config file and rerun docker login.

When you run docker login, it will give a warning but will save the auth token into the file.

$ docker login
Username: someuser
Password:
WARNING! Your password will be stored unencrypted in ~/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

The resulting docker config file should look like this:

{
        "auths": {
                "your.docker.registry": {
                        "auth": "dXNlcm5hbWU6cGFzc3dvcmQK="
                }
        }
}

The auth token is simply a base64 encoded string of the form username:password.

This worked for Docker Engine versions 19 and 20.

George Pantazes
  • 1,039
  • 3
  • 12
  • 26
ahuff
  • 131
  • 1
  • 3
  • if you can, just delete or rename /usr/bin/docker-credential-pass and remove entry in ~/.docker/config.json. use of `pass` with docker is WAY TOO COMPLICATED and HUGELY ERROR PRONE. – user855443 Aug 27 '20 at 09:42
  • Deleting the `credStore` field worked for me. On the login following deleting credstore, it showed the warning and saved the auth token as a base64 in the config. Just a suggestion: using the `docker --config` option to use config in some place other than your actual `~/.docker/config.json` makes it easier to perform these messy operations without worrying about screwing up your actual config. – George Pantazes Feb 02 '21 at 20:29
9

Unfortunately, Docker (as of 18.06) first looks for the docker-credential-* binaries, and if it finds any of them, it will automatically overwrite the "credsStore" value in ~/.docker/config.json.

Your only workaround would be to install docker-credential-pass in your home directory so that Docker will use that instead of docker-credential-secretservice. docker-credential-pass does not require a GUI.

Steps to install docker-credential-pass:

docker login fails on a server with no X11 installed

wisbucky
  • 33,218
  • 10
  • 150
  • 101
  • 1
    https://github.com/docker/docker-credential-helpers mentions `pass`, but doesn't explain what `pass` is. `pass` is the Standard Unix Password Manager – cowlinator Apr 27 '20 at 21:43
  • On Windows, if it doesn't find the default `docker-credential-winpass` helper it'll just fail with an error message, it doesn't fall back to anything else, so you can't just remove the default helper, you have to define a replacement. – StampyCode Apr 25 '22 at 14:27
3

I've looked through the code and there appears to be no way to generally disable the use of credential helpers. But you can skip the code path on a per-registry basis.

https://github.com/docker/cli/blob/25eee83d6b8c475548254b2decc9c8e0490d229c/cli/config/configfile/file.go#L308 will look up the helper to use (just the suffix after docker-credential-) in credHelpers from the registry host name. If it is "" it will use the normal unencrypted file store. As far as I can tell, this is undocumented and likely unintended behavior.

With that, in order to bypass the credential helpers for a specific registry, do

mkdir ./docker
echo "{\"credHelpers\": {\"$REGISTRY_HOST\": \"\"}}" > ./docker/config.json
docker --config ./docker login -u $USERNAME -p $PASSWORD $REGISTRY_HOST

I believe the cause why {"credsStore":""} isn't working is the omitempty serialization tag on that field. Setting it to empty is the same as not setting it.

  • WFM, Docker desktop 4.17. I added this to my config.json: `"credHelpers": { "artifactory.example.com": "", "docker.io": "" }` – Marvin Mar 29 '23 at 20:20
1

You can just ignore all the output by sending everything to /dev/null like:

echo $TOKEN|docker login -u=user --password-stdin myregistry.com > /dev/null 2>&1
where $TOKEN will be your previously exported token or password.

This will be useful as well with CI's when using some automation

isca
  • 986
  • 8
  • 9
1

Simply rename ~/.docker/config.json to something different, or remove it if you won't need it anymore.

mv ~/.docker/config.json ~/.docker/backup-config.json

nuclear_party
  • 91
  • 1
  • 5
0

Not an answer to the question, but maybe to the problem:

We can launch dbus ourselves then unlock/lock/query the keyring from the cli.

These are the bash functions I use:

function unlock-keyring () {
export $(dbus-launch)
read -rsp "Password: " pass
export $(echo -n "$pass" | gnome-keyring-daemon --unlock)
unset pass
}

function lock-keyring () {
dbus-send --dest=org.gnome.keyring --print-reply /org/freedesktop/secrets org.freedesktop.Secret.Service.LockService
}

function query-keyring-locked () {
busctl --user get-property org.freedesktop.secrets /org/freedesktop/secrets/collection/login org.freedesktop.Secret.Collection Locked
}

https://unix.stackexchange.com/questions/473528/how-do-you-enable-the-secret-tool-command-backed-by-gnome-keyring-libsecret-an

https://superuser.com/questions/700826/how-to-lock-a-unlocked-gnome-keyring

https://superuser.com/questions/1618970/query-status-of-gnome-keyring

https://unix.stackexchange.com/questions/602313/unlock-gnome-keyring-daemon-from-command-line

Simon Allfrey
  • 51
  • 1
  • 6
0

This will do the trick just to avoid the nag:

echo ${DOCKERPW} | docker login -u ${DOCKERUSER} --password-stdin 2> /dev/null