定期的なタスクに使用されたときにdockerコンテナーを起動したままにする正しい方法


41

ソフトウェアをインストールおよび構成したdockerコンテナーがあります。

常に開始/実行されるはずのプログラムはありません。

私が欲しいもの-外部イベントに応じてコマンドを開始する機能。好む:

docker exec mysupercont /path/to/mycommand -bla -for

そして

docker exec mysupercont /path/to/myothercommand 

しかし、コンテナが停止している場合は「exec」が不可能であり、このコンテナにはそのコマンドに使用される「作業」データが含まれているため、使用できません

docker run ...

毎回、画像からコンテナを再作成し、データを破壊するためです。

そのようなコンテナを動かし続けるための「正しい」方法と「最良の」方法は何ですか?内部で起動できるコマンドはどれですか?


これは非常によく説明された質問です。ここで別の同様の投稿を参照してください。
グラントリー

1
docker run -d --name=name container tail -f /dev/null
蒸気駆動

回答:


46

毎回実行する必要はありませんdocker run

docker run 実際には、「作成」と「開始」の2つのコマンドのシーケンスです。

コンテナを実行するとき、「-it」を指定する必要があります。

-i、
--interactive = false 接続されていない場合でもSTDINを開いたままにします-t、--tty = false疑似TTYを割り当てます

例:

docker run -it debian:stable bash

作業が完了した後、起動時に指定されたコマンド(私の例ではbash)。たとえば、「終了」を実行します。コンテナの停止:

CONTAINER ID        IMAGE                      COMMAND                CREATED             STATUS                     PORTS               NAMES
1329c99a831b        debian:stable              "bash"                 51 seconds ago      Exited (0) 1 seconds ago                       goofy_bardeen

これで再び起動できます

docker start 1329c99a831b

コンテナが起動し、コマンド「bash」を再度実行します。
コマンドでこのセッション「bash」に接続します

docker attach 1329c99a831b

まとめるrunと、startコンテナとコンテナの違いを理解する必要があります。
また、「Run」のパラメーター「」と「」の役割については、ドキュメントをご覧ください-i t-d


1
ああ、私はこれを理解しています。質問は次のとおりです。コンテナ内で実行するものは何もありませんが、「実行」状態に維持する必要があります。そのため、bashを使用してコンテナを実行状態に維持しますか
コルジャビンイヴァン

はい。実行時に指定したプロセスは、引き続き動作するコンテナに対して実行する必要があります。最も単純な例はbashです。おそらく、「-d」でコンテナを起動し、必要に応じてを使用してコンテナに接続する最も簡単な方法になるでしょうdocker attach ID。bashのを終了せずにこのセッションから出て行け、あなたが使用することができますCTRL-p CTRL-q
MSemochkin

コンテナの実行中に指定したプロセスはPID 1を受け取ります。したがって、コンテナはそれなしでは機能しません
。simply

開始とアタッチ(または-aiで開始)の私の経験では、コマンドラインのプロンプトとインタラクティブな編集が表示されません。例えば、ttyはレンダリングもエコーもしていません。
dlamblin

1
これは気の利いたことです。手動で再起動せずにコンテナをバックグラウンドで起動する場合(Webサービスを実行している場合など)、「-itd」パラメーターとCTRL-p CTRL-qを使用して、容器。
タラナキ

6

停止したコンテナを開始できるかどうかのこのビジネス全体は、コンテナが最初に作成された方法、つまり実行方法に依存します。終了したコマンドを実行した場合、またはbashなどの対話型コマンドを終了した場合、停止したコンテナを起動、再起動、または実行することはできません。できるのはそれを削除することだけです。ジャンクだ。

しかし、taranakiの最後のコメントである '-itd'を使用することは、Dockerが注文したもののようです。

コンテナは実行され続け、必要なものを実行でき、コンテナを停止、開始、または再起動できます。もちろん、これは高山のイメージに基づいた予備調査結果にすぎません。コンテナにアタッチした場合、終了すると停止しますが、再起動できます。


2
+1 "ドッカーが注文したもののようです" :-)
マットアレクサンダー

5

あなたは定期的なタスクについて言及しており、おそらくあなたが使用したい方法のためにcronのようなものを使用しているのでdocker exec、私はあなたのための薬だけを持っています。少なくとも私はこのようなことをすることになりました。

  1. Dockerfile

    FROM <some base>
    CMD tail -f /dev/null
    
  2. 普通に実行しますdocker run -d ....(使用しましたdocker-compose

  3. ホストマシンcrontabをセットアップします。次に例を示します。

    * * * * * docker exec mysupercont foo >> /var/log/foo.log 2>&1
    * * * * * docker exec mysupercont bar >> /var/log/bar.log 2>&1
    

このソリューションは、かなりデフォルトのLinux環境で古くて実績のあるcrontabに依存するようになり、Dockerはビジネスロジックのよりエキゾチックなdepと環境変数を処理するので、素晴らしいと思います。定期的なタスクがスタックしてメモリリークなどが発生した場合も、いくつかの制限を設定できます。


0

テールは、時々いくつかのファイル操作を引き起こします。

これが副作用なしで永遠に眠る私の解決策です。

# Ah, ha, ha, ha, stayin' alive...
while true; do :; done & kill -STOP $! && wait $!

使い方

while true; do :; done & # do nothing(:) in background, in an endless loop
kill -STOP $!            # stop the background process of doing nothing
wait $!                  # wait forever, because doing nothing process is stopped

1
その実行を理解するのは難しい。3650dだけで眠らない理由
Pieter

1
確かに、スリープはおそらく私のソリューションと同じように機能しますが、スリープは最終的にタイムアウトします:-D PS:ソリューションを理解しやすくするためにコメントを追加します。
qoomon
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.