# ko build: Build Go Images Without a Dockerfile

> ko build compiles a Go binary and packages it into a minimal container image, no Dockerfile or daemon. Reference for KO_DOCKER_REPO, --platform, --bare, and CI errors.

Source: https://latchkey.dev/learn/command-reference/ko-build-go  
Updated: 2026-06-30

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

```Terminal
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/server
```

## Options

| 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.

## FAQ

### ko build: Build Go Images Without a Dockerfile?

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.

### 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.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
