This repo contains the source for two separate tools:

  • docker-credential-magic - credential helper which proxies auth to other helpers based on domain name
  • docker-credential-magician - tool to augment images with various credential helpers (including magic)

The following third-party Docker credential helpers are currently supported:


Download latest release tarball
for your system and install both tools manually:

cat docker-credential-magic*.tar.gz | tar x -C /usr/local/bin 'docker-credential-magic*'


How to use docker-credential-magic

$ echo <domain> | docker-credential-magic get

The following example shows how docker-credential-magic can be used to
proxy auth to docker-credential-gcr, based on the detection of a * domain:

Note: Example requires docker-credential-gcr
to be pre-installed

$ export GOOGLE_APPLICATION_CREDENTIALS="${PWD}/service-account-key.json"
$ echo "" | docker-credential-magic get

Note: docker-credential-magic is a "read-only" credential helper, and does not modify credentials in any way (some helpers implement other subcommands like store or erase).

Local setup

The primary purpose of magic is to be added to images via magician.
However, you may wish to also use this tool on your local machine.

It is required that mappings files for each supported helper are present on
disk. The environment variable DOCKER_CREDENTIAL_MAGIC_CONFIG is used by magic
to find these files, nested under an etc/ subdirectory.

If DOCKER_CREDENTIAL_MAGIC_CONFIG is not set, magic respects the
XDG Base Directory Specification,
looking for mappings files under $XDG_CONFIG_HOME/magic/etc/.
This is equivalent to the following on each operating system:

  • Linux: $HOME/.config/magic/etc/
  • macOS: $HOME/Library/Application Support/magic/etc
  • Windows: %APPDATA%\magic\etc

magic has a useful subcommand, init, which will auto-create this directory
and populate it with the default mappings files, as well as a catch-all
Docker config.json file in the parent directory:

$ docker-credential-magic init
Creating directory '/Users/me/Library/Application Support/magic/etc' ...
Creating mapping file '/Users/me/Library/Application Support/magic/etc/aws.yml' ...
Creating mapping file '/Users/me/Library/Application Support/magic/etc/azure.yml' ...
Creating mapping file '/Users/me/Library/Application Support/magic/etc/gcp.yml' ...
Creating magic config file '/Users/me/Library/Application Support/magic/config.json' ...

magic has another subcommand, home, which you can use to
modify the DOCKER_CONFIG env var to point to the magic directory:

$ export DOCKER_CONFIG="$(docker-credential-magic home)"

You may wish to add the previous command to your ~/.bashrc / ~/.bash_profile.

If no matching domains are found, magic will fall back to use
your existing $HOME/.docker/config.json.

Note: At this time, magic will not automatically install the supported
helpers on your machine. You should install each of these manually.
For example, to install ecr-login on macOS via Homebrew:

$ brew install docker-credential-helper-ecr

How to use docker-credential-magician

$ docker-credential-magician mutate <ref>

The following example shows how docker-credential-magician can be used to
(1) augment the cosign image with
various credential helpers, (2) set the default credential store to magic,
and (3) push the new image to a registry running at localhost:5000:

$ docker-credential-magician mutate \ \
    -t localhost:5000/cosign:v0.5.0-magic
2021/07/29 17:06:59 Pulling ...
2021/07/29 17:07:01 Adding /opt/magic/etc/aws.yml ...
2021/07/29 17:07:01 Adding /opt/magic/etc/azure.yml ...
2021/07/29 17:07:01 Adding /opt/magic/etc/gcp.yml ...
2021/07/29 17:07:01 Adding /opt/magic/bin/docker-credential-ecr-login ...
2021/07/29 17:07:01 Adding /opt/magic/bin/docker-credential-acr-env ...
2021/07/29 17:07:01 Adding /opt/magic/bin/docker-credential-gcr ...
2021/07/29 17:07:01 Adding /opt/magic/bin/docker-credential-magic ...
2021/07/29 17:07:01 Adding /opt/magic/config.json ...
2021/07/29 17:07:02 Prepending PATH with /opt/magic/bin ...
2021/07/29 17:07:02 Setting DOCKER_CONFIG to /opt/magic ...
2021/07/29 17:07:02 Setting DOCKER_CREDENTIAL_MAGIC_CONFIG to /opt/magic ...
2021/07/29 17:07:02 Pushing image to localhost:5000/cosign:v0.5.0-magic ...
2021/07/29 17:07:04 Done.
$ docker run --rm --entrypoint sh \
    localhost:5000/cosign:v0.5.0-magic \
    -c 'ls -lah /opt/magic/etc && \
        ls -lah /opt/magic/bin &&
        env | grep DOCKER_ &&
        cat $DOCKER_CONFIG/config.json'
total 20K
drwxr-xr-x    2 root     root        4.0K Jul 29 21:00 .
drwxr-xr-x    4 root     root        4.0K Jul 29 21:00 ..
-r-xr-xr-x    1 root     root          45 Jan  1  1970 aws.yml
-r-xr-xr-x    1 root     root          40 Jan  1  1970 azure.yml
-r-xr-xr-x    1 root     root          44 Jan  1  1970 gcp.yml
total 25M
drwxr-xr-x    2 root     root        4.0K Jul 29 21:00 .
drwxr-xr-x    4 root     root        4.0K Jul 29 21:00 ..
-r-xr-xr-x    1 root     root        8.7M Jan  1  1970 docker-credential-acr-env
-r-xr-xr-x    1 root     root        7.8M Jan  1  1970 docker-credential-ecr-login
-r-xr-xr-x    1 root     root        5.6M Jan  1  1970 docker-credential-gcr
-r-xr-xr-x    1 root     root        3.0M Jan  1  1970 docker-credential-magic

If the -t / --tag flag is not provided, magician will default to
publishing the image back to its original location (overwriting the existing tag).

Note: At this time, docker-credential-magician is only designed for x86–64/AMD64 Linux containers.
More platforms may be supported in the future.

Including a subset of helpers

You may specify the -i / --include flag (one or more times) to
limit the helpers that are added to the image.

For example, to only include the azure and gcp helpers:

$ docker-credential-magician mutate \
    -i azure -i gcp

Note: These each must match one of the supported helpers found in the
mappings/ directory.

Using custom mappings and/or helpers

In some scenarios, you may wish to supply a custom directory of mappings,
for example to add extra domains. Or, you may wish to supply a custom
directory of helper binaries, if you need to use a different version of
a helper, or add your own.

For these cases, you can use the following flags:

  • --mappings-dir <custom_mappings_dir>
  • --helpers-dir <custom_helpers_dir>

Please note that all mappings and helpers must be provided (as in, magician will
not automatically resolve any missing binaries in <custom_helpers_dir>).

In addition, all helpers in <custom_helpers_dir> must be built for
a Linux amd64 architecture.

Lastly, the magic helper will always be sourced from
the one baked into magician.

Go library

You may wish to make use of magician functionality in your Go application.

Here is a Go example which mimics the command-line example found above:

package main

import (

func main() {
	src := ""
	dst := "localhost:5000/cosign:v0.5.0-magic"

	err := magician.Mutate(src, magician.MutateOptWithTag(dst))
	if err != nil {

Note: since magician makes use of embedded files (helper binaries and mappings), if you try
running this example, you will see errors such as the following:

pattern embedded/*: no matching files found

To fix this, you must manually populate these directories in your GOPATH
after running go mod tidy:

git clone tmp/
pushd tmp/
make clean vendor fetch-helpers copy-mappings build-magic-embedded
for d in $(find "$(go env | grep GOPATH | awk -F "=" '{print $2}' | tr -d '"')/pkg/mod/" -mindepth 1 -maxdepth 1 -type d); do
  sudo cp -r tmp/internal/embedded/helpers/embedded "${d}/internal/embedded/helpers" || true
  sudo cp -r tmp/internal/embedded/mappings/embedded "${d}/internal/embedded/mappings" || true
rm -rf tmp/

(If there is an easier way to approach this, please let us know)

Project history

The original concept for this project and its design
can be found in the following GitHub conversations:

If you are interested in understanding how Docker credential helpers work,
you may enjoy
this image.


Contributions are welcome!

Prior to submitting a
pull request,
please check the list of
open issues.
If there is not an existing issue related to your changes, please open a
new issue to first discuss your thoughts with the project maintainers.