Не зомби контейнеры , а зомби процессы . Напишите это zombie.py
:
#!/usr/bin/env python3
import subprocess
import time
p = subprocess.Popen(['/bin/sleep', '1'])
time.sleep(2)
subprocess.run(['/bin/ps', '-ewl'])
Напишите это Dockerfile
:
FROM python:3
COPY zombie.py /
CMD ["/zombie.py"]
Постройте и запустите:
chmod +x zombie.py
docker build -t zombie .
docker run --rm zombie
Что здесь происходит, команда /bin/sleep
запускается на исполнение. Родительский процесс должен использовать вызов wait
для очистки после него, но этого не происходит, когда он запускает ps
, вы увидите зомби-процесс "Z".
Но подождите, это еще не все! Скажем, ваш процесс тщательно очищается после себя. В этом конкретном примере, например, subprocess.run()
включает требуемый вызов wait
, и вы можете изменить вызов Popen
на run
. Если этот подпроцесс запускает другой подпроцесс, и он выходит (или падает), не ожидая его, процесс init с pid 1 становится новым родительским процессом зомби. (Он работал таким образом в течение 40 лет.) Однако в контейнере Docker основной контейнерный процесс выполняется с pid 1, и если он не ожидает «дополнительных» дочерних процессов, вы могли бы получить устаревшие процессы-зомби на весь срок службы контейнер.
Это иногда приводит к предположению, что контейнер Docker всегда должен запускать какой-то «реальный» процесс инициализации, возможно, такой минимальный, как tini , чтобы что-то поднималось после процессов зомби и вашего фактического контейнера. работа не должна волноваться об этом.