🤖

コンテナ上でgo buildをすると error obtaining VCS status: exit status 128 が出る問題

2024/07/24に公開
2

概要

Dockerコンテナ上でgo buildをおこなったところ、以下のようなエラーが出た。

error obtaining VCS status: exit status 128
	Use -buildvcs=false to disable VCS stamping.
failed to build, error: exit status 128

このエラーを解消する方法を探す。

原因究明

そもそもVCSとは

VCSはVersion Control Systemの略で、バージョン管理システムのことを指す。最も有名なVCSにGitがある。

Goではバグの原因を特定しやすくするためなどの目的で、ビルド時にVCSからコミットIDやコミット時刻などの情報を取得してバイナリに埋め込むという機能があるらしい。この機能のことをVCSスタンピングと呼ぶ。詳しくは以下。
https://tip.golang.org/doc/go1.18

以上のことを踏まえてエラー文を再読すると、Goがビルド時にVCSスタンピングをしようとしたが、VCS情報を取得することができず、エラーが発生したと考えられる。

git statusを実行してみる

本当にVCS情報を取得できていないのかどうかを確かめるために、ためしにDockerコンテナ内でgit statusを実行してみた。すると以下のようなエラーが出た。

fatal: detected dubious ownership in repository at '/app'
To add an exception for this directory, call:

	git config --global --add safe.directory /app

dubious ownership とは

リポジトリの所有者がGitコマンドを実行しているユーザーと異なる場合に出るエラーらしい。
詳しくは以下。
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24765

正直あまり深く理解できていないが、ざっくり言えば、Gitに存在する脆弱性を防ぐために所有者のチェックを厳しくしたということらしい。
実際にコンテナ内でwhoamiコマンドを実行するとrootだったが、ls -lを実行すると、

-rw-rw-r-- 1 1001 1001  140 Jul 23 20:12 Dockerfile
drwxrwxr-x 4 1001 1001 4096 Jul 23 20:12 cmd
-rw-rw-r-- 1 1001 1001  402 Jul 23 20:12 docker-compose.yml
-rw-rw-r-- 1 1001 1001  645 Jul 23 20:12 go.mod
-rw-rw-r-- 1 1001 1001 3135 Jul 23 20:12 go.sum
drwxrwxr-x 2 1001 1001 4096 Jul 23 20:12 handler
-rw-rw-r-- 1 1001 1001  469 Jul 23 20:12 main.go
drwxr-xr-x 2 root root 4096 Jul 23 20:12 tmp

と返ってきた。コンテナ内で自動作成された/tmp以外は所有者がコンテナ側のユーザーであるrootではなく、ホスト側のユーザーのuidを指す1001になっていることが分かる。

ちなみに、ボリュームのマウント時にマウントされたファイルの所有者がホスト側のユーザーになるこの現象は、Docker for Macでは起こらないようだ。自分はMacユーザーなので開発中はタイトルの問題には遭遇せず、Linuxサーバーにデプロイして初めてこの問題に気付いた。

念の為、MacのDockerコンテナ上でwhoamiをおこなうとrootが返り、ls -lを実行すると以下のようになることを確認した。

-rw-r--r-- 1 root root  140 Jul 23 18:06 Dockerfile
drwxr-xr-x 5 root root  160 Jul 23 18:06 cmd
-rw-r--r-- 1 root root  402 Jul 23 18:06 docker-compose.yml
-rw-r--r-- 1 root root  645 Jul 23 18:06 go.mod
-rw-r--r-- 1 root root 3135 Jul 23 18:06 go.sum
drwxr-xr-x 5 root root  160 Jul 23 18:06 handler
-rw-r--r-- 1 root root  469 Jul 23 18:06 main.go
drwxr-xr-x 3 root root   96 Jul 23 18:07 tmp

Docker for Mac上ではボリュームのマウントをおこなっても、所有者をコンテナ側のユーザーに良い感じに書き換えてくれるようだ。

解決方法

やや複雑だったがまとめるとエラーの流れは以下のようになる。

  1. Dockerのボリュームをマウントするとコンテナ内のファイルの所有者がホスト側のユーザーになる
  2. Goのビルド時にGitの情報を取得しようとする
  3. Gitコマンドの実行者はコンテナ側のユーザーなのにファイルの所有者はホスト側のユーザーなので、脆弱性対策のためにGitがエラーを発生させる
  4. Gitがエラーを返すのでGoのビルドも失敗する

つまり根本的な原因はボリュームマウント時の所有者の問題にあるので、そこを解決してやれば良い。具体的な方法については以下の記事に託す。
https://qiita.com/yohm/items/047b2e68d008ebb0f001

余談だが、この記事を書いている途中で「そもそも本番環境でボリュームのマウントをする必要はないのでは?」と思い、本番環境でのボリュームのマウント自体をやめた。ボリュームのマウントはホスト側での変更をコンテナ側に即反映させるための機能のはずなので、変更を即反映させる必要性の薄い本番環境では不必要な場面が多いだろう。

怪我の功名ではあるが、自分が今まで思考停止で適当にマウントの機能を使ってきたということを思い知ることができてよかった。

今回の自分のように、開発環境はMacで本番環境はLinuxの人は、上記のQiitaの記事の内容を実行せずとも、本番でのボリュームのマウントを止めるだけでエラーは発生しなくなるだろう。根本的な解決にはなっていないが…。

参考

https://tech.mfkessai.co.jp/2023/07/vcs-stamping-error/
https://qiita.com/yohm/items/047b2e68d008ebb0f001

追記(2024-11-19)

Dockerのuserns-remapという機能を使えば、ホストとコンテナ間でユーザーをマッピングすることができるというコメントを頂いた。詳しくは以下の記事を参照。
https://makiuchi-d.github.io/2024/06/08/klabtechbook11-docker-userns-remap.ja.html

GitHubで編集を提案

Discussion

つるくもつるくも

なるほど、存じ上げませんでした。追記しておきます。
情報ありがとうございます!