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 shell format vs JSON formatなど"のものを説明できますか? 簡単な言葉で。

ちょうど注意する-同じことがあった command: での指令 docker-compose.yml 予想通り。

違いは、2番目のコマンドがシェル処理を行い、最初のコマンドはシェル処理を行わないためかもしれないと思います。 あたり 公式文書、があります execshell フォーム。 あなたの最初のコマンドは exec フォーム。 その exec フォームは、環境変数を展開しません。 shell フォームはありません。 それは使用によってこと可能です exec フォームコマンドはシェル処理に依存しているために失敗しています。 これを確認するには、次を実行します docker logs CONTAINERID

あなたの第二のコマンド、シェル形式は、次のように相当します -

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

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

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

あなた自身でそれを堅くさせてはいけない。 ちょうどbashファイルを作成します"start.sh":

#!/bin/bash/usr/bin/command2 param1/usr/bin/command1

あなたのDockerfileでは、次のようにします:

ADD start.sh /RUN chmod +x /start.shCMD ["/start.sh"]

のjson構文 CMD (と RUNENTRYPOINT)引数を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"]

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

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

しかし、バックグラウンドで静かに失敗するプロセスを処理するには、supervisordのようなマルチプロセスマネージャに切り替えるか、アプリケーションを複数の

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

第二の形式は、";"で区切られたすべてのコマンドがshコマンドに供給され、それらを実行するために機能します。

たとえば、実行する2つのpythonコマンドがあるとします python init_reset.pypython app.py. 次に、CMDを使用して、2つのコマンドを単一のコマンドと組み合わせることができます

CMD python init_reset.py ; python app.py

Docker composeでは、これは次の例のように行うことができます:

command: ["sh", "-c", "    apt update && apt install -y libldap-common;    cp /ca.crt /usr/local/share/ca-certificates/;    update-ca-certificates;    exec apache2-foreground  "]

その exec メイン実行可能ファイルのコンテキストをapache2-forgroundに切り替えます。

私はあなたが"開始"の後に半コンマを置くべきではないと思います

を使用する代わりに

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