GoogleContainerTools/skaffold · error

docker build options, secrets and ssh, require BuildKit - se

Error message

docker build options, secrets and ssh, require BuildKit - set `useBuildkit: true` in your config, or run with `DOCKER_BUILDKIT=1`

What it means

Skaffold's local Docker daemon builder refuses to build a Docker artifact that uses build-time secrets or SSH agent forwarding, because those features only work with BuildKit. The daemon path uses the legacy docker build API when BuildKit is disabled, which cannot service `secrets` or `ssh` options, so CheckCompatible fails fast with an actionable message instead of a cryptic remote error.

Source

Thrown at pkg/skaffold/docker/image.go:328

	if err == nil {
		if err := json.Unmarshal(raw, cfg); err != nil {
			return nil, err
		}
	} else {
		cfg, err = RetrieveRemoteConfig(image, l.cfg, v1.Platform{})
		if err != nil {
			return nil, err
		}
	}

	l.imageCache[image] = cfg

	return cfg, nil
}

func (l *localDaemon) CheckCompatible(a *latest.DockerArtifact) error {
	if len(a.Secrets) > 0 || a.SSH != "" {
		return fmt.Errorf("docker build options, secrets and ssh, require BuildKit - set `useBuildkit: true` in your config, or run with `DOCKER_BUILDKIT=1`")
	}
	return nil
}

// Build performs a docker build and returns the imageID.
func (l *localDaemon) Build(ctx context.Context, out io.Writer, workspace string, artifact string, a *latest.DockerArtifact, opts BuildOptions) (string, error) {
	log.Entry(ctx).Debugf("Running docker build: context: %s, dockerfile: %s", workspace, a.DockerfilePath)

	if err := l.CheckCompatible(a); err != nil {
		return "", err
	}
	imageInfoEnv, err := EnvTags(opts.Tag)
	if err != nil {
		return "", fmt.Errorf("couldn't parse image tag: %w", err)
	}
	buildArgs, err := EvalBuildArgsWithEnv(opts.Mode, workspace, a.DockerfilePath, a.BuildArgs, opts.ExtraBuildArgs, imageInfoEnv)
	if err != nil {
		return "", fmt.Errorf("unable to evaluate build args: %w", err)

View on GitHub (pinned to a1189de023)

Solutions

  1. Set `useBuildkit: true` on the artifact/builder in your skaffold.yaml
  2. Run skaffold with DOCKER_BUILDKIT=1 exported in the environment
  3. Remove the `secrets`/`ssh` entries from the Docker artifact if they are not needed, replacing them with plain build args where acceptable

Example fix

// before
build:
  artifacts:
    - image: myapp
      docker:
        dockerfile: Dockerfile
        secrets:
          - id: npm_token,src:/npm_token.txt
// after
build:
  artifacts:
    - image: myapp
      docker:
        dockerfile: Dockerfile
        useBuildkit: true
        secrets:
          - id: npm_token,src:./npm_token.txt
Defensive patterns

Strategy: validation

Validate before calling

func usesBuildkitOnlyFeatures(a *latest.DockerArtifact) bool {
	return len(a.Secrets) > 0 || a.SSH != ""
}
if usesBuildkitOnlyFeatures(artifact) && os.Getenv("DOCKER_BUILDKIT") != "1" {
	// enable BuildKit before calling Build
}

Type guard

func needsBuildkit(a *latest.DockerArtifact) bool { return a != nil && (len(a.Secrets) > 0 || a.SSH != "") }

Try / catch

if err := daemon.CheckCompatible(artifact); err != nil {
	// surface guidance: enable BuildKit or drop secrets/ssh
	return fmt.Errorf("build incompatible: %w", err)
}

Prevention

When it happens

Trigger: Calling localDaemon.Build on a *latest.DockerArtifact whose `Secrets` list is non-empty or whose `SSH` field is set, while the skaffold config has useBuildkit disabled/unset and DOCKER_BUILDKIT is not set to 1 in the environment.

Common situations: A Dockerfile uses `RUN --mount=type=secret` for tokens or `--mount=type=ssh` for private git clones; the user's skaffold.yaml predates BuildKit defaults or explicitly sets useBuildkit: false; CI environments lack DOCKER_BUILDKIT=1 while a newly added Dockerfile requires BuildKit mounts.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/d46cc265bf5fd4e7. Report an issue: GitHub.