Introduction
ko is a lightweight container image builder designed specifically for Go applications. It compiles your Go binary, layers it onto a minimal base image (distroless by default), and pushes the result to a container registry — all without a Dockerfile or Docker daemon. ko also integrates with Kubernetes manifests, replacing image references on the fly so you can build and deploy in a single step.
What ko Does
- Compiles Go applications and packages them into minimal OCI container images
- Pushes images directly to any container registry without requiring a local Docker daemon
- Resolves ko:// image references in Kubernetes YAML and replaces them with built image digests
- Uses distroless base images by default for minimal size and attack surface
- Supports multi-platform builds for linux/amd64, linux/arm64, and more
Architecture Overview
ko works by invoking the Go compiler to produce a static binary for the target platform. It then constructs an OCI image by layering that binary onto a configurable base image (defaulting to gcr.io/distroless/static). The image layers are pushed directly to the registry via the OCI distribution API, bypassing Docker entirely. For Kubernetes workflows, ko parses YAML manifests, finds image fields matching ko:// prefixes, builds those images, and rewrites the references with fully qualified digests.
Self-Hosting & Configuration
- Install via go install or download a pre-built binary from the GitHub releases page
- Set KO_DOCKER_REPO to your target registry (e.g., ghcr.io/myorg or gcr.io/myproject)
- Create a .ko.yaml config file to customize base images, build flags, or platform targets
- Use ko build ./cmd/app to build a single service or ko build ./... for all commands
- Integrate with kubectl by piping: ko resolve -f deploy/ | kubectl apply -f -
Key Features
- Zero-Docker workflow: no Dockerfile, no docker build, no daemon process required
- Blazing fast builds that leverage Go's compilation speed and registry-direct pushing
- Automatic SBOM generation for supply chain security and vulnerability scanning
- Multi-platform support for building images targeting amd64, arm64, s390x simultaneously
- Kubernetes-native integration that resolves and applies manifests in one step
Comparison with Similar Tools
- Dockerfile + docker build — requires writing and maintaining Dockerfiles plus a running daemon
- Jib — same daemonless philosophy but designed for Java/Maven/Gradle, not Go
- Kaniko — builds Dockerfiles in containers for CI but still needs a Dockerfile and is slower
- GoReleaser — excellent for releasing Go binaries and archives but container support is secondary
- Buildpacks (Paketo) — auto-detect and build but slower, larger images, and less Go-specific optimization
FAQ
Q: Does ko work with CGO-enabled applications? A: By default ko builds with CGO_ENABLED=0 for static binaries. If your app needs CGO, you can set build flags in .ko.yaml and use a base image with glibc.
Q: Can I use a custom base image instead of distroless? A: Yes. Set defaultBaseImage in .ko.yaml or use the --base-image flag to specify any OCI image as the base.
Q: How does ko handle private registries? A: ko uses the standard Docker credential helpers and config.json for authentication. It works with GCR, ECR, ACR, GHCR, and any registry supporting token-based auth.
Q: Is ko suitable for production deployments? A: Yes. ko is used in production by the Knative project, Tekton, and many other Kubernetes-native Go projects. Image digests ensure immutable deployments.