basecamp/kamal · error · Kamal::Commands::Builder::BuilderError

Missing #{dockerfile}

Error message

Missing #{dockerfile}

What it means

When building images, Kamal::Commands::Builder::Base#build_dockerfile resolves the configured dockerfile path (from the builder's dockerfile option, default 'Dockerfile') relative to the current directory via File.expand_path, and adds `--file <dockerfile>` to the docker build command only if Pathname#exist? is true. If the file is not there, Kamal raises Kamal::Commands::Builder::BuilderError ('Missing <path>') before docker is invoked.

Source

Thrown at lib/kamal/commands/builder/base.rb:106

    end

    def build_labels
      argumentize "--label", { service: config.service }
    end

    def build_args
      argumentize "--build-arg", args, sensitive: true
    end

    def build_secrets
      argumentize "--secret", secrets.keys.collect { |secret| [ "id", secret ] }
    end

    def build_dockerfile
      if Pathname.new(File.expand_path(dockerfile)).exist?
        argumentize "--file", dockerfile
      else
        raise BuilderError, "Missing #{dockerfile}"
      end
    end

    def build_target
      argumentize "--target", target if target.present?
    end

    def build_ssh
      argumentize "--ssh", ssh if ssh.present?
    end

    def builder_provenance
      argumentize "--provenance", provenance unless provenance.nil?
    end

    def builder_sbom
      argumentize "--sbom", sbom unless sbom.nil?
    end

View on GitHub (pinned to eee0083b38)

Solutions

  1. Verify the file exists at the path kamal resolves: run `ls <path>` from the directory where you invoke kamal (paths are expanded against the current working directory).
  2. Fix the builder config to point at the real file (config/deploy.yml): builder: dockerfile: Dockerfile or a correct relative path from your kamal invocation directory.
  3. In CI, ensure the checkout includes the Dockerfile and the job's working directory matches where the config expects it.
  4. For monorepos, either cd into the app dir before running kamal or set the accurate relative dockerfile path.

Example fix

# before (config/deploy.yml, run from repo root, app in ./app)
builder:
  dockerfile: Dockerfile   # repo-root Dockerfile missing -> BuilderError
# after
builder:
  dockerfile: app/Dockerfile
# or invoke kamal from the app directory containing the Dockerfile
Defensive patterns

Strategy: validation

Validate before calling

require "pathname"
dockerfile = "Dockerfile" # or read from config builder section
File.exist?(File.expand_path(dockerfile)) || abort("#{dockerfile} not found from #{Dir.pwd}; fix builder.dockerfile or cwd")
system("kamal build")

Type guard

def dockerfile_resolves?(path)
  Pathname.new(File.expand_path(path)).exist?
end

Try / catch

begin
  Kamal::CLI::Build.new.invoke(:deliver)
rescue Kamal::Commands::Builder::BuilderError => e
  raise unless e.message.start_with?("Missing")
  abort "#{e.message} — run kamal from the directory containing the Dockerfile or fix builder.dockerfile"
end

Prevention

When it happens

Trigger: `kamal build` (or any deploy that builds) when the builder config's dockerfile: points to a missing file (e.g. dockerfiles/app.dockerfile not committed), or when kamal is run from a directory other than the app root so the default Dockerfile isn't found (File.expand_path uses Dir.pwd, not the config dir).

Common situations: Monorepos where the Dockerfile lives in a subdirectory but kamal runs from the repo root (or vice versa); custom dockerfile: path with a typo or uncommitted file; CI checking out a sparse/partial tree that excludes the Dockerfile; running kamal from a gem directory or via a script that changed cwd.

Related errors


AI-assisted analysis of basecamp/kamal@eee0083b38 (2026-08-21). Data as JSON: /api/errors/6e20b226ef96caff. Report an issue: GitHub.