docker / docker/cli

saving configuration file is not forward-compatible

Open
#5,559 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area/authentication area/manifest kind/enhancement
Dominant language
Go
Stars
6.1k
Forks
2.2k
Avg merge
1d 15h
Merged PRs (30d)
43

Description

Description

The config/configfile package always uses the current schema of the config-file to save the file to disk. This can be problematic, as there's many code-bases that use this code to authenticate (and store credentials), and those code-bases may be using an older version of the code. For example, go-containerregistry up until recently (previous patch release) used v24.0 as dependency;
https://github.com/google/go-containerregistry/blob/v0.20.1/go.mod#L7

Those libraries will continue to work, because they're only using the "auths" field from the configuration file, but if someone would log in using those tools they may be discarding configuration options from the config-file. As an example, https://github.com/docker/cli/commit/c5016c6d5ba4d8c6a4e258a926d46fe420b476f2 (https://github.com/docker/cli/pull/4376) introduced a new "features" field in the CLI configuration file. That change is part of Docker v26.1 and up, but older versions are not aware of it.

Reproducer

I'm running this inside a container, which doesn't have a credentials-helper configured. The container has an older version of the Docker CLI (v25.0);

$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock docker:25.0-cli sh

$ docker --version
Docker version 25.0.5, build 5dc9bcc

Inside the container, I create a config-file in a temporary directory that contains experimental and features fields;

$ mkdir temp-config
$ echo '{"experimental":"enabled", "features":{"hooks": "true", "something-else": "false"}}' > temp-config/config.json

When running docker login or docker logout, the config is overwritten with only fields known by that version of the code;

$ cat ./temp-config/config.json
{"experimental":"enabled", "features":{"hooks": "true", "something-else": "false"}}

$ docker --config=./temp-config/ logout
Removing login credentials for https://index.docker.io/v1/

$ cat temp-config/config.json
{
	"auths": {},
	"experimental": "enabled"
}

Some other actions, such as switching the context will result in the same;

# reset the config-file
$ echo '{"experimental":"enabled", "features":{"hooks": "true", "something-else": "false"}}' > temp-config/config.json

$ docker --config=./temp-config/ context create somecontext
somecontext
Successfully created context "somecontext"

$ cat ./temp-config/config.json
{"experimental":"enabled", "features":{"hooks": "true", "something-else": "false"}}

$ docker --config=./temp-config/ context use somecontext
somecontext
Current context is now "somecontext"

$ cat ./temp-config/config.json
{
	"auths": {},
	"experimental": "enabled",
	"currentContext": "somecontext"
}

Solutions

The overall design of configuration file(s) as used by the CLI and plugins needs some re-thinking. This problem is partially because we have a poor separation of "config" and "state"; storing authentication in the config-file itself was never a great choice (and amplifies this issue), and ideally, the CLI would not mutate settings created by the user (or at least limited to actual config changes, not "state").

For actions mentioned (login, logout, switching default context), we only modify a single field in the config-file any other changes present in the config file don't have to be "understood" by the code, and we could change the code to "patch" the config-file.

i.e., when updating the config-file;

  1. read the config into a generic map[string]any
  2. patch the field to update (auths or currentContext)
  3. marshal the map[string]any to JSON and write it to the file.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the config/configfile package and reproducing the Docker 25.0 login, logout, or context-switch behavior described above. The change is complete when updating auths or currentContext preserves unknown configuration fields such as features, while the existing configuration behavior remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.