ko build: Build Go Images Without a Dockerfile
ko build compiles a Go main package and lays the static binary onto a minimal base image, then pushes it, with no Dockerfile and no Docker daemon.
For Go services, ko removes the Dockerfile entirely: it cross-compiles the binary and packages it on a distroless base, producing small, reproducible images fast in CI.
What it does
ko build (aliased ko publish) compiles the given Go import path, appends the resulting static binary onto a configurable base image, and pushes the image to the repository named by $KO_DOCKER_REPO, printing the pushed reference. No Dockerfile, no daemon, and multi-arch with one flag.
Common usage
export KO_DOCKER_REPO=ghcr.io/acme
# build, push, and print the image reference
ko build ./cmd/server
# multi-arch, clean image name (no md5 suffix)
ko build --bare --platform=linux/amd64,linux/arm64 ./cmd/server
# build to a local tarball / daemon instead of pushing
ko build --local ./cmd/serverOptions
| Flag | What it does |
|---|---|
| IMPORTPATH | Go main package(s) to build (positional) |
| --platform <list> | Target platform(s), e.g. linux/amd64,linux/arm64 or all |
| --bare | Use KO_DOCKER_REPO as the exact image name (no path suffix) |
| --tags <list> | Tags to apply to the pushed image |
| --local, -L | Load into the local daemon instead of pushing |
| --sbom spdx|none | SBOM format to attach (default spdx) |
In CI
Set KO_DOCKER_REPO to your registry and ko build ./cmd/... publishes a small multi-arch image with an SBOM, no Dockerfile to maintain. ko authenticates via the standard docker config, so a prior registry login is enough.
Common errors in CI
"KO_DOCKER_REPO environment variable is unset" means export it before building. "error: failed to publish: ... UNAUTHORIZED" means log in to the registry first. "no Go files in ..." or "import path does not contain package main" means you pointed ko at a library, not a main package. Cross-compile failures usually come from cgo; set CGO_ENABLED=0 for the static build ko expects.