web-dev-qa-db-ja.com

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

`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シェル形式とJSON形式など」について説明できますか?簡単な言葉で。

注意してください-同じことがcommand:ディレクティブdocker-compose.yml、 予想通り。

46
Vladan

2番目のコマンドはシェル処理を行いますが、最初のコマンドはそうではありません。公式 documentation によると、execおよびShellフォームがあり、最初のコマンドはexecフォームであり、たとえば、環境変数を展開しませんが、2番目のコマンドは1つあります。したがって、exec形式を使用すると、シェル処理に依存するためにコマンドが失敗する可能性があります。これはdocker logs CONTAINERIDを実行して確認できます

2番目のコマンドであるシェルフォームは-と同等です。

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

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

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

37
Daniel t.

自分に負担をかけないでください。 bashファイル「start.sh」を作成するだけです。

#!/bin/bash

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

dockerfileで次のようにします。

ADD start.sh /
RUN chmod +x /start.sh

CMD ["/start.sh"]
12
Digital Human

CMD(およびRUNおよび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によるコンテナーの異常な終了が発生します。 Shell execコマンドを使用すると、信号処理を軽減できます。

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

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

3
BMitch

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

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

1
devrimbaris

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

使用する代わりに

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

試す

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

dockerが「sh -c」を使用するため、上記のコマンドは次のように実行されます

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