Docker CMDを複数回使用して複数のサービスを実行できないのはなぜですか?


96

centos + sshという名前のDockerfileからベースイメージを構築しました。centos + sshのDockerfileでは、CMDを使用してsshサービスを実行しています。

次に、rabbitmqというDockerfileという名前の別のサービスを実行してイメージを構築します。

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD /opt/mq/sbin/rabbitmq-server start

rabbitmqコンテナーを起動するには、次を実行します。

docker run -d -p 222:22 -p 4149:4149 rabbitmq

sshサービスは機能しません。rabbitmqのDockerfile CMDがcentosのCMDをオーバーライドしていることを検出します。

  1. CMDはdocker image内でどのように機能しますか?
  2. 複数のサービスを実行したい場合、どうすればよいですか?スーパーバイザを使用していますか?

回答:


62

CMDはDockerfileに書き留められていますが、実際にはランタイム情報です。EXPOSEと同じですが、たとえばRUNおよびADDとは逆です。これにより、後で、拡張されたDockerfileで、またはrunコマンドで単純にオーバーライドできます。常に、CMDは1つしか存在できません。

複数のサービスを実行したい場合、私は実際にスーパーバイザーを使用します。各サービスのスーパーバイザー構成ファイルを作成し、これらをディレクトリに追加し、スーパーバイザーを実行して、supervisord -c /etc/supervisorすべてのサービスをロードし、次のようなスーパーバイザー構成ファイルを指すことができます

[supervisord]
nodaemon=true

[include]
files = /etc/supervisor/conf.d/*.conf

詳細をご希望の場合は、こちらのブログをこちらに書き込みました:http : //blog.trifork.com/2014/03/11/using-supervisor-with-docker-to-manage-processes-supporting-image-継承/


おかげで、上司は良いアイデアですが、私は、ドッキングウィンドウの画像内のCMDの仕事をどうするか不思議だ
edwardsbean

2
2.複数のサービスを実行する上で2つの質問をしました。CMDがどのように機能するのか疑問に思ったら、具体的に知りたいことを詳しく説明してください。これはランタイム情報であり、新しいCMDによって上書きされることはすでに述べました。
qkrijger 2014年

118

そうです、2番目のDockerfileはCMD最初のDockerfileを上書きします。Dockerは常に1つ以上のコマンドを実行します。したがって、Dockerfileの最後に、実行するコマンドを1つ指定できます。それ以上ではありません。

ただし、両方のコマンドを1行で実行できます。

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD service sshd start && /opt/mq/sbin/rabbitmq-server start

Dockerfileをもう少しきれいにするために何ができるか、CMDコマンドを追加のファイルに置くことができます。

FROM centos+ssh
EXPOSE 22
EXPOSE 4149
CMD sh /home/centos/all_your_commands.sh

そして、このようなファイル:

service sshd start &
/opt/mq/sbin/rabbitmq-server start

1
おかげで、私はスーパーバイザーを使用する方が良いと思います。
edwardsbean 2014年

1
何が起こっているのか分かりません。しかし、私はそれがそのように設計されていると思います。イメージがあり、その中でコマンドを実行すると(例:CMDを使用)、コンテナーが起動します。コンテナーは、コマンドが実行されている限り実行されます。そして、コマンドが終了するとすぐに、コンテナーも停止します。したがって、各コンテナーは1つの(実行中の)コマンドを表します。
Thomas Uhrig 2014年

lcxか何かの限界が原因だと思います
edwardsbean 2014年

2
@ Tyguy7 .. なぜなら ................?
StartupGuy

1
&&この手法は、非対話型サービス(バックグラウンドで開始できる)でのみ機能します。それ以外の場合は、最初のサービスのみが実行されます。
noraj

26

この問題を回避する方法を説明するqkrijgerからの回答を尊重していますが、ここで何が行われているのかを知ることができることはまだまだたくさんあると思います...

なぜ」という質問に実際に回答するには... docker stopコマンドがどのように機能するかを理解し、プロセスを再起動しようとするときの問題(ファイルの破損など)を防ぐために、すべてのプロセスを完全シャットダウンする必要があると思います。

問題:docker コマンドからSSH 開始し、DockerファイルからRabbitMQを開始した場合どうなりますか?" docker stopコマンドは、コンテナー内のルートプロセス(PID 1)にSIGTERMシグナルを送信することにより、最初に実行中のコンテナーを停止しようとします。 "どのプロセスが、SIGTERMを取得するPID 1としてドッキングプロセスを追跡していますか?SSHですか、それともウサギですか?「Unixプロセスモデルによると、initプロセス-PID 1-はすべての孤立した子プロセスを継承し、それらを取得する必要があります。ほとんどのDockerコンテナーには、これを正しく実行するinitプロセスがないため、コンテナーがいっぱいになります。ゾンビは時間をかけて処理します。」

回答:ドッカーは、単にその最後CMDを取る1として発売されますルートプロセス PID 1としてからSIGTERMを取得しますdocker stop

推奨される解決策:phusion / baseimageなど、複数のサービスを実行するために特別に作成されたベースイメージを使用(または作成)する必要があります

ことに注意することが重要であるべきTINIは、このような理由のために正確に存在し、ドッカー1.13の最大として、TINIは正式ドッカーで複数のプロセスを実行するとことを教えてくれるドッカーの一部であり、有効です。..そうたとえ誰かに主張 Dockerについてより熟練し、これを行うことを考えるのは馬鹿げていると主張し、そうでないことを知ってください。そうするための完全に有効な状況があります。

知っておきたいこと:


3

コンテナ内で複数のサービス実行するための公式のドッカーの答え。

これは、initシステム(systemd、sysvinit、upstart)、スクリプト(CMD ./my_wrapper_script.sh)、またはのようなスーパーバイザーでそれを行う方法を説明していますsupervisord

この&&回避策は、バックグラウンド(デーモン)で開始するサービス、または対話なしで迅速に実行され、プロンプトを解放するサービスに対してのみ機能します。(プロンプトを保持する)対話型サービスでこれを行うと、最初のサービスのみが開始されます。


0

CMDがコンテナーごとに1つのサービスのみを実行するように設計されている理由に対処するために、同じコンテナーで実行されるセカンダリサーバーが単純ではない/補助的ではなく「主要」(たとえば、フロントエンドアプリにバンドルされているストレージ)である場合に何が起こるかを理解しましょう。まず、ノード間の水平(自動)スケーリングや再スケジュールなど、いくつかの重要なコンテナー化機能を分類します。どちらも、コンテナーごとに1つのアプリケーション(CPU負荷のソース)しかないことを前提としています。次に、脆弱性の問題があります-コンテナーに公開されているサーバーが多いほど、CVEのパッチの頻度が高くなります...

したがって、それはDocker(およびKubernetes / Openshift)の設計者による優れた実践への「ナッジ」であり、回避策を再発明すべきではないことを認めましょう(SSHは必要ありません-私たちはdocker exec / kubectl exec / oc rshそれを置き換えるように設計しました)。

  • より詳しい情報

/devops/447/why-it-is-recommended-to-run-only-one-process-in-a-container

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.