Ответ 1
Предполагая, что вы запустите службу Java, определив следующее в Dockerfile
:
CMD java -jar ...
Когда вы теперь вводите контейнер и перечисляете процессы, например. docker exec -it <containerName> ps AHf
(я не пробовал это с java
, но с изображением ubuntu
), вы видите, что ваш процесс Java не является корневым процессом (а не процессом с PID 1), а дочерним процессом /bin/sh
процесс:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 18:27 ? 00:00:00 /bin/sh -c java -jar ...
root 8 1 0 18:27 ? 00:00:00 java -jar ...
Итак, в основном у вас есть оболочка Linux, которая является основным процессом с PID 1, который имеет дочерний процесс (Java) с PID 8.
Чтобы обеспечить правильную обработку сигналов, вы должны избегать этого родительского процесса оболочки. Это можно сделать, используя встроенную команду оболочки exec
. Это приведет к процессу дочернего процесса над родительским процессом. Поэтому в конце прежний родительский процесс больше не существует. И дочерний процесс становится процессом с PID 1. Попробуйте следующее в Dockerfile
:
CMD exec java -jar ...
В листинге процесса должно отображаться следующее:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 18:30 ? 00:00:00 java -jar ...
Теперь у вас есть только один процесс с PID 1. Как правило, хорошей практикой является наличие в контейнерах докеров только одного процесса - с PID 1 (или если вам действительно нужно больше процессов, то вы должны использовать, например, supervisord
как ПИД-1, который сам позаботится о обработке сигналов для своих дочерних процессов).
С этой настройкой SIGTERM
будет обрабатываться непосредственно процессом Java. Нет никакого процесса оболочки больше, между которыми может нарушить обработку сигнала.
ИЗМЕНИТЬ
Тот же эффект exec
может быть достигнут с помощью другого синтаксиса CMD
, который делает это неявно (спасибо Andy за его комментарий):
CMD ["java", "-jar", "..."]