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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions