Как исправить ctrl + c внутри контейнера докера

Если я подключаюсь к контейнеру докера

$> docker exec -it my_container zsh

и внутри него я хочу убить что-то, с чего я начал с ctrl+c. Я заметил, что он навсегда завершается. Я искал googled, и кажется, что ctrl+c работает немного иначе, чем вы ожидали. Мой вопрос, как я могу исправить ctrl+c внутри контейнера?

Ответ 1

Проблема в том, что Ctrl-C отправляет сигнал процессу верхнего уровня внутри контейнера, но этот процесс не обязательно реагирует так, как вы ожидаете. Процесс верхнего уровня имеет ID 1 внутри контейнера, что означает, что он не получает обработчики сигналов по умолчанию, которые обычно имеют процессы. Если процесс верхнего уровня является оболочкой, то он может получать сигнал через собственный обработчик, но не передает его команде, которая выполняется внутри оболочки. Подробности объясняются здесь here. В обоих случаях докер-контейнер действует так, как будто он просто игнорирует Ctrl-C.

Начиная с docker 0.6.5, вы можете добавить -t к команде запуска докера, которая присоединит 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

контейнера там нет (он был прерван). Если вы наберете Control-P Control-Q вместо Control-C во 2-м примере, контейнер все равно будет работать.

Оберните программу сценарием bash docker-entrypoint.sh, который блокирует контейнерный процесс и умеет ловить ctrl-c. Это пример 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

Ответ 2

Используйте Ctrl + \ вместо Ctrl + C
он убивает этот процесс, вместо того, чтобы вежливо попросить его закрыть. (читайте здесь.)

Ответ 3

У меня была похожая проблема, когда я пытался запустить mdbook (исполняемый файл Rust) в контейнере Docker. mdbook запускает простой веб-сервер, и я хочу остановить его через 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

[email protected]

Ответ 4

Лучше всего остановить КОНТЕЙНЕР ID Вы можете увидеть все идентификаторы активного контейнера с помощью:

$ docker ps

then type

$ docker stop 07a5ac282a81

(замените 07a5ac282a82 идентификатором контейнера, который хотите остановить)