Почему я не могу CTRL-C бесконечно спать в докере, когда он работает как PID 1

Случай: у нас есть док-контейнер, который запускает bash-скрипт, который необходимо «заблокировать» навсегда (поскольку он предоставляет том для другого контейнера, но есть и другие причины, по которым мы иногда этого хотим).

Я думал, что это может сработать тогда:

exec sleep infinity;

ps aux затем дает «сон» как PID 1. Отлично, подумал я, тогда он будет получать сигналы, которые мы посылаем ему из-за пределов контейнера. Например:

docker kill -s INT container_name

Но это не работает, контейнер продолжает работать (также для SIGTERM). Обычное убийство работает, но я не понимаю, в чем разница (что меня сильно раздражает):

docker kill container_name

Почему я не могу убить «сон» с помощью SIGINT/SIGTERM, когда он работает как PID 1 в моем контейнере? Я считаю, что могу убить другие вещи (например, сценарии bash) с помощью SIGINT/SIGTERM, когда они работают как PID 1 в контейнере.


person Otto    schedule 17.07.2017    source источник
comment
Какая команда запустила контейнер? Какая версия Докера? Какая ОС хоста? Можем ли мы увидеть Dockerfile?   -  person Andy Shinn    schedule 17.07.2017


Ответы (1)


Будет ли от этого какая-то польза? https://www.fpcomplete.com/blog/2016/10/docker-demons-pid1-orphans-zombies-signals

В основном проблема заключается в процессе номер 1. Ядра Linux/unix неохотно сигнализируют об этом процессе обычным способом, поскольку он должен быть инициализирован. Если процесс инициализации умирает, система немедленно выдает панику и перезагружается. Если ваш процесс 1 не имеет обработчика сигнала, сигнал просто сбрасывается. Sleep не имеет обработчиков каких-либо сигналов, но вы можете создать их для сценария bash.

По сути, вам нужно использовать форму exec в вашем файле докеров и разделить бесконечность сна на цикл, поскольку ловушки bash не срабатывают, пока оболочка выполняет команду. Это отправляет сигнал запущенному процессу 1 и перехватывает его:

Докерфайл:

FROM ubuntu
ADD foo.sh /tmp
RUN ["/tmp/foo.sh"]

foo.ш:

#!/bin/bash

trap "echo signal;exit 0" SIGINT 

while :
do
    sleep 1
done

Это отреагирует на убийство докера --signal=SIGINT.

person Hannu    schedule 17.07.2017
comment
Спасибо, это указало мне правильное направление. После некоторого чтения и поиска в Google я также нашел это, что кажется хорошим решением и, вероятно, хорошей идеей при запуске контейнеров Docker: docs.docker.com/engine/reference/run/#specify-an-init-process - person Otto; 18.07.2017