- サービスをジョブに連携するには
- サービスのヘルスチェックの仕組み
- どのようなサービスがあるか
.gitlab-ci.yml
ファイルでservices
を定義します。- サービスへのアクセス
- CI/CD変数をサービスに渡す
- 利用可能な設定
services
- 同じイメージから複数のサービスを起動する
- サービスのコマンド設定
services
とdocker run
(Docker-in-Docker)を並行して使用します。- Dockerインテグレーションの仕組み
- サービス・コンテナ・ログの取得
- ジョブのローカルデバッグ
- サービスコンテナ使用時のセキュリティ
- 共有/buildsディレクトリ
サービス内容
CI/CDを設定する際、ジョブが実行されるコンテナを作成するためのイメージを指定します。このイメージを指定するには、image
キーワードを使用します。
services
キーワードを使用すると、追加のイメージを指定できます。この追加イメージは、最初のコンテナで使用可能な別のコンテナを作成するために使用されます。2 つのコンテナは互いにアクセスでき、ジョブを実行するときに通信できます。
サービスイメージは任意のアプリケーションを実行できますが、最も一般的な使用例は、データベースコンテナなどを実行することです:
- MySQL
- PostgreSQL
- Redis
- JSONAPIを提供するマイクロサービスの例としてのGitLab
プロジェクトがビルドされるたびにmysql
などをインストールするよりも、既存のイメージを使用して追加のコンテナとして実行するほうが簡単で高速です。
データベース・サービスだけに限定されるわけではありません。.gitlab-ci.yml
に必要なサービスをいくつでも追加したり、手動でconfig.toml
を変更することができます。Docker Hubや非公開のコンテナレジストリにあるイメージなら、どんなものでもサービスとして使用できます。
サービスは、CIコンテナ自体と同じDNSサーバー、検索ドメイン、および追加ホストを継承します。
サービスをジョブに連携するには
コンテナのリンクがどのように機能するかをよりよく理解するには、コンテナをリンクするを参照してください。
アプリケーションにmysql
をサービスとして追加した場合、イメージはジョブコンテナにリンクされたコンテナを作成するために使用されます。
MySQL のサービスコンテナは、ホスト名mysql
でアクセスできます。データベースサービスにアクセスするには、ソケットやlocalhost
ではなく、mysql
という名前のホストに接続します。詳しくはサービスへのアクセスを参照してください。
サービスのヘルスチェックの仕組み
サービスは、ネットワークからアクセス可能な追加機能を提供するために設計されています。MySQLのようなデータベースやRedis、Docker-in-Dockerを使えるようにするdocker:dind
。CI/CDジョブの進行に必要で、ネットワークからアクセスできるものであれば何でも構いません。
これが動作することを確認するために、Runner:
- デフォルトでコンテナから公開されているポートをチェックします。
- これらのポートがアクセス可能になるのを待つ特別なコンテナを起動します。
チェックの第2ステージが失敗すると、警告が表示されます:*** WARNING: Service XYZ probably didn't start properly
。このイシューは、以下の理由で発生する可能性があります:
- サービスに開かれているポートがありません。
- タイムアウト前にサービスが正しく開始されておらず、ポートが応答していません。
ほとんどの場合、この警告はジョブに影響しますが、警告が表示されてもジョブが成功する場合もあります。例えば
- 警告が表示された直後にサービスが開始され、ジョブが最初からリンクされたサービスを使用していない場合。この場合、ジョブがサービスにアクセスする必要があったとき、すでに接続待ちの状態になっている可能性があります。
- サービスコンテナはネットワークサービスを提供していませんが、ジョブのディレクトリに対して何かを行っています(すべてのサービスはジョブディレクトリを
/builds
の下にボリュームとしてマウントしています)。この場合、サービスはそのジョブを実行し、ジョブが接続を試みていないため、失敗することはありません。
サービスが正常に開始された場合、before_script
が実行される前に開始されます。つまり、サービスをクエリするbefore_script
を書くことができます。
ジョブが失敗しても、ジョブの終了時にサービスは停止します。
どのようなサービスがあるか
前述したように、この機能はネットワークからアクセス可能なサービスを提供するために設計されています。データベースはそのようなサービスの最も単純な例です。
サービス機能は、定義されたservices
イメージからジョブのコンテナにソフトウェアを追加するようには設計されていません。
例えば、ジョブ内に以下のservices
が定義されている場合、php
、node
、go
コマンドはスクリプトで利用できず、ジョブは失敗します:
job:
services:
- php:7
- node:latest
- golang:1.10
image: alpine:3.7
script:
- php -v
- node -v
- go version
php
、node
、go
をスクリプトで利用できるようにする必要がある場合は、どちらかを選択する必要があります。
- 必要なツールをすべて含む既存のDockerイメージを選択します。
- 必要なツールがすべて含まれた独自のDockerイメージを作成し、ジョブで使用します。
.gitlab-ci.yml
ファイルでservices
を定義します。
ジョブごとに異なる画像とサービスを定義することも可能です:
default:
before_script:
- bundle install
test:2.6:
image: ruby:2.6
services:
- postgres:11.7
script:
- bundle exec rake spec
test:2.7:
image: ruby:2.7
services:
- postgres:12.2
script:
- bundle exec rake spec
または、image
とservices
の拡張設定オプションを渡すこともできます:
default:
image:
name: ruby:2.6
entrypoint: ["/bin/bash"]
services:
- name: my-postgres:11.7
alias: db-postgres
entrypoint: ["/usr/local/bin/db-postgres"]
command: ["start"]
before_script:
- bundle install
test:
script:
- bundle exec rake spec
サービスへのアクセス
アプリケーションとAPIのインテグレーションをテストするためにWordpressのインスタンスが必要だとします。その場合、例えば.gitlab-ci.yml
ファイルでtutum/wordpress
イメージを使用することができます:
services:
- tutum/wordpress:latest
サービスエイリアスを指定しない場合、ジョブが実行されるとtutum/wordpress
が起動します。ビルドコンテナから2つのホスト名でアクセスできます:
tutum-wordpress
tutum__wordpress
アンダースコアを含むホスト名は RFC 上有効ではなく、サードパーティのアプリケーションで問題が発生する可能性があります。
サービスのホスト名のデフォルトのエイリアスは、これらのルールに従って、そのイメージ名から作成されます。
- コロン (
:
) 以降はすべて取り除かれます。 - スラッシュ (
/
) はダブルアンダースコア (__
) に置き換えられ、メインのエイリアスが作成されます。 - スラッシュ (
/
) はシングルダッシュ (-
) に置き換えられ、セカンダリーエイリアスが作成されます (GitLab Runner v1.1.0 以降が必要です)。
デフォルトの動作を上書きするために、サービスのエイリアスを指定できます。
サービスの接続
外部 API が独自のデータベースと通信する必要があるエンドツーエンドテストのような複雑なジョブでは、相互に依存するサービスを使用できます。
たとえば、API を使用するフロントエンドアプリケーションのエンドツーエンドテストで、API がデータベースを必要とします:
end-to-end-tests:
image: node:latest
services:
- name: selenium/standalone-firefox:${FIREFOX_VERSION}
alias: firefox
- name: registry.gitlab.com/organization/private-api:latest
alias: backend-api
- postgres:14.3
variables:
FF_NETWORK_PER_BUILD: 1
POSTGRES_PASSWORD: supersecretpassword
BACKEND_POSTGRES_HOST: postgres
script:
- npm install
- npm test
このソリューションを動作させるには、ジョブごとに新しいネットワークを作成するネットワーキング・モードを使用する必要があります。
CI/CD変数をサービスに渡す
Dockerimages
やservices
を微調整するためのカスタムCI/CD変数を .gitlab-ci.yml
ファイルで直接渡すこともできます。詳しくは.gitlab-ci.yml
定義変数をお読みください。
# The following variables are automatically passed down to the Postgres container
# as well as the Ruby container and available within each.
variables:
HTTPS_PROXY: "https://10.1.1.1:8090"
HTTP_PROXY: "https://10.1.1.1:8090"
POSTGRES_DB: "my_custom_db"
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "example"
PGDATA: "/var/lib/postgresql/data"
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --data-checksums"
default:
services:
- name: postgres:11.7
alias: db
entrypoint: ["docker-entrypoint.sh"]
command: ["postgres"]
image:
name: ruby:2.6
entrypoint: ["/bin/bash"]
before_script:
- bundle install
test:
script:
- bundle exec rake spec
利用可能な設定services
GitLabとGitLab Runner 9.4で導入されました。
設定 | 必須 | GitLabバージョン | 説明 |
---|---|---|---|
name | 他のオプションと併用する場合は必須 | 9.4 | 使用す る イ メ ージ の完全名。完全なイメージ名にレジストリホスト名が含まれている場合は、alias オプションを使用して、より短いサービスアクセス名を定義します。詳細については、サービスへのアクセスを参照してください。 |
entrypoint | いいえ | 9.4 | コンテナのエントリポイントとして実行するコマンドまたはスクリプト。コンテナの作成時に Docker--entrypoint オプションに変換されます。構文はDockerfile のENTRYPOINT ディレクティブに似ており、各シェルトークンは配列内の個別の文字列です。 |
command | いいえ | 9.4 | コンテナのコマンドとして使用するコマンドまたはスクリプト。イメージ名の後に Docker に渡される引数に変換されます。構文はDockerfile のCMD ディレクティブに似ており、各 Shell トークンは配列内の個別の文字列となります。 |
alias (1) | いいえ | 9.4 | ジョブのコンテナからサービスにアクセスするために使用できる追加のエイリアスです。詳細については、サービスへのアクセスを参照してください。 |
variables (2) | いいえ | 14.5 | サービスにのみ渡される追加の環境変数。構文はジョブ変数と同じです。サービス変数は自分自身を参照することはできません。 |
(1) Kubernetes ExecutorのエイリアスサポートはGitLab Runner 12.8で導入され、Kubernetesバージョン1.7以降でのみ利用可能です。
(2) DockerとKubernetes Executorのサービス変数サポートはGitLab Runner 14.8で導入されました。
同じイメージから複数のサービスを起動する
GitLabとGitLab Runnerの9.4で導入されました。詳細は拡張設定オプションを参照してください。
新しい拡張Docker設定オプションが導入される前には、以下の設定が正しく動作しませんでした。
services:
- mysql:latest
- mysql:latest
Runnerは2つのコンテナを起動し、それぞれがmysql:latest
。ランナーは、mysql
イメージを使用する2つのコンテナを起動しますが、デフォルトのホスト名命名に基づき、 エイリアスでジョブのコンテナに追加されます。この場合、サービスの1つにアクセスできなくなります。
新しい拡張Docker設定オプションの導入後は、上記の例は以下のように動作が変更されます。
services:
- name: mysql:latest
alias: mysql-1
- name: mysql:latest
alias: mysql-2
Runnerはmysql:latest
イメージを使って2つのコンテナを起動しますが、それぞれのコンテナには.gitlab-ci.yml
ファイルで設定したエイリアスでもアクセスできるようになります。
サービスのコマンド設定
GitLabとGitLab Runnerの9.4で導入されました。詳細は拡張設定オプションを参照してください。
SQLデータベースを内部に持つsuper/sql:latest
。これをジョブのサービスとして使用したいとします。また、このイメージはコンテナの起動時にデータベースプロセスを開始しないとします。ユーザーは手動で/usr/bin/super-sql run
をコマンドとして使用してデータベースを起動する必要があります。
新しい拡張Docker設定オプションの前は、以下のことが必要でした:
-
super/sql:latest
イメージをベースに独自のイメージを作成します。 - デフォルトのコマンドを追加します。
-
ジョブの設定で画像を使用します。
-
my-super-sql:latest
イメージのDockerfileを使います:FROM super/sql:latest CMD ["/usr/bin/super-sql", "run"]
-
.gitlab-ci.yml
内のジョブで:services: - my-super-sql:latest
-
新しい拡張Docker設定オプションの後は、代わりに.gitlab-ci.yml
ファイルでcommand
:
services:
- name: super/sql:latest
command: ["/usr/bin/super-sql", "run"]
command
の構文はDockerfileCMD
と似ています。
services
とdocker run
(Docker-in-Docker)を並行して使用します。
docker run
で起動したコンテナは GitLab が提供するサービスにも接続できます。
サービスを起動するのにコストがかかったり時間がかかったりする場合は、このテクニックを使ってさまざまなクライアント環境からテストを実行し、テスト対象のサービスは一度だけ起動するようにしましょう。
access-service:
stage: build
image: docker:20.10.16
services:
- docker:dind # necessary for docker run
- tutum/wordpress:latest
variables:
FF_NETWORK_PER_BUILD: "true" # activate container-to-container networking
script: |
docker run --rm --name curl \
--volume "$(pwd)":"$(pwd)" \
--workdir "$(pwd)" \
--network=host \
curlimages/curl:7.74.0 curl "http://tutum-wordpress"
この解決策を実行するには
- ジョブごとに新しいネットワークを作成するネットワークモードを使用してください。
-
DockerソケットバインディングでDocker Executorを使用しないでください。どうしても必要な場合は、上記の例では、
host
の代わりに、このジョブのために作成された動的ネットワーク名を使用してください。
Dockerインテグレーションの仕組み
以下、ジョブの実行中にDockerで実行されるステップを高レベルでまとめてみました。
- 任意のサービスコンテナを作成:
mysql
,postgresql
,mongodb
,redis
. - ビルドイメージの
config.toml
とDockerfile
で定義されているすべてのボリュームを格納するキャッシュコンテナを作成します ( 上記の例ではruby:2.6
)。 - ビルド・コンテナを作成し、任意のサービス・コンテナをビルド・コンテナにリンクします。
- ビルド・コンテナを起動し、コンテナにジョブ・スクリプトを送信します。
- ジョブ・スクリプトを実行します。
-
/builds/group-name/project-name/
にコードをチェックアウトします。 -
.gitlab-ci.yml
で定義されたステップを実行します。 - ビルドスクリプトの終了ステータスをチェックします。
- ビルド・コンテナと作成されたすべてのサービス・コンテナを削除します。
サービス・コンテナ・ログの取得
GitLab Runner 15.6で導入されました。
サービスコンテナ内で実行されているアプリケーションによって生成されたログは、その後の調査やデバッグのためにキャプチャすることができます。サービスコンテナのログを見たいのは、サービスコンテナが正常に起動したものの、期待通りの動作をしておらず、ジョブの失敗につながっている場合でしょう。ログは、コンテナ内のサービスの設定漏れや不正確さを示している可能性があります。
CI_DEBUG_SERVICES
サービスコンテナのログをキャプチャすると、ストレージとパフォーマンスの両方に影響があるため、サービスコンテナがアクティブにデバッグされている場合にのみ有効にしてください。
サービスロギングを有効にするには、プロジェクトの.gitlab-ci.yml
ファイルにCI_DEBUG_SERVICES
変数を追加します:
variables:
CI_DEBUG_SERVICES: "true"
受け入れられる値は以下のとおりです:
- 有効です:
TRUE
true
、True
- 無効
FALSE
false
、False
これ以外の値を指定するとエラーメッセージが表示され、実質的に機能が無効になります。
有効にすると、_すべての_サービスコンテナのログがキャプチャされ、他のログと同時にジョブトレースログにストリーミングされます。各コンテナからのログは、コンテナのエイリアスが先頭に付き、異なる色で表示されます。
CI_DEBUG_SERVICES
マスクされた変数が明らかに CI_DEBUG_SERVICES
なるCI_DEBUG_SERVICES
ことがあります CI_DEBUG_SERVICES
。有効にCI_DEBUG_SERVICES
すると CI_DEBUG_SERVICES
、サービスコンテナのログと CI ジョブのログが_同時に_ジョブのトレースログにストリームされるため、ジョブのマスクされたログの_中に_サービスコンテナのログが挿入される可能性があります。これにより、変数のマスキングメカニズムが妨害され、マスキングされた変数が明らかになります。CI/CD 変数のマスクを参照してください。
ジョブのローカルデバッグ
以下のコマンドはroot権限なしで実行します。ユーザーアカウントでDockerを実行できるはずです。
まず、build_script
というファイルを作成します:
cat <<EOF > build_script
git clone https://gitlab.com/gitlab-org/gitlab-runner.git /builds/gitlab-org/gitlab-runner
cd /builds/gitlab-org/gitlab-runner
make
EOF
ここでは、Makefileを含むGitLab Runnerリポジトリを例にしているので、実行make
するとMakefileで定義されたコマンドが make
実行されます。のmake
代わりに make
、プロジェクト固有のコマンドを実行することもできます。
次に、いくつかのサービスコンテナを作成します。
docker run -d --name service-mysql mysql:latest
docker run -d --name service-postgres postgres:latest
それぞれ最新のMySQLイメージとPostgreSQLイメージを使用するservice-mysql
とservice-postgres
という名前の2つのサービスコンテナを作成します。どちらもバックグラウンドで実行されます (-d
)。
最後に、先ほど作成したbuild_script
ファイルを実行してビルドコンテナを作成します:
docker run --name build -i --link=service-mysql:mysql --link=service-postgres:postgres ruby:2.6 /bin/bash < build_script
build
このコンテナはruby:2.6
イメージから生成され、2 つのサービスがリンクされています。build_script
はstdin
を使って Bash インタープリターにパイプされ、Bash インタープリターはbuild
コンテナでbuild_script
を実行します。
テストが終了しコンテナが不要になったら、コンテナを削除します。
docker rm -f -v build service-mysql service-postgres
これにより、build
コンテナ、2 つのサービスコンテナ、およびコンテナ作成時に作成されたすべてのボリューム (-v
) が強制的に (-f
) 削除されます。
サービスコンテナ使用時のセキュリティ
Docker特権モードはサービスに適用されます。これは、サービスイメージコンテナがホストシステムにアクセスできることを意味します。信頼できるソースからのコンテナイメージのみを使用する必要があります。
共有/buildsディレクトリ
すべてのサービスは、ジョブディレクトリを/builds
以下のボリュームとしてマウントしているため、ビルドからファイルにアクセスできます。