現在、JenkinsエージェントはRailsプロジェクトごとにdocker-compose.ymlを生成し、docker-compose upを実行します。 docker-compose.ymlには、rbenvと他のすべてのRails依存関係を内部に持つメインの「ウェブ」コンテナがあります。テストPostgres DBを含むDBコンテナにリンクされています。
問題は、実際にテストを実行して終了コードを生成する必要があるときに発生します。 CIサーバーは、テストスクリプトがexit 0を返す場合にのみデプロイされますが、コンテナコマンドの1つが失敗した場合でも、docker-composeは常に0を返します。
もう1つの問題は、Webコンテナーがテストの実行を完了した後でも、DBコンテナーが無期限に実行されるため、docker-compose up
が返されないことです。
このプロセスにdocker-composeを使用する方法はありますか?コンテナを実行できる必要がありますが、Webコンテナが完了して終了コードが返された後に終了します。現時点では、Dockerを使用してDBコンテナをスピンアップし、-linkオプションを使用してWebコンテナを実行します。
バージョン1.12.0
以降、--exit-code-from
オプションを使用できます。
ドキュメント から:
--exit-code-from SERVICE
選択したサービスコンテナの終了コードを返します。 --abort-on-container-exitを意味します。
docker-compose run
は、希望する終了ステータスを取得する簡単な方法です。例えば:
$ cat docker-compose.yml
roit:
image: busybox
command: 'true'
naw:
image: busybox
command: 'false'
$ docker-compose run --rm roit; echo $?
Removing test_roit_run_1...
0
$ docker-compose run --rm naw; echo $?
Removing test_naw_run_1...
1
別の方法として、 inspect dead containerのオプションがあります。 -f
フラグを使用して、終了ステータスのみを取得できます。
$ docker-compose up
Creating test_naw_1...
Creating test_roit_1...
Attaching to test_roit_1
test_roit_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
$ docker-compose ps -q | xargs docker inspect -f '{{ .Name }} exited with status {{ .State.ExitCode }}'
/test_naw_1 exited with status 1
/test_roit_1 exited with status 0
戻らないdbコンテナについては、docker-compose up
を使用する場合、そのコンテナをsigkillする必要があります。それはおそらくあなたが望むものではありません。代わりに、docker-compose up -d
を使用して、デーモン化されたコンテナを実行し、テストの完了時にコンテナを手動で強制終了できます。 docker-compose run
shouldリンクされたコンテナを実行しますが、SOでおしゃべりを聞いたことがあります。意図したとおりです。
Kojiroの答えに基づいて:
docker-compose ps -q | xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v '^0' | wc -l | tr -d ' '
返された0以外の終了コードの数を返します。すべてがコード0で終了した場合、0になります。
docker-compose run
を使用して手動でテストを開始する場合、奇妙なことに--rm
フラグを追加すると、Composeはコマンドの終了ステータスを正確に反映します。
これが私の例です。
$ docker-compose -v
docker-compose version 1.7.0, build 0d7bf73
$ (docker-compose run kpi false) || echo 'Test failed!' # False negative.
$ (docker-compose run --rm kpi false) || echo 'Test failed!' # True positive.
Test failed!
$ (docker-compose run --rm kpi true) || echo 'Test failed!' # True negative.
docker wait
を使用して、終了コードを取得します。
$ docker-compose -p foo up -d
$ ret=$(docker wait foo_bar_1)
foo
は「プロジェクト名」です。上記の例では、明示的に指定しましたが、指定しない場合はディレクトリ名です。 bar
は、docker-compose.ymlでテスト中のシステムに付ける名前です。
docker logs -f
も正しいことを行い、コンテナが停止すると終了することに注意してください。だからあなたは置くことができます
$ docker logs -f foo_bar_1
docker-compose up
とdocker wait
の間にあるため、テストの実行を監視できます。
--exit-code-from SERVICE
および--abort-on-container-exit
は、すべてのコンテナを最後まで実行する必要があるシナリオでは機能しませんが、コンテナの1つが早期に終了すると失敗します。たとえば、2つのテストスーツを異なるコンテナで同時に実行する場合です。
@spenthilの提案を使用すると、docker-compose
をスクリプトでラップして、コンテナが失敗すると失敗するようにできます。
#!/bin/bash
set -e
# Wrap docker-compose and return a non-zero exit code if any containers failed.
docker-compose "$@"
exit $(docker-compose -f docker-compose.ci.build.yml ps -q | tr -d '[:space:]' |
xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v 0 | wc -l | tr -d '[:space:]')
次に、CIサーバーでdocker-compose up
を./docker-compose.sh up
に変更します。
終了ステータスは次の方法で確認できます。
echo $(docker-compose ps | grep "servicename" | awk '{print $4}')
docker-Rails を使用すると、どのコンテナのエラーコードがメインプロセスに返されるかを指定できるため、CIサーバーで結果を判断できます。これはCIおよびRails for dockerの開発に最適なソリューションです。
例えば
exit_code: web
docker-Rails.yml
では、コマンドdocker-Rails ci test
の結果としてweb
コンテナの終了コードが生成されます。 docker-Rails.yml
は、標準docker-compose.yml
の単なるメタラッパーであり、異なる環境、つまり開発vsテストvs parallel_testsで同じ基本構成を継承/再利用する可能性を提供します。
1つのdockerエンジンで同じ名前のdocker-composeサービスをさらに実行する可能性があり、正確な名前がわからない場合:
docker-compose up -d
(exit "${$(docker-compose logs -f test-chrome)##* }")
echo %?
-test-chromeサービスから終了コードを返します
利点: