よくある質問と回答

あなたの質問がここになければ、freenode IRC の #docker-compose にあるコミュニティに、質問を気軽に投げてください。

サービスの再作成や停止に10秒かかるのはどうして?

Compose の停止(stop)とはコンテナに SIGTERM を送信して停止することです。 デフォルトのタイムアウトは 10 秒間です 。タイムアウトしたら、コンテナを強制停止するために SIGKILL を送信します。タイムアウトで待っているとは、つまり、コンテナが SIGTERM シグナルを受信しても停止しないのを意味します。

これはコンテナが プロセスのシグナルをどう扱うか(英語) の問題で言及されています。

この問題を解決するには、以下のことを試してください。

  • Dockerfile の CMDENTRYPOINT 命令で JSON 形式を使用する。

たとえば、 ["program", "arg1", "arg2"] の形式を使うのであり、 "program arg1 arg2" の形式を使いません。後者の文字列で指定すると、Docker はプロセスの実行に bash を使います。すると Docker は適切にシグナルを扱えません。 Compose では常に JSON 形式を使っていれば、Compose ファイル上のコマンドやエントリを書き換える心配は不要です。

  • 可能であれば、アプリケーションが SIGTERM シグナルを確実に扱えるように書き換えます。

  • アプリケーションを書き換え不可能な場合は、アプリケーションを( s6 のような)軽量な init システムを使うか、あるいはシグナルを( dumb-inittini などで)プロキシします。いずれかのラッパーを使い、 SIGTERM シグナルを適切に扱います。

同一ホスト上で Compose ファイルをコピーして、複数実行するには?

Compose での作成時は、プロジェクト名をユニークな識別子として使います。これはプロジェクト内の全てのコンテナや他のリソースに使います。プロジェクトをコピーして複数実行するには、 -p コマンドライン・オプション を使って任意のプロジェクト名を指定するか、あるいは COMPOSE_PROJECT_NAME 環境変数 を使います。

uprunstart の違いは何ですか?

一般的には docker-compose up が使われるでしょう。 up を使うと docker-compose.yml ファイル中で定義したサービスの開始または再起動を行います。デフォルトは「アタッチド」モードであり、全てのコンテナのログが画面上に表示されます。「デタッチド」モード( -d )では、Compose はコンテナを実行すると終了しますが、コンテナは後ろで動き続けます。

docker-compose run コマンドは「ワンオフ」(one-off;1つだけ、偶発的) または「アドホック」(adhoc;臨時)なタスクの実行に使います。実行するにはサービス名の指定が必要であり、特定のサービス用のコンテナを起動し、かつ依存関係のあるコンテナも起動します。 run の利用時は、テストの実行であったり、データ・ボリューム・コンテナに対するデータの追加・削除といった管理タスクです。 run コマンドは実際には docker run -ti を処理しており、コンテナに対してインタラクティブなターミナルを開き、コンテナのプロセスが終了すると、その時点の該当する終了コードを返します。

docker-compose start コマンドは既に作成済みのコンテナの再起動には便利です。しかし止まっているコンテナを起動するだけであり、新しいコンテナは作成しません。

Compose ファイルには、YAML の代わりに JSON を使えますか?

はい、 YAML は JSON のスーパーセットです 。そのため、あらゆる JSON ファイルは有効な YAML でもあります。Compose ファイルに JSON を使いたい場合は、ファイル名で( .json を )指定します。実行例:

docker-compose -f docker-compose.json up

データベースが起動するのを待ってからアプリケーションを起動するには?

残念ながら、正統な理由がなければ Compose はそのように処理できません。

データベースが準備するまで待たせることにより、分散システムにおいて非常に大きな問題となる可能性があります。プロダクション環境においては、データベースが使えなくなるか、あるいは他のホストに移動する場合があるでしょう。アプリケーションは、この種の障害に対する回復力を必要とします。

そのためには、アプリケーションがデータベースとの通信ができなくなっても、再度接続を試みるでしょう。もしアプリケーションのリトライが失敗したら、データベースに対する接続性は失われたと考えるべきです。

アプリケーションが正常になるまで待つためには、ヘルスチェックを実装する必要があります。ヘルスチェックはアプリケーションに対してリクエストを送り、ステータス・コードの応答が正常化どうかを確認します。もし成功しなければ、短時間待った後、再試行します。何度もタイムアウトをするようであれば、チェックを停止し、失敗を報告します。

もしアプリケーションに対する実行テストが必要であれば、ヘルスチェックを実行できます。ヘルスチェックの応答が正常であれば、テストを実行可能になります。

コードを入れるには COPYADD ですか、それともボリュームですか?

コードをイメージにコピーするには、 DockerfileCOPY または ADD 命令が使えます。これは Docker イメージのコードを置き換える場合に便利です。たとえば、コードを別の環境(プロダクション、CI 、等)に送りたい場合です。

コードを変更したい場合、すぐに反映したい場合は volume を使うべきでしょう。たとえば、コードをデプロイする場面で、サーバがホット・コード・リロードやライブ・リロードをサポートしている場合です。

両方の命令を使いたい場合があるかもしれません。開発環境上において、イメージに対してコードを追加する場合は COPY を使い、Compose ファイルにコードを含める場合は volume を使えます。ボリュームを使えばイメージの中にあるディレクトリの情報を上書きします。