GitLabでDockerイメージをビルドする際の基本的な設定を考えることにする。なお、今回、RunnerはDocker Runnerで作成しているものとする。
簡単に書くと
- dindでは特権モードを使うように設定、doodではdocker.sockをマウントするように設定
- dindとdoodでは使用するコンテナイメージが違う
- コンテナレジストリへのログインにはそのための環境変数を使う
Docker in DockerかDocker outside of Dockerか
Docker in Dockerは、Dockerコンテナ内にDockerコンテナを立てるやり方、Docker outside of Dockerは、Dockerコンテナからホスト側のDockerを呼び出し、ホスト側にDockerコンテナを立てるやり方である。Docker in Dockerはdind、Docker outside of Dockerはdoodと略すのが通例である。
dindはあたかも普通の仮想マシンのようにDockerを扱うことができるというのが大きい。一方、dindは特権モードで動かす必要があることから、ひとたびトラブルが起きたら、ホストごと巻き込んでトラブルが起きる。
一方、doodは特権モードである必要はないため、影響があるのはホストとのマウントの範囲に限られる。一方、取り扱いには少し面倒な作業が必要になること、dood固有のトラブルが起きやすいことなどの問題がある。
今回は双方の取り扱いを書くことにするが、基本はdoodを推奨する。
また、事前にDockerベースのRunner設定が完了しているものとする。
設定作業
GitLab Runnerの設定は、config.tomlファイルを用いる。dindとdoodで設定箇所が異なる。
dindでのconfig.tomlの修正箇所
runners.dockerセクションにprivilegedという項目がある。ここがデフォルトではfalseになっているが、ここをtrueに変更し、特権モードを有効にしたうえでGitLab Runnerを再起動する
doodでのconfig.tomlの修正箇所
runners.dockerセクションにvolumesという項目がある。この配列に"/var/run/docker.sock:/var/run/docker.sock"
という項目を追加する。これによりホストのDockerのUNIXソケットをコンテナ側にマウントする。設定ファイル変更後はGitLab Runnerを再起動する
使用するイメージ
使用するイメージは、dindとdoodで異なる。どちらもdockerというイメージを用いるが、dindではdindとついたタグのイメージを使う。例えばdocker:dindといったようなイメージを指定する。一方doodでは普通のタグを使う(例えばdocker:stableなど)。
コンテナレジストリへのログイン
コンテナレジストリへログインするには、docker login
コマンドを使う。外部のDockerレポジトリを使う場合はそのクレデンシャルを使えばよいが、GitLabに付属したコンテナレジストリを使う場合、そのログインはecho "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY --username $CI_REGISTRY_USER --password-stdin
というものになる。簡単に言えば、標準出力にパスワードを出力し、それをパイプでログインコマンドの標準入力に渡す形でログインする、ということである。
buildxを使いたい
buildxを使うには、イメージを作るのが手っ取り早いが、簡易にやると、以下のようなコードになる。
mkdir -p /usr/local/libexec/docker/cli-plugins
apk add git
apk add curl
export DL_ARCH_SUFFIX=${CI_RUNNER_EXECUTABLE_ARCH//\//-}
export BUILDX_URL="https://github.com/docker/buildx/releases/download/v0.10.0/buildx-v0.10.0.$DL_ARCH_SUFFIX"
curl -Lo /usr/local/libexec/docker/cli-plugins/docker-buildx $BUILDX_URL
chmod a+x /usr/local/libexec/docker/cli-plugins/docker-buildx
docker buildx install
docker buildx create --use --name multiarch --platform linux/amd64,linux/arm64
ここでバージョンは0.10.0と指定しているが、これは当然値が変わることがある。また、multiarchと指定しているが、ここの名前は自分で決めて構わない。ただし、この名前は後で使うので注意。
イメージのビルドは、例えばdocker buildx build --pull --platform linux/amd64,linux/arm64 -t $CI_REGISTRY_IMAGE:latest --push .
のようなコマンドになる。
最後の後始末は、このコマンドのあとに入れるわけだが、docker buildx rm multiarch
と、ここで先ほど決めた名前を使う。なお、after_scriptに入れてはならない。というのも、after_scriptの実行コンテキストは他の2つのコンテキストとは別なためである。
なお、現在、複数アーキテクチャのイメージをコンテナレポジトリにpushすると、正しく表示されない不具合があるが、これはGitLabのIssueにも登録されているバグである。