Solución:
El problema es que Ctrl-C envía una señal al proceso de nivel superior dentro del contenedor, pero ese proceso no necesariamente reacciona como cabría esperar. El proceso de nivel superior tiene ID 1 dentro del contenedor, lo que significa que no obtiene los manejadores de señales predeterminados que suelen tener los procesos. Si el proceso de nivel superior es un shell, entonces puede recibir la señal a través de su propio controlador, pero no la reenvía al comando que se ejecuta dentro del shell. Los detalles se explican aquí. En ambos casos, el contenedor de la ventana acoplable actúa como si simplemente ignorara Ctrl-C.
Empezando con docker 0.6.5
, puedes añadir -t
al comando docker run, que adjuntará un pseudo-TTY
. Entonces puedes escribir Control-C
despegar del recipiente sin cerrarlo.
Si utiliza -t
y -i
luego Control-C terminará el contenedor. Cuando usas -i with -t
entonces tienes que usar Control-P Control-Q
para despegar sin terminar.
Prueba 1:
$ ID=$(sudo docker run -t -d ubuntu /usr/bin/top -b)
$ sudo docker attach $ID
Control-P Control-Q
$ sudo docker ps
El contenedor todavía aparece en la lista.
Prueba 2:
$ ID=$(sudo docker run -t -i -d ubuntu /usr/bin/top -b)
$ sudo docker attach $ID
Control-C
$ sudo docker ps
el contenedor no está allí (se ha terminado). Si escribe Control-P
Control-Q
en lugar de Control-C en el segundo ejemplo, el contenedor aún se estaría ejecutando.
Envuelva el programa con un script bash docker-entrypoint.sh que bloquea el proceso del contenedor y es capaz de capturar ctrl-c. Este ejemplo de bash podría ayudar: 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
Tuve un problema similar cuando intentaba ejecutar mdbook
(el ejecutable de Rust) en el contenedor de la ventana acoplable. los mdbook
inicia un servidor web simple y quiero detenerlo a través de control+C que no funcionó.
$ 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
Inspírate con la respuesta de @ NID Encapsulé el ejecutable mdbook mediante el script universal bash docker-entrypoint.sh
que hizo el truco (sin la necesidad de capturar explícitamente la señal 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 $
El contenido de la docker-entrypoint.sh
es muy simple:
#!/bin/bash
[email protected]
Usar control+ en lugar de control+C
mata el proceso en lugar de pedirle cortésmente que se cierre (lea más aquí).