docker/cli · error

unable to open Dockerfile

Error message

unable to open Dockerfile: %w

What it means

Returned by runBuild (build.go:244) when os.Open(options.dockerfileName) fails after detecting that the resolved Dockerfile lives outside the build context (relDockerfile starts with '../'). In that case the CLI must open the Dockerfile separately to inject it into the context archive. Failure means the -f path cannot be opened for reading.

Solutions

  1. Verify the -f path exists and is a readable file: 'test -f <path> && head <path>'.
  2. Move the Dockerfile into the build context to avoid the outside-context code path entirely.
  3. Fix file ownership/permissions: 'chmod u+r <path>'.
  4. Check for typos and relative-path confusion (path is relative to cwd, not the context).

Example fix

# before (Dockerfile outside context, unreadable)
docker build -f ../secrets/Dockerfile .
# after (Dockerfile inside context)
cp ../secrets/Dockerfile ./Dockerfile && docker build .
Defensive patterns

Strategy: validation

Validate before calling

// Verify a Dockerfile specified with -f is readable, especially when outside the context.
func validateDockerfileFlag(f string) error {
	info, err := os.Stat(f)
	if err != nil { return err }
	if info.IsDir() { return fmt.Errorf("%s is a directory", f) }
	return nil
}

Try / catch

if err := buildCmd.Execute(); err != nil {
	if strings.Contains(err.Error(), "unable to open Dockerfile") {
		// the -f path is missing or unreadable; correct it
	}
}

Prevention

When it happens

Trigger: Running 'docker build -f <outside-path> <context>' where <outside-path> does not exist, is not readable, is a directory, or is blocked by permissions. The detection that triggers this code path is specifically that the Dockerfile resolved to a location above the build context directory.

Common situations: Pointing -f at a Dockerfile in a parent directory that has since been moved/deleted; a Dockerfile path with a typo; the Dockerfile exists but is owned by another user with no read permission; the path resolves to a directory rather than a file.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/fc86b34b42f3aa05. Report an issue: GitHub.

Appendix: source

Thrown at cli/command/image/build.go:244

	}

	switch contextType {
	case build.ContextTypeStdin:
		// buildCtx is tar archive. if stdin was dockerfile then it is wrapped
		buildCtx, relDockerfile, err = build.GetContextFromReader(dockerCli.In(), options.dockerfileName)
		if err != nil {
			return fmt.Errorf("unable to prepare context from STDIN: %w", err)
		}
	case build.ContextTypeLocal:
		contextDir, relDockerfile, err = build.GetContextFromLocalDir(options.context, options.dockerfileName)
		if err != nil {
			return fmt.Errorf("unable to prepare context: %s", err)
		}
		if strings.HasPrefix(relDockerfile, ".."+string(filepath.Separator)) {
			// Dockerfile is outside build-context; read the Dockerfile and pass it as dockerfileCtx
			dockerfileCtx, err = os.Open(options.dockerfileName)
			if err != nil {
				return fmt.Errorf("unable to open Dockerfile: %w", err)
			}
			defer dockerfileCtx.Close()
		}
	case build.ContextTypeGit:
		var tempDir string
		tempDir, relDockerfile, err = build.GetContextFromGitURL(options.context, options.dockerfileName)
		if err != nil {
			return fmt.Errorf("unable to prepare context: %w", err)
		}
		defer func() {
			_ = os.RemoveAll(tempDir)
		}()
		contextDir = tempDir
	case build.ContextTypeRemote:
		buildCtx, relDockerfile, err = build.GetContextFromURL(progBuff, options.context, options.dockerfileName)
		if err != nil && options.quiet {
			_, _ = fmt.Fprintln(dockerCli.Err(), progBuff)
		}

View on GitHub (pinned to 4f84911bfe)