ko 是一个由 Google 开发的 Go 语言工具用于快速构建 Go 应用程序的容器镜像。ko 直接调用本地的 Go 编译器进行编译,然后将编译后的二进制文件打包成镜像层(Layer)追加到基础镜像中,最后修改镜像的入口点(Entrypoint)完成构建。整个过程不需要 Docker 的参与,也无需编写 Dockerfile 文件,因此可以很方便地集成在 CI/CD 环境中。
ko 安装简单,只需在 Release 页面下载对应平台的二进制文件即可,macOS 系统上可以使用 Homebrew 安装 ko:
1 | brew install ko |
安装完成后调用 ko login
命令登录镜像仓库:
如果使用
docker login
命令登录过可以忽略该步骤,ko 会自动使用 docker 的凭证。
1 | ko login ${REGISTRY} --username=${USERNAME} --password=${PASSWORD} |
使用命令构建
ko 提供了非常方便的命令行工具,使得我们可以像使用 go build
命令编译 Go 项目一样轻松完成镜像构建,下面来初始化一个简单的 Go 项目:
1 | mkdir hello-ko |
使用 ko 构建镜像并推送:
1 | export KO_DOCKER_REPO=docker.io/lin2ur |
ko build
的第一个参数用于指定 Go 项目的路径,-t
参数指定镜像的标签,--sbom=none
表示不生成软件构建材料清单(SBOM)。KO_DOCKER_REPO
环境变量用于指定镜像仓库,-B
参数表示使用 Go module 名称作为镜像名,在这个例子中是 hello-ko
,再结合 -t
参数指定的镜像标签,最终的镜像名为 docker.io/lin2ur/hello-ko:1.0.0
。如果不想使用 Go module 名称作为镜像名,可以将 -B
参数替换为 --bare
,此时镜像名为 KO_DOCKER_REPO
环境变量的值。
构建完毕后我们来运行一下:
1 | docker run --rm lin2ur/hello-ko:1.0.0 |
使用配置文件构建
命令行适用于单个目标的简单构建场景,如果需要定制化镜像,比如替换基础镜像、设置 go build
编译参数、构建多平台支持镜像等,需要使用 .ko.yaml 文件来配置构建过程,下面来看一个例子:
1 | defaultBaseImage: ubuntu # <- 指定基础镜像 |
在这份配置文件中指定基础镜像为 ubuntu
并配置了两个构建目标。dir
字段指定了目标的路径;env
字段指定了编译环境变量,注意这个环境变量只会被传递给 go build
命令,不会在镜像中生效;flags
字段指定了 go build
参数;ldflags
字段指定了链接器参数,其中{{ .Git.ShortCommit }}
和 {{ .Git.Branch }}
是 ko 提供的模板变量,用于获取 Git 仓库的提交 ID 和分支名称,更多可用的模板变量可以参考官方文档,以 server
构建目标的配置为例,等效于下面的编译命令:
1 | export GOPRIVATE=git.internal.example.com |
总结
大多数情况下 ko 都能很好地满足我们的需求,但是 ko 也有一些局限性,无法更多地定制化镜像,比如无法在镜像中预设环境变量,无法像 Docker 一样在构建过程中执行命令安装依赖等,不过我们在构建基础镜像的过程中完成这些操作。