Docker CMDディレクティブの複数のコマンド


39

実行時に `DockerfileのCMDディレクティブを介して2つのコマンドを実行しようとすると、何が起こっているのか理解できません。私はこれがうまくいくと仮定しました:

CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]

しかし、それは機能していません。コンテナは起動していません。だから私はこのようにしなければなりませんでした:

CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]

分かりません。何故ですか?なぜ最初の行が正しい方法ではないのですか?誰かがこれらの「CMDシェル形式vs JSON形式など」について説明してくれますか。簡単な言葉で。

ただ注意してください- 予想通り、command:ディレクティブはin でも同じでしたdocker-compose.yml

回答:


33

違いは関係があると思います。2番目のコマンドはシェル処理を実行しますが、最初のコマンドは実行しません。公式ドキュメントによれば、execand shellフォームがあり、最初のコマンドはexecフォームであり、たとえば環境変数を展開しませんが、2番目のコマンドは実行します。そのため、execフォームを使用すると、シェル処理への依存のためにコマンドが失敗する可能性があります。これを確認するには、次を実行しますdocker logs CONTAINERID

2番目のコマンド、シェル形式は-と同等です

CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm

ドキュメントからの抜粋-

注:シェルフォームとは異なり、execフォームはコマンドシェルを呼び出しません。これは、通常のシェル処理が行われないことを意味します。たとえば、ではCMD [ "echo", "$HOME" ]変数の置換を行いません$HOME。シェル処理が必要な場合は、シェル形式を使用するか、シェルを直接実行します(例:)CMD [ "sh", "-c", "echo", "$HOME" ]


環境変数が原因でコマンドが失敗した可能性があります。このexec形式は推奨形式なので、この形式を引き続き使用する必要がありますか?なぜそれが好ましいのですか?または、よりシンプルなshellフォームを使用する必要がありますか?
ウラダン

次から次へとコマンドを実行することはシェル関数であるため、失敗しました。環境変数は赤いニシンです。
ブライアン

Dockerで複数のサービスを実行している場合、supervisorなどのプロセスマネージャーを使用することをお勧めします。そうすれば、CMDセクションの下でスーパーバイザーのみを起動し、サービスの開始を処理します。詳細はこちらで確認できます-docs.docker.com/articles/using_supervisord
Daniel t。

これはちょうど私が読んでいた正確な記事です:)ありがとう。
ウラダン

なぜあなたがする必要があるのか​​まだわかりませんCMD [ "sh", "-c", "echo", "$HOME"]。なぜそうではないのCMD ["sh", "-c", "echo $HOME"]か、それに関してはCMD ["sh -c echo $HOME"]
sixty4bit

4

自分自身でそれを難し​​くしないでください。bashファイル「start.sh」を作成するだけです。

#!/bin/bash

/usr/bin/command2 param1
/usr/bin/commnad1

Dockerfileで以下を実行します。

ADD start.sh /

CMD ["/start.sh"]

2

CMD(およびRUNand ENTRYPOINT)のjson構文は、引数をカーネルに直接exec syscallとして渡します。exec syscallには、スペース、引用符のエスケープ、IOリダイレクション、変数置換、コマンド間のパイピング、複数のコマンドの実行などによる、コマンドと引数の分離はありません。syscallは、実行する実行可能ファイルと、その実行可能ファイルに渡す引数のリストのみを受け取り、実行します。

以下のような文字$、変数を展開するには;、別のコマンドに別々の引数に、(スペース)&&||チェーンコマンドには、>出力のリダイレクトに、|などのコマンド、間のパイプに、すべてのようなシェルと必要なものの特徴である/bin/shか、/bin/bashそれを解釈して実装します。


の文字列構文に切り替えるとCMD、dockerはシェルを使用してコマンドを実行します。

CMD /etc/init.d/nullmailer start ; /usr/sbin/php5-fpm

それ以外の場合、2番目の構文はまったく同じことを行います。

CMD ["sh", "-c", "/etc/init.d/nullmailer start ; /usr/sbin/php5-fpm"]

最初のコマンドが失敗した場合、特にバックグラウンドで実行された場合はエラー処理が行われないため、コンテナ内でこの方法で複数のコマンドを実行することはお勧めしません。また、コンテナー内でpid 1として実行されているシェルを残します。これにより、シグナルの処理が中断され、10秒の遅延と、Dockerによるコンテナーの不適切な強制終了が発生します。信号処理は、シェルexecコマンドを使用して軽減できます。

CMD /etc/init.d/nullmailer start ; exec /usr/sbin/php5-fpm

ただし、バックグラウンドでサイレントに失敗するプロセスを処理するには、supervisordのような何らかのマルチプロセスマネージャーに切り替えるか、できればアプリケーションを複数のコンテナーに分割して、docker-composeなどでデプロイする必要があります。


1

DOCKER CMD形式では、最初のパラメーターのみが実行され、残りはこのコマンドに入力されるため、最初のコマンドは失敗すると思います。

すべてのコマンドが「;」で区切られているため、2番目の形式が機能します shコマンドに渡され、実行されます。


1

「開始」の後にセミコンマを入れるべきではないと思う

使用する代わりに

CMD ["/etc/init.d/nullmailer", "start", ";", "/usr/sbin/php5-fpm"]

試してみる

CMD ["/etc/init.d/nullmailer", "start", "/usr/sbin/php5-fpm"]

ドッカーは「sh -c」を使用するため、上記のコマンドは以下のように実行されます

/etc/init.d/nullmailer start
/etc/init.d/nullmailer /usr/sbin/php5-fpm

json構文はシェルでコマンドを実行しませんsh -c。そのシナリオにはありません。
BMitch
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.