Skip to content

config: hard failure when Docker config.json is missing #149

@mdelapenya

Description

@mdelapenya

Problem

On machines without traditional Docker installed, any operation that requires registry credentials hard-fails because config.Load() requires ~/.docker/config.json to exist on disk.

Reproduction:

ERROR: failed to create sandbox: create sandbox: create sandbox: run sandbox:
  apply definition hook: failed to retrieve registry credentials for
  docker/sandbox-templates:shell: load config: config path:
  config file does not exist (C:\Users\docker\.docker\config.json)

This machine has no ~/.docker/ directory and no config.json.

Root Cause

The error chain is a cascade of hard failures with no graceful fallback:

1. config/load.go — hard-fails on missing files

  • Dir() (line ~61): returns error if ~/.docker directory doesn't exist
  • Filepath() (line ~85): returns error if config.json doesn't exist
  • Load() (line ~106): calls Filepath(), propagates the error as "config path: %w"

2. config/auth.go — no fallback to credential helpers

  • AuthConfigs() (line ~18): calls Load(), wraps error as "load config: %w", returns immediately
  • AuthConfigForHostname() (line ~31): same behavior — contradicts its own docstring which claims it "will attempt to load registry credentials using the default credential helper for the platform"

3. Image pull propagates the failure

  • image/options.go:59WithCredentialsFromConfig() calls AuthConfigs(), propagates error
  • image/pull.go:70 — wraps as "set credentials for pull option: %w"
  • container/lifecycle.go:321defaultPullHook calls image.Pull() → hard-fail

What Should Happen

When config.json is missing, the auth functions should:

  1. Not fail — a missing config file is a valid state (fresh install, CI environments, alternative runtimes)
  2. Fall through to credential helpersconfig/credentials_helpers.go already implements platform-specific helpers (wincred, osxkeychain, pass, secretservice) but they're never reached because Load() fails first
  3. Return empty credentials as a last resort — public images don't need auth

Existing graceful pattern in this repo

context/current.go:25-26 already handles missing config correctly:

if os.IsNotExist(err) {
    return DefaultContextName, nil  // Graceful fallback
}

This pattern should be replicated in the auth functions.

Proposed Solution

The docker/secrets-engine project handles credential retrieval robustly without requiring a Docker config file on disk. The secrets-engine team should be well-positioned to contribute a fix here that:

  1. Makes config.Load() / auth functions tolerate a missing config file
  2. Integrates with secrets-engine for credential resolution when config.json is absent
  3. Falls back to platform credential helpers (already implemented in credentials_helpers.go but unreachable)
  4. Returns empty credentials as a final fallback for public registries

Files That Need Changes

File Function Issue
config/load.go Dir(), Filepath() Hard-fails if ~/.docker or config.json missing
config/auth.go AuthConfigs() Doesn't fallback to credential helpers on missing config
config/auth.go AuthConfigForHostname() Same — contradicts its own docstring
image/options.go WithCredentialsFromConfig() No fallback to empty credentials

cc @docker/secrets-engine team

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions