Build Go container image with `ko`
From the project home page, ko
makes building Go container images easy, fast, and secure by default.
lets start with simple Go http project using gin
.
$ mkdir simple
$ cd simple
$ go mod init saktidwicahyono.name/simple
go: creating new go.mod: module saktidwicahyono.name/simple
$ go get -u github.com/gin-gonic/gin
Now create simple main.go
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "ok"})
})
r.Run()
}
Installing ko
You can install using brew
$ brew install ko
Or using go
$ go install github.com/google/ko@latest
Building container image
To decide where the container image registry as the push target, ko
use env var KO_DOCKER_REPO
. For this example I use my docker hub handle saktidc
.
$ export KO_DOCKER_REPO=saktidc
and then to build
$ ko build
2023/06/01 11:12:08 Using base cgr.dev/chainguard/static:latest@sha256:ee47224a2afc674c1f1089b9dea97d5ee400cf2fff3797398778450a4cfb2a8d for saktidwicahyono.name/simple
2023/06/01 11:12:09 Building saktidwicahyono.name/simple for linux/amd64
2023/06/01 11:12:10 Publishing saktidc/simple-c16baa5c7902f141ca35ab0eba518e77:latest
2023/06/01 11:12:14 existing blob: sha256:365a9bc05fc55ad9a0b77656877aeef86439c94307d00385a1096eccb437d47b
2023/06/01 11:12:15 pushed blob: sha256:50e3901fbf4cb45efb05f06dab3002caa814e0d1febcd8a46b4db06b70152937
2023/06/01 11:12:16 index.docker.io/saktidc/simple-c16baa5c7902f141ca35ab0eba518e77:sha256-26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990.sbom: digest: sha256:3873c56fd9a7f0c629417d05dec2ced75bf459961915dc9f45a744695e2fc3a0 size: 374
2023/06/01 11:12:16 Published SBOM index.docker.io/saktidc/simple-c16baa5c7902f141ca35ab0eba518e77:sha256-26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990.sbom
2023/06/01 11:12:17 existing blob: sha256:9a94261fe7288ed0aa24077c7668fb25f929d3f51a955d17b44938cf06356736
2023/06/01 11:12:17 existing blob: sha256:7d2e0f7d141e2e962603f0cdd19542fa01b454a49f5fd5a966fa3c44f37eb0a1
2023/06/01 11:12:17 existing blob: sha256:250c06f7c38e52dc77e5c7586c3e40280dc7ff9bb9007c396e06d96736cf8542
2023/06/01 11:12:17 existing blob: sha256:9a7a7857408c2c77b99ae8c182e8420cb8729ff42a8adbdbea5d24a4da039899
2023/06/01 11:12:18 saktidc/simple-c16baa5c7902f141ca35ab0eba518e77:latest: digest: sha256:26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990 size: 1210
2023/06/01 11:12:18 Published saktidc/simple-c16baa5c7902f141ca35ab0eba518e77@sha256:26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990
saktidc/simple-c16baa5c7902f141ca35ab0eba518e77@sha256:26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990
Ensure you have auth setup to the registry of your choice. Check `ko login --help` if you does not have docker in your system.
The ko build
command build the Go binary, containerize it, and publish it. By default will use following format as destination
registry.example.com/repo/<app/cli>-<md5>
If you want to disable md5 suffix you can use option --base-import-paths / -B
, lets try it again:
$ ko build -B
2023/06/01 11:17:15 Using base cgr.dev/chainguard/static:latest@sha256:ee47224a2afc674c1f1089b9dea97d5ee400cf2fff3797398778450a4cfb2a8d for saktidwicahyono.name/simple
2023/06/01 11:17:16 Building saktidwicahyono.name/simple for linux/amd64
2023/06/01 11:17:17 Publishing saktidc/simple:latest
2023/06/01 11:17:20 pushed blob: sha256:b1d00a125b2e1d12e952a7173fed2990110229725b1c8a3db850804627fb1e84
2023/06/01 11:17:21 pushed blob: sha256:365a9bc05fc55ad9a0b77656877aeef86439c94307d00385a1096eccb437d47b
2023/06/01 11:17:21 index.docker.io/saktidc/simple:sha256-26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990.sbom: digest: sha256:5925704c870a9ec82ba350e3600dd0bfcc1263041aaeb5f5125b0ed512052125 size: 374
2023/06/01 11:17:21 Published SBOM index.docker.io/saktidc/simple:sha256-26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990.sbom
2023/06/01 11:17:24 pushed blob: sha256:7d2e0f7d141e2e962603f0cdd19542fa01b454a49f5fd5a966fa3c44f37eb0a1
2023/06/01 11:17:24 pushed blob: sha256:250c06f7c38e52dc77e5c7586c3e40280dc7ff9bb9007c396e06d96736cf8542
2023/06/01 11:17:27 pushed blob: sha256:9a7a7857408c2c77b99ae8c182e8420cb8729ff42a8adbdbea5d24a4da039899
2023/06/01 11:17:27 pushed blob: sha256:9a94261fe7288ed0aa24077c7668fb25f929d3f51a955d17b44938cf06356736
2023/06/01 11:17:27 saktidc/simple:latest: digest: sha256:26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990 size: 1210
2023/06/01 11:17:27 Published saktidc/simple@sha256:26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990
saktidc/simple@sha256:26f86626dd1fdc39fce9b0b5b00636ec8d4ec4658dfd759aeaa99e5157600990
Will push the image to https://hub.docker.com/r/saktidc/simple then test it using
$ docker run --rm -it -p 8080:8080 saktidc/simple
# in other terminal
$ curl localhost:8080
{"message":"ok"}%
# succeed
The options
You can create .ko.yaml
file config, to customize the ko behaviour. For example to have both arm64 and amd64 build:
# .ko.yaml
defaultPlatforms:
- linux/arm64
- linux/amd64
Or you can override it using env var KO_DEFAULTPLATFORMS=linux/arm64,linux/amd64
. For complete option check official documentation https://ko.build/configuration/.
Also if your app have multiple cmd or you want to specify explicitly, put it as ko build
argument.
$ ko build ./cmd/app1
$ ko build ./cmd/app2
Limitation
Currently only work with static compile, work best without dependency to underlying image, the build executed using CGO_ENABLED=0
by default.
To install OS dependency you should configure the base image https://ko.build/configuration/#overriding-base-images.