feat(docker): auto-resolve registry auth from ~/.docker/config.json#257
Merged
feat(docker): auto-resolve registry auth from ~/.docker/config.json#257
Conversation
Pulling images from private registries previously failed with HTTP 407 because the library never looked at the user's Docker credentials. Align with other Testcontainers implementations by reading `~/.docker/config.json` (honouring `DOCKER_CONFIG`) and passing an `X-Registry-Auth` header on image pulls when no explicit auth is configured on the container. Only the `auths` map is consulted. Credential helpers (`credsStore`, `credHelpers`) are intentionally out of scope for this change: when encountered they produce a debug log and resolution falls back to anonymous access so the pull can still proceed (or fail as before) rather than shelling out to a helper binary. The header value is URL-safe base64 (without padding) of a JSON payload with `username`, `password`, and `serveraddress`, per the Docker Engine API spec. Explicitly configured `Container.auth` continues to take precedence over auto-resolution, and missing/invalid config files are handled silently at debug level.
Podman rejects an X-Registry-Auth header whose `serveraddress` is a full URL (e.g. `https://index.docker.io/v1/`) with HTTP 400. The Docker Engine API spec calls for a bare domain/IP (optionally with port). Normalize the value in `Testcontainers.Docker.Auth.build_header/2` by stripping the scheme and any trailing path, and canonicalize `index.docker.io` to `docker.io` to match the Docker CLI. When auth is auto-resolved from the user's `~/.docker/config.json` (rather than set explicitly on the container config) and the pull fails with a 4xx, retry once without the header. This protects pulls against stale or otherwise invalid credentials that happen to sit in the config file on shared environments such as CI runners, where they would previously have broken the first user-visible pull. Fixes a regression seen on the rootless-podman CI job.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Testcontainers.Docker.Auth.resolve/2, which reads~/.docker/config.json(respectingDOCKER_CONFIG), looks up credentials for the target image's registry, and returns a ready-to-sendX-Registry-Authheader value (URL-safe base64 of JSON withusername,password,serveraddress, per the Docker Engine API spec).Testcontainers.maybe_pull_image/2via apull_with_fallback/2helper: whenContainer.authis not set, auto-resolution is attempted; explicitContainer.authstill takes precedence.serveraddressis normalized to a bare host (scheme and trailing path stripped;index.docker.iocanonicalized todocker.io). This matches the Docker Engine API spec and fixes a 400 from podman, which rejects full-URLserveraddressvalues.~/.docker/config.json(common on shared CI runners) therefore can't break pulls that would otherwise succeed anonymously. ExplicitContainer.authis never retried — failures there stay failures.authsentries only.credsStore/credHelpersare intentionally out of scope for this PR — if encountered we log at debug level and fall back to anonymous, rather than shelling out to a helper binary. Support for those can be added in a follow-up.Fixes #182
Test plan
mix compilemix credo --strictmix dialyzermix test— 205 tests, 0 failurestest/docker/auth_test.exscovers:docker.ioentry with a scheme-free, path-free serveraddress (regression test)nilnormalize_server_address/1strips schemes and paths, canonicalizesindex.docker.io→docker.io