web-dev-qa-db-ja.com

CIでdocker-composeを使用する-終了コードとデーモン化されたリンクコンテナを処理する方法は?

現在、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コンテナを実行します。

74
Logan Serman

バージョン1.12.0以降、--exit-code-fromオプションを使用できます。

ドキュメント から:

--exit-code-from SERVICE

選択したサービスコンテナの終了コードを返します。 --abort-on-container-exitを意味します。

64
panjan

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 runshouldリンクされたコンテナを実行しますが、SOでおしゃべりを聞いたことがあります。意図したとおりです。

35
kojiro

Kojiroの答えに基づいて:

docker-compose ps -q | xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v '^0' | wc -l | tr -d ' '

  1. コンテナIDを取得
  2. 各コンテナIDの最後の実行終了コードを取得する
  3. 「0」で始まらないステータスコードのみ
  4. 0以外のステータスコードのカウント数
  5. 空白を切り取る

返された0以外の終了コードの数を返します。すべてがコード0で終了した場合、0になります。

22
spenthil

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.
6
esmail

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 updocker waitの間にあるため、テストの実行を監視できます。

6
Bryan Larsen

--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に変更します。

5
Matt Cole

終了ステータスは次の方法で確認できます。

echo $(docker-compose ps | grep "servicename" | awk '{print $4}')
2
RT Bathula

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
kross

1つのdockerエンジンで同じ名前のdocker-composeサービスをさらに実行する可能性があり、正確な名前がわからない場合:

docker-compose up -d
(exit "${$(docker-compose logs -f test-chrome)##* }")

echo %?-test-chromeサービスから終了コードを返します

利点:

  • 正確なサービスが終了するのを待ちます
  • コンテナ名ではなくサービス名を使用します
0
cvakiitho