ko beta
ko enables fast, standardized, reproducible,
configuration-less, Docker-less, and multi-platform container image builds for
Go apps.
Skaffold embeds ko as a library, so you do not need to download ko
to use the ko builder.
Benefits of the ko builder
Compared to …
-
the Cloud Native buildpacks builder, the ko builder is fast, doesn’t require Docker, and uses a default base image that has a small attack surface.
-
the Docker builder, the ko builder standardizes builds, avoiding artisanal snowflake
Dockerfiles. It also doesn’t require the Docker daemon, so builds can run in environments where Docker isn’t available for security reasons. -
the Kaniko builder, the ko builder doesn’t need a Kubernetes cluster, and it avoids the previously-mentioned artisanal
Dockerfiles. -
the Bazel builder, the ko builder doesn’t require users to adopt Bazel. However, we recommend the Bazel builder for users who already use Bazel for their Go apps.
-
the custom builder, the ko builder standardizes builds, as it doesn’t require running
kousing custom shell scripts.
Configuring the ko builder
The ko builder default configuration is sufficient for many Go apps. To use
the ko builder with its default configuration, provide an empty map in the
ko field, e.g.:
build:
artifacts:
- image: my-simple-go-app
ko: {}
Base image
ko uses the
cgr.dev/chainguard/static
image as the default base image. This is a small image that provides a
minimal environment for Go binaries.
The default base image does not provide a shell, and it does not include
glibc.
You can specify a different base image using the ko builder fromImage config
field. For instance, if you want to use a base image that contains glibc,
you can use this configuration:
ko:
fromImage: cgr.dev/chainguard/glibc-dynamic
If you run Skaffold in a Google Cloud VPC network with limited or no internet access, you can use a distroless base image from Google Container Registry, accessible via Private Google Access:
ko:
fromImage: gcr.io/distroless/static-debian11:nonroot
Multi-platform images
The ko builder supports building multi-platform images. The default platform
is linux/amd64, but you can configure a list of platforms using the
artifact’s platforms configuration field, e.g.:
build:
platforms: ["linux/amd64", "linux/arm64"]
artifacts:
- image: foo
ko: {}
You can also supply ["all"] as the value of platforms. all means that the
ko builder builds images for all platforms supported by the base image.
Image labels
Use the labels configuration field to add
image labels
(a.k.a. Dockerfile LABELs),
For example, you can add labels based on the pre-defined annotations keys from the Open Container Initiative (OCI) Image Format Specification:
ko:
labels:
org.opencontainers.image.licenses: Apache-2.0
org.opencontainers.image.source: https://github.com/GoogleContainerTools/skaffold
The labels section supports templating of values based on environment
variables, e.g.:
ko:
labels:
org.opencontainers.image.revision: "{{.GITHUB_SHA}}"
org.opencontainers.image.source: "{{.GITHUB_SERVER_URL}}/{{.GITHUB_REPOSITORY}}"
Build time environment variables
Use the env configuration field to specify build-time environment variables.
Example:
ko:
env:
- GOCACHE=/workspace/.gocache
- GOPRIVATE=git.internal.example.com,source.developers.google.com
The env field supports templating of values using environment variables, for
example:
ko:
env:
- GOPROXY={{.GOPROXY}}
Dependencies
The dependencies section configures what files Skaffold should watch for
changes when in dev mode.
paths and ignore are arrays that list file patterns to include and ignore.
Any patterns in ignore will be ignored by the Skaffold file watcher, even if
they are also specified in paths. ignore is only used when paths is not
empty.
Example:
ko:
dependencies:
paths:
- cmd
- go.mod
- pkg
ignore:
- vendor
If no dependencies are specified, the default values are as follows:
ko:
dependencies:
paths: ["**/*.go"]
ignore: []
Build flags
Use the flags configuration field to provide flag arguments to go build,
e.g.:
ko:
flags:
- -mod=vendor
- -v
Use the ldflags configuration field to provide linker flag arguments, e.g.:
ko:
ldflags:
- -s
- -w
The flags and ldflags fields support templating using environment
variables,
e.g.:
ko:
ldflags:
- -X main.version={{.VERSION}}
These templates are evaluated by Skaffold. Note that the syntax is slightly
different to
ko’s template expansion,
specifically, there’s no .Env prefix.
Source file locations
If your Go source files and go.mod are not in the context directory,
use the dir configuration field to specify the path, relative to the
context directory, e.g.:
ko:
dir: ./compat-go114
If your package main is not in the context directory (or in dir if
specified), use the main configuration field to specify the path or target,
e.g.:
ko:
main: ./cmd/foo
If your context directory only contains one package main directory, you
can use the ... wildcard in the main field value, e.g., ./....
Both dir and main default to ..
Existing ko users
Useful tips for existing ko users:
-
Specify your destination image registry using Skaffold’s
default-repofunctionality. The ko builder does not read theKO_DOCKER_REPOenvironment variable. -
Image naming follows the Skaffold image naming strategy. Skaffold removes the
ko://prefix, if present, before determining the image name. -
If your image references use the
ko://prefix and you are pushing the images to a registry, you must set the default repo. -
The ko builder supports reading base image configuration from the
.ko.yamlfile. If you already configure your base images using this file, you do not need to specify thefromImagefield for the artifact inskaffold.yaml. -
The ko builder supports reading build configs from the
.ko.yamlfile ifskaffold.yamldoes not specify any of the build config fields (dir,main,env,flags, andldflags). If you already specify these fields in.ko.yaml, you do not need to repeat them inskaffold.yaml. -
You can generate
skaffold.yamlfiles by examining an existing code base, using the commandskaffold init --XXenableKoInit=true. Select the Ko builder for your images when prompted.
ko commands and workflows in Skaffold
Here are some examples of Skaffold equivalents of ko commands and worflows.
Using vendored dependencies
If vendor your dependencies and your go.mod specifies a Go version < 1.14,
you can pass -mod=vendor to ko using the GOFLAGS environment variable:
GOFLAGS="-mod=vendor" ko publish .
To achieve the same using Skaffold’s ko builder, use the flags field in
skaffold.yaml:
ko:
flags:
- -mod=vendor
skaffold build
Capturing image name from stdout
If you want Skaffold to print out the full image name and digest (and nothing
else) to stdout, similar to what ko build does, use the
--quiet and --output flags.
These flags enable you to capture the full image references in an environment
variable or redirect to a file, e.g.:
skaffold build --quiet --output='{{range .Builds}}{{.Tag}}{{end}}' > out.txt
Note that Skaffold produces a JSON file with the image names if you run
skaffold build with the --file-output flag. You can then use this flag as
input to skaffold render to render Kubernetes manifests. For details on how
to do this, see the next section.
Rendering Kubernetes manifests
When you use the Skaffold ko builder, Skaffold takes care of replacing the image placeholder name in your Kubernetes manifest files using its render functionality.
The ko builder supports image name placeholders that consist of the ko://
prefix, followed by the Go import path to the main package. This means that
Skaffold works with existing Kubernetes manifest files that use this image name
placeholder format. Note that Skaffold only replaces image references in fields
that have the name image.
If you previously built images and rendered Kubernetes manifests using ko,
e.g.:
ko resolve --filename k8s/*.yaml > out.yaml
You can instead use Skaffold’s
render subcommand
with the --digest-source local flag to build and render manifests:
skaffold render --digest-source local --offline --output out.yaml
Or you can perform the action as two steps: first build the images, then
render the manifests using the output file from the build step:
skaffold build --file-output artifacts.json --push
skaffold render --build-artifacts artifacts.json --digest-source none --offline --output out.yaml
Specify the location of your Kubernetes manifests in skaffold.yaml:
manifests:
rawYaml:
- k8s/*.yaml
To build images in parallel, consider setting the SKAFFOLD_BUILD_CONCURRENCY
environment variable value to 0:
SKAFFOLD_BUILD_CONCURRENCY=0 skaffold [...]
You can also set the concurrency value in your skaffold.yaml:
build:
local:
concurrency: 0
Advanced usage
Debugging
Cloud Code and
skaffold debug
can debug images built using ko.
Images built using ko are automatically identified as Go apps by the presence
of the
KO_DATA_PATH environment variable.
Skaffold configures ko to build with compiler optimizations and inlining
disabled (-gcflags='all=-N -l') when you run skaffold debug or use
Cloud Code to
debug a Kubernetes application.
If you debug using VS Code and need to configure a “remote path” or “path on
remote container”, then this value should match your local path, typically
${workspaceFolder}. The reason is that “remote path” in this case means the
path to your Go source code where it was compiled. The ko builder currently
only supports local builds, so the remote path will be same as the local path.
To learn more about how Skaffold debugs Go applications, read the Go section in the Debugging guide.
File sync
The ko builder can
sync files to a running container
when you run skaffold dev.
The sync feature for the ko builder only works for
static assets bundled with the container image.
Use infer mode to specify patterns for the files you want to sync. The
infer patterns are relative to the context directory.
For instance, if your main package is in the context directory, you can use
this configuration to sync all the static files bundled with the container
image:
sync:
infer:
- kodata/**/*
Note that the file sync feature requires the tar command to be available in
the container. The default ko builder base image does not include the tar
command. Use the fromImage field in the ko builder configuration in your
skaffold.yaml file to specify a base image that contains the tar command,
such as gcr.io/distroless/base-debian11:debug.
You can use profiles with
activation by command to override the fromImage value only when running
skaffold dev, such as in this example:
profiles:
- name: sync
activation:
- command: dev
patches:
- op: add
path: /build/artifacts/0/ko/fromImage
value: gcr.io/distroless/base-debian11:debug
Remote builds
The ko builder supports remote builds on Google Cloud Build. See the
example.
Using the custom builder
If the ko builder doesn’t support your use of ko, you can instead use the
custom builder.
See the custom builder
example.
build:
artifacts:
- image: ko://github.com/googlecontainertools/skaffold/examples/custom
custom:
buildCommand: ./build.sh
dependencies:
paths:
- "**/*.go"
- go.*
- .ko.yaml
If you need to use ko via the custom builder rather than the ko builder,
please consider filing an
issue
that describes your use case.
Collecting coverage profiles from integration tests
Go 1.20 introduced support for collecting coverage profile data from running Go
application when running integration or end-to-end tests. To see how you can
use the ko builder to configure this, see the tutorial
Go integration test coverage profiles.
SBOM synthesis and upload
The ko CLI by default generates a software bill of materials (SBOM) and
uploads it to the image registry. The Skaffold ko builder does not generate
or upload SBOMs. If you need this feature, please
raise an issue.