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
- Verify the -f path exists and is a readable file: 'test -f <path> && head <path>'.
- Move the Dockerfile into the build context to avoid the outside-context code path entirely.
- Fix file ownership/permissions: 'chmod u+r <path>'.
- 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
- Keep the Dockerfile inside the build context to avoid the outside-context code path.
- Verify 'test -f <dockerfile>' before building with -f.
- Remember -f is relative to cwd, not to the context path.
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
- unable to prepare context
- error while getting existing contexts
- removing image ID file
- unable to prepare context from STDIN
- unable to prepare context: path
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)