🚪

GitLab Runner とコンテナの entrypoint

2023/12/04に公開

これは GitLab Adventcalendar 2023 の 3日目 の記事です。

はじめに

GitLab Runner の docker executor や kubernetes executor で、こんな現象に見舞われたことはないでしょうか。

  • Preparing environment の段階で unable to upgrade connection: container not found というエラーでジョブが fail する
  • entrypoint が実行されるが、.gitlab-ci.yml のスクリプトが実行されない
  • entrypoint が実行されないで、スクリプトだけが実行される

その原因と対策を解説します。

Runner がコンテナを起動してスクリプトを実行するシーケンス

解説の前提として、Runner がどうやってコンテナを起動してスクリプトを実行しているのかを説明します。
ドキュメントのここに記載されている通り、こんなシーケンスです。

  1. コンテナを command を付けて起動 (command の内容は下記のコードブロックの通り)
  2. コンテナに attach
  3. attach したコンテナの shell の stdin にスクリプトを入力
  4. スクリプトの出力を stdout から取得

1.でコンテナを起動する際の command の内容

sh -c if [ -x /usr/local/bin/bash ]; then
	exec /usr/local/bin/bash 
elif [ -x /usr/bin/bash ]; then
	exec /usr/bin/bash 
elif [ -x /bin/bash ]; then
	exec /bin/bash 
elif [ -x /usr/local/bin/sh ]; then
	exec /usr/local/bin/sh 
elif [ -x /usr/bin/sh ]; then
	exec /usr/bin/sh 
elif [ -x /bin/sh ]; then
	exec /bin/sh 
elif [ -x /busybox/sh ]; then
	exec /busybox/sh 
else
	echo shell not found
	exit 1
fi

各現象の原因と対策

entrypoint が実行されるが、スクリプトが実行されない

原因

Runner は、前述のシーケンスの 2. ~ 3. の段階で、コンテナ内で shell が動作していることを期待しています。
コンテナは動作しているけれどもプロセスが shell ではない場合は、当然ですが 3. で入力されたスクリプトは実行されず、entrypoint だけが実行されてコンテナが終了します。

対策

command つまり entrypoint 内の "${@}" には前述のコマンドが渡されているので、entrypoint の最後でそれを exec しておきます。

exec "${@}"

Preparing environment の段階で unable to upgrade connection: container not found というエラーでジョブが fail する

原因

前述のシーケンスの 2. の段階で、attach 先のコンテナが存在しない、というエラーです。
Runner が attach する前に entrypoint つまり pid = 1 のプロセスが終了すると、コンテナも終了するのでこうなります。

対策

従って対策は前項と同じ、entrypoint の最後で shell を exec しておくことです。

exec "${@}"

entrypoint が実行されないで .gitlab-ci.yml のスクリプトだけが実行される

原因1

Kubernetes executor の場合、FF_KUBERNETES_HONOR_ENTRYPOINT というフィーチャーフラグを true にしないとentrypoint は実行されません。
これは、CI/CD変数がその設定方法次第で entrypoint 内で参照できないことがあるなどの制限事項があるためです。

対策1

フィーチャーフラグ FF_KUBERNETES_HONOR_ENTRYPOINTtrue (でも 1 でもいいんですが) に設定します。
Runner のフィーチャーフラグは、CI/CD変数か config.toml で設定できます

原因2

entrypoint は、.gitlab-ci/ymlimages.entrypoint: でオーバーライドできます。
.gitlab-ci.ymlimage: セクションに下記のように entrypoint: があると、オーバーライドされています。

  image:
    name: my-image
    entrypoint: [""]

対策2

コンテナで定義された entrypoint を実行したい場合は、image: セクションの entrypoint: を削除します。

Discussion