停止したDockerコンテナーを別のコマンドで開始するにはどうすればよいですか?


250

デフォルトのコマンドがクラッシュするため、停止したDockerコンテナーを別のコマンドで開始したいと思います。つまり、コンテナーを開始してから「docker exec」を使用できません。

基本的にシェルを起動して、コンテナーの内容を検査できるようにしたいと考えています。

幸い、私は-itオプションでコンテナを作成しました!

回答:


380

停止したコンテナーIDを見つける

docker ps -a

停止したコンテナをコミットします。

このコマンドは、変更されたコンテナーの状態を新しいイメージに保存します user/test_image

docker commit $CONTAINER_ID user/test_image

別のエントリポイントで開始/実行します。

docker run -ti --entrypoint=sh user/test_image

エントリーポイント引数の説明:https ://docs.docker.com/engine/reference/run/#/entrypoint-default-command-to-execute-at-runtime

注意:

上記の手順は、停止したコンテナを同じファイルシステム状態で起動するだけです。これは迅速な調査に最適です。ただし、環境変数、ネットワーク構成、接続されているボリューム、その他のスタッフは継承されないため、これらの引数をすべて明示的に指定する必要があります。

停止したコンテナーを開始する手順は、ここから借用されています:(最後のコメント)https://github.com/docker/docker/issues/18078


1
いいえ、画像は読み取り専用です。これは、新しいイメージtest_imageに変更コンテナの状態を保存
Dmitriusan

4
これは、env、volumes、UIDなどに関するほぼすべての構成を見逃します。停止されたコンテナーと共通するのは、ファイルシステム(これで十分な場合もあります)
Florian Klein

4
どういうわけか、同じ環境、ネットワーク構成、接続されたボリュームを取得できたら素晴らしいと思います。inspect出力を後続の実行で使用される構成に変換することは可能ですか?
Otheus

2
@Webman、はい、しかしそれはコンテナーを停止する前にマウントされたボリュームには当てはまりません。次回コンテナを起動するときに、同じボリュームを明示的に接続する必要があります
Dmitriusan

1
@EmreTapcı、それはDockerイデオロギーに反すると思います。コンテナーは、仮想マシンとは対照的に、使い捨ての使い捨てエンティティになることを目的としています。あなたはaaa90210の答えを追おうとするかもしれませんが、それはハックでしょう。
ドミトリウサン2018年

126

このファイルを編集します(停止したコンテナに対応):

vi /var/lib/docker/containers/923...4f6/config.json

「パス」パラメーターを変更して、新しいコマンドをポイントします(例:/ bin / bash)。コマンドに引数を渡すために "Args"パラメータを設定することもできます。

dockerサービスを再起動します(これにより、実行中のすべてのコンテナーが停止することに注意してください)。

service docker restart

コンテナーをリストし、コマンドが変更されていることを確認します。

docker ps -a

コンテナを起動してアタッチします。これでシェルに入るはずです!

docker start -ai mad_brattain

Docker 1.7.1を使用してFedora 22で作業しました。

注:シェルがインタラクティブでない場合(たとえば、-itオプションで元のコンテナーを作成しなかった場合)、代わりにコマンドを「/ bin / sleep 600」または「/ bin / tail -f / dev / null」に変更できます。シェルを取得する別の方法として「docker exec -it CONTID / bin / bash」を実行するのに十分な時間を与えるため。

注2:dockerの新しいバージョンにはconfig.v2.jsonがあり、EntrypointまたはCmdのいずれかを変更する必要があります(user60561に感謝)。


44
私の目。私の目。これがDockerでこれを適切に処理するための機能要求であることを願っています。
gertvdijk 2016年

2
@AlexeyStrakh "/ usr / bin / sleep 600"を実行してから "docker exec -it / bin / bash"を実行してシェルを取得できます。そのパス変数にパラメーターを配置する方法はわかりませんが。それ以外の場合は、execを実行するのに十分長く存続する別のコマンドを探すか、Dmitriusanからの回答を参照してください。
aaa90210 2016年

3
他のすべての命題は「ほとんど同じ」コンテナを実行しますが、ボリューム、env、UIDなどを忘れます
Florian Klein

3
私の場合、/ usr / bin / sleepは利用できませんでした。私は成功しました..."Path":"tail","Args":["-f","/dev/null"]...
nevrome

4
ドッキングウィンドウの新しいバージョンを持っているconfig.v2.jsonあなたはどちらか変更する必要があります場所、EntrypointまたはCmd
user60561

20

Entrypointスクリプトの上部にチェックを追加します

Dockerはこれを新機能として実際に実装する必要がありますが、成功または失敗後に終了するエントリポイントがある状況での別の回避策オプションがあります。これにより、デバッグが困難になる可能性があります。

エントリーポイントスクリプトがない場合は、コンテナに必要なコマンドを実行するスクリプトを作成します。次に、このファイルの先頭で、次の行を追加しますentrypoint.sh

# Run once, hold otherwise
if [ -f "already_ran" ]; then
    echo "Already ran the Entrypoint once. Holding indefinitely for debugging."
    cat
fi
touch already_ran

# Do your main things down here

catが接続を保持していることを確認するには、TTYを提供する必要がある場合があります。私はエントリポイントスクリプトでコンテナを実行しています。

docker run -t --entrypoint entrypoint.sh image_name

これにより、スクリプトが1回実行され、(コンテナーの仮想ファイルシステムで)既に実行されたことを示すファイルが作成されます。次に、コンテナを再起動してデバッグを実行できます。

docker start container_name

コンテナーを再起動すると、already_ranファイルが見つかり、Entrypointスクリプトが停止しますcat(これにより、永遠に入力されない入力を待ちますが、コンテナーは存続します)。その後、デバッグbashセッションを実行できます。

docker exec -i container_name bash

コンテナーの実行中にデバッグする必要がある場合already_ranは、entrypoint.shスクリプトを削除して手動で実行し、再実行することもできます。


3
さらに、エントリポイントを実行する/bin/sh代わりに実行することもできます。そうすれば、catいつでも再起動することができます。あなたのソリューションは素晴らしいです!
ダニーデュライ

4

私の問題:

  • 私はコンテナを始めました docker run <IMAGE_NAME>
  • そして、このコンテナにいくつかのファイルを追加しました
  • 次に、コンテナーを閉じて、上記と同じコマンドでコンテナーを再起動しました。
  • しかし、新しいファイルを確認したところ、ファイルがありませんでした
  • 実行するdocker ps -aと、2つのコンテナが表示されました。
  • つまりdocker run <IMAGE_NAME>、コマンドを実行するたびに、新しいイメージが作成されていました

解決策: 最初に作成したのと同じコンテナで作業するには、次の手順に従います。

  • docker ps コンテナのコンテナを取得する
  • docker container start <CONTAINER_ID> 既存のコンテナを開始する
  • その後、離れたところから続行できます。例えばdocker exec -it <CONTAINER_ID> /bin/bash
  • 次に、それから新しいイメージを作成することを決定できます

これは質問の答えにはなりません。OPはコンテナーを再起動する方法を知りたいが、引数が異なるdocker run <containerID>
CodeBlooded

2

私は@Dmitriusanの回答を取り、それをエイリアスにしました:

エイリアスdocker-run-prev-container = 'prev_container_id = "$(docker ps -aq | head -n1)" && docker commit "$ prev_container_id" "prev_container / $ prev_container_id" && docker run -it --entrypoint = bash "prev_container / $ prev_container_id "'

これを~/.bashrcエイリアスファイルに追加docker-run-prev-containerすると、前のコンテナのシェルにドロップする気の利いた新しいエイリアスが作成されます。

失敗したdocker buildのデバッグに役立ちます。


2

これは正確にあなたが求めているものではありませんが、必要なのがdocker exportファイルを検査することだけであれば、停止したコンテナで使用できます。

mkdir $TARGET_DIR
docker export $CONTAINER_ID | tar -x -C $TARGET_DIR

1

コンテナーが終了するかどうかは指定されていません。コードがクラッシュし、コンテナーで何が行われているのかを確認する必要があるだけです。存在しない場合は、別の解決策が考えられます。

コンテナIDを取得する docker ps

docker exec -it 665b4a1e17b6 /bin/sh

entrypointが問題のある何かに設定されている場合、Dmitriusanの回答で提案されているように、それをオーバーライドすることもできます。また、を使用して、実行中の任意のコンテナに接続できることにも注意してくださいdocker attach。非常に多くのソリューションは異なるソリューションです。画像にコミットする必要があるとは思いません。必要ないようです。

Docker execのドキュメント-https ://docs.docker.com/engine/reference/commandline/exec/

Dockerアタッチのドキュメント-https ://docs.docker.com/engine/reference/commandline/attach/


-12

私はこれらの答えの両方に実際には同意しません。コンテナーの内容を確認するだけの場合は、このコマンドを実行してシェルを取得できます。エントリーポイントを変更したり、設定を変更したりする必要はありません。

docker run -it <image_name> bash

12
これは、opではイメージではなくコンテナーについて尋ねているため、機能しません。
Peter Vrabel

私はあなたの権利を推測しますが、そうする理由はわかりません。ログをstdoutにパイプしdocker logs <container_id> --followて、必要なものを提供できます。別の方法としては、上記のコマンドを使用してから、そのイメージでdockerfileの同じコマンドを使用してクラッシュするサービスを開始し、そこからデバッグします。
deadbabykitten

4
runコマンドは、イメージから新しいコンテナーを作成します。停止しているコンテナは起動しません。
Waleed Abdulla

2
うーん、.. dockerのポイントは、すべての画像がまったく同じ方法でスピンアップできるということではありませんか?これはあなたの主張を否定します。彼は停止したコンテナを起動する必要はありません。どのコンテナもまったく同じなので、どのコンテナを開始または停止するかは重要ではありません。彼は中身を調べようとしているだけです。これを行う最も簡単な方法は、bashを実行して、コマンドを実行するか、コマンドの出力をログにパイプすることです。皆さんは簡単な問題の最も複雑な解決策を思いつくこともあります。
deadbabykitten 2017年

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