Introduction
ko is a container image builder designed specifically for Go applications. Instead of writing a Dockerfile and running Docker build, you point ko at a Go import path and it compiles the binary, layers it onto a minimal distroless base image, and pushes the result to a registry. Created at Google for Knative development, ko makes Go container workflows dramatically simpler and faster.
What ko Does
- Builds Go binaries and packages them into OCI container images without Docker
- Pushes images directly to any OCI-compatible container registry
- Resolves image references in Kubernetes YAML and replaces them with built image digests
- Produces minimal distroless images with no shell, package manager, or OS utilities
- Supports multi-platform builds (amd64, arm64) with a single command
Architecture Overview
ko works entirely in user space without a Docker daemon. It invokes go build to compile the target binary for the specified platform, then constructs an OCI image by layering the binary onto a base image (default: cgr.dev/chainguard/static). The image layers are computed and pushed directly to the registry using the go-containerregistry library. For Kubernetes workflows, ko apply parses YAML files, detects ko:// image references, builds and pushes them, substitutes the digest, and pipes the result to kubectl apply.
Self-Hosting & Configuration
- Install with
go install github.com/ko-build/ko@latestor download a release binary - Set
KO_DOCKER_REPOto your target registry (e.g.,ghcr.io/myuser,gcr.io/myproject) - Configure
.ko.yamlto set default base image, build flags, and platform targets - Use
ko loginor Docker credential helpers for registry authentication - Integrate into CI with a single
ko buildstep; no Docker-in-Docker needed
Key Features
- No Dockerfile required: Go import path is the only input needed
- No Docker daemon: builds run entirely in user space with no root or socket access
- Distroless by default: minimal attack surface with no shell or unnecessary packages
- Multi-platform: build linux/amd64 and linux/arm64 images simultaneously
- Kubernetes integration:
ko applyreplaces image refs in YAML with built digests
Comparison with Similar Tools
- Docker Build — General-purpose but requires a Dockerfile and daemon; ko is Go-specific and daemonless
- Kaniko — Builds Dockerfiles without a daemon in K8s; ko skips the Dockerfile entirely for Go
- Buildpacks — Auto-detects language and builds images; ko is faster and more minimal for Go
- GoReleaser — Release automation with Docker support; ko is lighter for just building images
- Jib — Similar concept for Java (Maven/Gradle); ko is the Go equivalent
FAQ
Q: Does ko only work with Go? A: Yes. ko is purpose-built for Go applications. For other languages, consider Buildpacks, Jib (Java), or standard Dockerfiles.
Q: Can I customize the base image?
A: Yes. Set defaultBaseImage in .ko.yaml or use the --base-image flag to specify any OCI base image.
Q: How does ko handle Go build tags and ldflags?
A: Configure them in .ko.yaml under builds with flags, env, and ldflags fields, similar to GoReleaser.
Q: Is ko suitable for production use? A: Absolutely. ko is used in production by Knative, Tekton, Sigstore, and many CNCF projects. Its distroless images have a minimal CVE surface.