Ответ
В Docker-контейнере процесс с идентификатором PID 1 — это самый первый (корневой) процесс, который запускается при старте контейнера. Он определяется инструкциями ENTRYPOINT или CMD в Dockerfile.
Ключевая роль PID 1
Процесс с PID 1 имеет особое значение в Linux-системах:
- Родительский процесс: Он становится родителем для всех дочерних процессов, запущенных в контейнере.
- Обработка сигналов: Он отвечает за получение и обработку системных сигналов, таких как
SIGTERM, который отправляется командойdocker stop. Корректная обработка сигнала позволяет приложению завершиться штатно. - Завершение контейнера: Когда процесс с
PID 1завершается, контейнер останавливается.
Проблема и Best Practices
Частая ошибка — запуск приложения через shell (shell form), что делает сам shell процессом с PID 1, а не ваше приложение. Shell не всегда корректно передает сигналы дочернему процессу, что может привести к "зомби-процессам" и некорректному завершению работы.
1. Используйте exec форму
Это лучший способ, чтобы ваше приложение стало PID 1.
# НЕПРАВИЛЬНО (shell form): /bin/sh становится PID 1
CMD service myapp start
# ПРАВИЛЬНО (exec form): 'myapp' становится PID 1
CMD ["myapp", "--foreground"]
2. Используйте легковесный init-процесс
Для более сложных случаев, когда приложение само не умеет корректно управлять дочерними процессами, рекомендуется использовать init-систему, например tini. Она становится PID 1, корректно обрабатывает сигналы и собирает "зомби-процессы".
Docker имеет встроенную поддержку tini через флаг --init:
docker run --init my-image
Или можно встроить tini прямо в Dockerfile:
FROM alpine:3.15
# Устанавливаем tini
RUN apk add --no-cache tini
# Копируем приложение
COPY ./myapp /usr/local/bin/myapp
# Указываем tini как точку входа. Он запустит наше приложение.
ENTRYPOINT ["/sbin/tini", "--"]
# Указываем команду для запуска
CMD ["myapp"]
Правильное управление процессом PID 1 — ключ к созданию стабильных и предсказуемых Docker-контейнеров.