Cloud Build で Chainguard の ko イメージを使う
はじめに
Go アプリケーションのコンテナイメージをビルドする際、ko は非常に便利なツールです。
Google Cloud Build で ko を使う場合、Chainguard の ko イメージ を使うと、セキュリティに優れ、ビルドも高速です。
しかし、実際に使ってみると、いくつかの落とし穴がありました。
結論
Chainguard の ko イメージを Cloud Build で使うには、以下の環境変数が必要です。
steps:
- name: 'cgr.dev/chainguard/ko'
env:
- GOCACHE=/tmp/go-cache
- GOMODCACHE=/tmp/go-mod
- GIT_CONFIG_COUNT=1
- GIT_CONFIG_KEY_0=safe.directory
- GIT_CONFIG_VALUE_0=/workspace
- KO_DOCKER_REPO=${_REGION}-docker.pkg.dev/$PROJECT_ID/${_REPO_NAME}/web
args:
- 'build'
- '.'
- '--bare'
- '-t'
- '$SHORT_SHA'
| 環境変数 | 目的 |
|---|---|
GOCACHE=/tmp/go-cache |
Go ビルドキャッシュの権限エラー回避 |
GOMODCACHE=/tmp/go-mod |
Go モジュールキャッシュの権限エラー回避 |
GIT_CONFIG_* |
Git safe.directory エラー回避 |
以下、各問題の詳細を説明します。
落とし穴 1: GOCACHE の権限エラー
エラー内容
failed to initialize build cache at /builder/home/.cache/go-build:
mkdir /builder/home/.cache: permission denied
原因
Chainguard の ko イメージは、セキュリティのため nonroot ユーザー (UID 65532) で実行されます。一方、Cloud Build は $HOME として /builder/home を使用しますが、このディレクトリは nonroot ユーザーには書き込みできません。
Go コンパイラはビルドキャッシュを $HOME/.cache/go-build に作成しようとしますが、権限がないため失敗します。
解決策
GOCACHE 環境変数で、書き込み可能な /tmp を指定します。
Cloud Build では各ビルドが新しいコンテナで実行され、ビルド間でキャッシュは共有されません。そのため、キャッシュの場所を /tmp に変更しても実質的なデメリットはありません。
落とし穴 2: GOMODCACHE の権限エラー
エラー内容
go: could not create module cache: mkdir /builder/home/go: permission denied
原因
Go はダウンロードしたモジュールを $HOME/go/pkg/mod に保存します。これも nonroot ユーザーでは書き込みできません。
なお、GOCACHE=off は Go 1.12 以降では使えません(ビルドキャッシュが必須になったため)。GOMODCACHE=off も同様に使えません。モジュールのソースコードは実際にファイルとして保存する必要があるためです。
解決策
GOMODCACHE 環境変数で、書き込み可能な /tmp を指定します。
落とし穴 3: Git の safe.directory エラー
エラー内容
error obtaining VCS status: exit status 128
Use -buildvcs=false to disable VCS stamping.
ログを見ると、以下のメッセージがありました。
current folder is not a git repository. Git info will not be available
原因
Go 1.18 から、ビルド時に VCS(バージョン管理システム)の情報をバイナリに埋め込む機能がデフォルトで有効になっています。この機能は Git リポジトリの情報を取得しようとします。
しかし、Git には CVE-2022-24765 への対策として、リポジトリの所有者とコマンド実行者が異なる場合にアクセスを拒否する セキュリティ機能があります。
Cloud Build では:
- ソースファイルは特定のユーザー(おそらく root)が所有
- Chainguard ko は nonroot (UID 65532) で実行
- Git が「安全でないリポジトリ」としてアクセスを拒否
解決策
Git の設定を環境変数で渡し、/workspace ディレクトリを信頼するよう指定します。
safe.directory=* で全ディレクトリを信頼することもできますが、セキュリティの観点から /workspace(Cloud Build のソースディレクトリ)のみを指定することをお勧めします。
Discussion