web-dev-qa-db-ja.com

Dockerコンテナ内でctrl + cを修正する方法

Dockerコンテナに接続する場合

$> docker exec -it my_container zsh

そしてその中からctrl+cで始めた何かを殺したいのです。完了するには永遠に時間がかかることに気付きました。私はグーグルで調べたが、ctrl+cはあなたが期待するものとは少し異なるように見える。私の質問、コンテナ内でctrl+cを修正するにはどうすればよいですか?

16

問題は、Ctrl-Cがコンテナ内の最上位プロセスにシグナルを送信することですが、そのプロセスは必ずしも期待どおりに反応するとは限りません。最上位プロセスのコンテナ内のIDは1です。つまり、プロセスが通常持っているデフォルトのシグナルハンドラを取得しません。最上位プロセスがシェルの場合、独自のハンドラーを介してシグナルを受信できますが、シェル内で実行されるコマンドにそれを転送しません。詳細は こちら で説明されています。どちらの場合でも、Dockerコンテナは、単にCtrl-Cを無視するように動作します。

docker 0.6.5から始めて、-tをdocker runコマンドに追加して、pseudo-TTYをアタッチできます。次に、Control-Cと入力して、コンテナを終了せずにコンテナから切り離します。

-tおよび-iを使用すると、Control-Cはコンテナーを終了します。 -i with -tを使用する場合、Control-P Control-Qを使用して終了せずに切り離す必要があります。

テスト1:

$ ID=$(Sudo docker run -t -d ubuntu /usr/bin/top -b)
$ Sudo docker attach $ID
Control-P Control-Q
$ Sudo docker ps

コンテナはまだリストされています。

テスト2:

$ ID=$(Sudo docker run -t -i -d ubuntu /usr/bin/top -b)
$ Sudo docker attach $ID
Control-C
$ Sudo docker ps

コンテナがそこにありません(終了しました)。 2番目の例でControl-Cの代わりにControl-PControl-Qと入力した場合、コンテナは引き続き実行されます。

コンテナープロセスをブロックし、ctrl-cをキャッチできるdocker-entrypoint.sh bashスクリプトでプログラムをラップします。このbashの例が役立つ場合があります。 https://rimuhosting.com/knowledgebase/linux/misc/trapping-ctrl-c-in-bash

#!/bin/bash

# trap ctrl-c and call ctrl_c()
trap ctrl_c INT

function ctrl_c() {
        echo "** Trapped CTRL-C"
}

for i in `seq 1 5`; do
    sleep 1
    echo -n "."
done
19
NID

使用する Ctrl+\ の代わりに Ctrl+C
シャットダウンを丁寧に要求するのではなく、プロセスを強制終了します。(続きを読む こちら 。)

4
asedsami

Dockerコンテナでmdbook(Rust実行可能ファイル)を実行しようとしたときに、同様の問題が発生しました。mdbookは単純なWebサーバーを起動し、 Ctrl+C うまくいきませんでした。

$ docker -ti --rm -p 4321:4321 my-docker-image mdbook serve --hostname 0.0.0.0 --port 4321
2019-08-16 14:00:11 [INFO] (mdbook::book): Book building has started
2019-08-16 14:00:11 [INFO] (mdbook::book): Running the html backend
2019-08-16 14:00:11 [INFO] (mdbook::cmd::serve): Serving on: http://0.0.0.0:4321
2019-08-16 14:00:11 [INFO] (ws): Listening for new connections on 0.0.0.0:3001.
2019-08-16 14:00:11 [INFO] (mdbook::cmd::watch): Listening for changes...
^C^C

@NIDの答えに触発されて、私はmdbook実行可能ファイルをユニバーサルbashスクリプトdocker-entrypoint.shでカプセル化しました。これは(INTシグナルを明示的にキャッチする必要なく)行いました。

$ docker -ti --rm -p 4321:4321 my-docker-image docker-entrypoint.sh mdbook serve --hostname 0.0.0.0 --port 4321
2019-08-16 14:00:11 [INFO] (mdbook::book): Book building has started
2019-08-16 14:00:11 [INFO] (mdbook::book): Running the html backend
2019-08-16 14:00:11 [INFO] (mdbook::cmd::serve): Serving on: http://0.0.0.0:4321
2019-08-16 14:00:11 [INFO] (ws): Listening for new connections on 0.0.0.0:3001.
2019-08-16 14:00:11 [INFO] (mdbook::cmd::watch): Listening for changes...
^C $

docker-entrypoint.shの内容は非常に単純です:

#!/bin/bash

$@
2
eNca

最善の方法は、コンテナIDを停止することです。すべてのアクティブなコンテナIDを次のように表示できます。

$ docker ps

then type

$ docker stop 07a5ac282a81

(停止するコンテナIDで07a5ac282a82を置き換えます)

0
MD Nelles