ko

repository·main·Indexed 11 days ago

https://github.com/ko-build/ko

A specialized container image builder for Go applications that eliminates the need for a Docker daemon by leveraging local go build execution. Designed for speed and simplicity in CI/CD and Kubernetes environments, ko supports multi-platform builds, SBOM generation, and integration with Kustomize and AWS Lambda. It can be used as a CLI tool or as a Go library via the pkg/build and pkg/publish packages.

Tokens
26.7K
Snippets
90
Records
121
Agent score
90%

What's inside ko

  1. Overview of `ko` for Go container builds

    main

    ko is a simple and fast container image builder specifically designed for Go applications. It is ideal for building images containing a single Go application that has minimal or no dependencies on the OS base image (e.g., applications without cgo or OS package dependencies).

    Key features include:

    • No Docker required: ko builds images by executing go build on your local machine, making it suitable for lightweight CI/CD environments where a Docker daemon is unavailable.
    • Multi-platform builds: Simplifies the creation of images for different architectures.
    • SBOM support: Produces Software Bill of Materials (SBOMs) by default.
    • Kubernetes integration: Supports simple YAML templating to facilitate building for Kubernetes applications.
  2. What is ko and when should I use it?

    main

    ko is a container image builder designed specifically for Go applications. It simplifies the process of building images that are easy, fast, and secure by default.

    Key Characteristics

    • Go-Centric: It builds images by executing go build on your local machine.
    • No Docker Required: Because it uses your local Go toolchain, it does not require a Docker daemon to be installed, making it ideal for lightweight CI/CD environments.
    • Ideal Use Cases: It is best suited for images containing a single Go application with minimal OS dependencies (e.g., applications without cgo or complex OS package requirements).

    Core Features

    • Multi-platform builds: Easily target multiple architectures.
    • SBOMs by default: Automatically produces Software Bill of Materials.
    • Kubernetes Integration: Supports simple YAML templating to facilitate building images for Kubernetes applications.
  3. Use the ko CLI

    main

    The ko command is the primary entrypoint for building and managing Go containers. It allows you to rapidly iterate by containerizing Go packages and interacting with Kubernetes. The CLI follows a subcommand pattern (e.g., ko build, ko apply).

    ko [flags]
  4. Use `ko://` importpaths in Kubernetes YAML

    main

    Instead of hardcoding fully-qualified image references (e.g., registry.example.com/my-app:v1.2.3) in your Kubernetes manifests, you can use the ko:// prefix followed by the Go package importpath. This allows ko to automatically build, push, and resolve the correct image for your deployment.

        spec:
          containers:
          - name: my-app
            image: ko://github.com/my-user/my-repo/cmd/app
  5. Configure image naming and registry behavior with `ko apply`

    main

    When using ko apply, you can control how images are named in the registry and how they are published using the following flags:

    • --preserve-import-paths (-P): Preserves the full import path after the registry URL (e.g., ${KO_DOCKER_REPO}/<import path>). By default, ko uses <package name>-<hash of import path>.
    • --base-import-paths (-B): Uses the base path without the MD5 hash after the registry URL.
    • --bare: Uses only the KO_DOCKER_REPO without additional context.
    • --local (-L): Loads images into the local Docker daemon instead of pushing to a remote registry. When KO_DOCKER_REPO is set to ko.local, it behaves the same as using --local.
    • --push: Determines whether to push images to the registry. This is true by default.
    • --tags: Specifies custom tags for the produced images instead of the default [latest]. Note that using --tags may not work correctly with --base-import-paths or --bare.
    # Example: Preserving import paths in the registry
    ko apply --preserve-import-paths -f config/
    
    # Example: Loading images to local docker daemon
    ko apply --local -f config/
  6. Enable Last-Modified headers for static assets

    main

    Because ko does not embed timestamps by default, standard Go tools like http.FileServer cannot serve Last-Modified headers or validate If-Modified-Since requests.

    To fix this and enable timestamp support for your bundled assets, you must set the KO_DATA_DATE_EPOCH environment variable during the ko build process.

  7. Use templating in flags and ldflags

    main

    The flags and ldflags fields in the builds section support templating. The following parameters are available:

    Template paramDescription
    EnvMap of environment variables used for the build
    GoEnvMap of go env environment variables used for the build
    DateThe UTC build date in RFC 3339 format
    TimestampThe UTC build date as Unix epoc seconds
    Git.BranchThe current git branch
    Git.TagThe current git tag
    Git.ShortCommitThe git commit short hash
    Git.FullCommitThe git commit full hash
    Git.CommitDateThe UTC commit date in RFC 3339 format
    Git.CommitTimestampThe UTC commit date in Unix format
    Git.IsDirtyWhether or not current git state is dirty
    Git.IsCleanWhether or not current git state is clean
    Git.TreeStateEither clean or dirty
  8. Configure image naming strategies with `ko create`

    main

    When using ko create, you can control how images are named in your registry using the following strategies:

    1. Default Strategy: Images are published as ${KO_DOCKER_REPO}/<package name>-<hash of import path>.
    2. Preserve Import Paths: Use the --preserve-import-paths (or -P) flag to publish images using their full import path: ${KO_DOCKER_REPO}/<import path>.
    3. Local Development: Use the --local (or -L) flag to load images directly into your local Docker daemon as ko.local/<import path> instead of pushing to a remote registry.
    4. Base Import Paths: Use --base-import-paths (or -B) to use the base path without the MD5 hash after the registry URL (note: this may conflict with --tags).
    # Preserve full import paths in the registry
    ko create --preserve-import-paths -f config/
    
    # Load images to local docker daemon instead of pushing
    ko create --local -f config/
  9. Understand the requirements for using ko

    main

    To get the best results with ko, your Go application should ideally have no dependencies on the underlying container image.

    Key constraints and recommendations:

    • CGO: ko is optimized for applications that do not require cgo. By default, ko executes builds with CGO_ENABLED=0.
    • OS Packages: If your application requires specific OS-level packages, you must ensure they are included in your configured base image.
    • Language Support: ko is purpose-built for Go applications only.
  10. Bundle static assets using the kodata convention

    main

    To bundle static assets into your container image, place them in a directory named kodata/ located within your package's import path. ko will automatically include these files in the image.

    Inside the container, the location of these assets is provided via the KO_DATA_PATH environment variable. You should use this variable in your application code to locate the files rather than hardcoding a path.

    Key behaviors:

    • Symlinks: ko follows symlinks within the kodata directory and includes the target files in the image.
    • Timestamps: By default, ko does not embed timestamps, meaning http.FileServer will not serve Last-Modified headers. To enable timestamp support, set the KO_DATA_DATE_EPOCH environment variable during your build.
    // Example directory structure:
    // cmd/app/main.go
    // cmd/app/kodata/index.html
    
    func main() {
        // Use the KO_DATA_PATH environment variable to find bundled assets
        dataDir := os.Getenv("KO_DATA_PATH")
        http.Handle("/", http.FileServer(http.Dir(dataDir)))
        log.Fatal(http.ListenAndServe(":8080", nil))
    }
  11. Install root CA certificates using incert

    main

    You can use the incert tool to append CA certificates to an image after it has been built by ko. This involves building your image with ko build, then running incert to modify the image and push it to a destination registry.

    Workflow:

    1. Build and push your Go application image using ko build.
    2. Use incert to append the certificates to the built image and specify a destination registry.
    # 1. Build and push your Go application container image
    KO_DOCKER_REPO=mycompany/myimage:latest ko build .
    
    # 2. Append the built image with your custom CA certificate(s) using incert
    incert -image-url=mycompany/myimage:latest -ca-certs-file=/path/to/cacerts.pem -dest-image-url=myregistry/myimage:latest
  12. Debug Go containers with `ko apply`

    main

    If you need to interactively debug the containers created by ko, use these flags:

    • --debug: Includes a Delve debugger in the image and wraps the application. The debugger listens on port 40000.
    • --disable-optimizations: Disables optimizations during the Go build process, making the binary more suitable for interactive debugging.
    # Build a container optimized for debugging
    ko apply --disable-optimizations -f config/
    
    # Build a container with a Delve debugger included
    ko apply --debug -f config/