Python многопроцессорный сбой док-контейнера - PullRequest
0 голосов
/ 12 февраля 2019

Существует простой многопроцессорный код Python, который работает как чудо, когда я запускаю его в консоли:

# mp.py
import multiprocessing as mp


def do_smth():
    print('something')


if __name__ == '__main__':
    ctx = mp.get_context("spawn")
    p = ctx.Process(target=do_smth, args=tuple())
    p.start()
    p.join()

Результат:

> $ python3 mp.py
something

Затем я создал простой Dockerконтейнер с Dockerfile:

FROM python:3.6

ADD . /app
WORKDIR /app

и docker-compose.yml:

version: '3.6'

services:
  bug:
    build:
      context: .
    environment:
      - PYTHONUNBUFFERED=1
    command: su -c "python3.6 forever.py"

Где forever.py:

from time import sleep

if __name__ == '__main__':
    i = 0
    while True:
        sleep(1.0)
        i += 1
        print(f'hello {i:3}')

Теперь я запускаю forever.pyс докером составь:

> $ docker-compose build && docker-compose up 
...
some output
...
Attaching to mpbug_bug_1
bug_1  | hello   1
bug_1  | hello   2
bug_1  | hello   3
bug_1  | hello   4

До этого момента все хорошо и понятно.Но когда я пытаюсь запустить mp.py в контейнере Docker, он вылетает без какого-либо сообщения:

> $ docker exec -it mpbug_bug_1 /bin/bash
root@09779ec47f9d:/app# python mp.py 
something
root@09779ec47f9d:/app# % 

Суть с кодом можно найти здесь: https://gist.github.com/ilalex/83649bf21ef50cb74a2df5db01686f18

Можете ли выобъясните, почему разбился контейнер Docker и как это сделать без сбоев?

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 15 февраля 2019

для быстрого исправления, не используйте spawn метод запуска и / или не используйте su -c ..., оба являются ненужными IMO.измените на:

p = mp.Process(target=do_smth, args=tuple())

или вы можете запустить контейнер с опцией --init.

с spawn методом запуска, Python также запустит семафорный трекер чтобы предотвратить утечку семафора, вы можете увидеть этот процесс, сделав паузу mp.py в середине, он выглядит следующим образом:

472   463 /usr/local/bin/python3 -c from multiprocessing.semaphore_tracker import main;main(3)

этот процесс запущен mp.py, но завершен после mp.py, таким образом, он будетне должен быть получен mp.py, но должен быть получен init по проекту.

проблема в том, что в этом контейнере (пространстве имен) нет init вместо init, PID1 - su -c, поэтому процесс отслеживания мертвого семафора принимается su.

. Похоже, что su считает, что мертвый дочерний процесс является ошибочным процессом команды (forever.py), без проверкиотношения, поэтому su выходят вслепую, так как при выходе из PID 1 ядро ​​убивает все другие процессы в контейнере, включая forever.py.

, такое поведение можно наблюдать при strace:

docker run --security-opt seccomp:unconfined --rm -it ex_bug strace -e trace=process -f su -c 'python3 forever.py'

выведет сообщение об ошибке, например:

strace: Exit of unknown pid 14 ignored

ref: Проблема с Docker и PID 1 зомби (phusion.nl)

0 голосов
/ 15 февраля 2019

mp.py не похоже на эквивалент forever.py.mp.py запустит новый рабочий процесс, который просто напечатает something, а затем выйдет => join(), в главном процессе немедленно завершится, когда этот рабочий процесс завершится.

Лучший эквивалентforever.py: рабочий процесс печатает приветственное сообщение в бесконечном цикле, и главный процесс будет ожидать выхода этого рабочего процесса в join() - forever-mp.py:

import multiprocessing as mp
from time import sleep

def do_smth():
    i = 0
    while True:
        sleep(1.0)
        i += 1
        print(f'hello {i:3}')

if __name__ == '__main__':
    ctx = mp.get_context("spawn")
    p = ctx.Process(target=do_smth, args=tuple())
    p.start()
    p.join()

Обновлено docker-compose.yml:

version: '3.6'

services:
  bug:
    build:
      context: .
    environment:
      - PYTHONUNBUFFERED=1
    command: su -c "python3.6 forever-mp.py"

Тест:

$ docker-compose build && docker-compose up 
...
some output
...
Attaching to multiprcs_bug_1_72681117a752
bug_1_72681117a752 | hello   1
bug_1_72681117a752 | hello   2
bug_1_72681117a752 | hello   3
bug_1_72681117a752 | hello   4

Проверка процессов в контейнере:

$ docker top multiprcs_bug_1_72681117a752
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                38235               38217               0                   21:36               ?                   00:00:00            su -c python3.6 forever-mp.py
root                38297               38235               0                   21:36               ?                   00:00:00            python3.6 forever-mp.py
root                38300               38297               0                   21:36               ?                   00:00:00            /usr/local/bin/python3.6 -c from multiprocessing.semaphore_tracker import main;main(3)
root                38301               38297               0                   21:36               ?                   00:00:00            /usr/local/bin/python3.6 -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=4, pipe_handle=6) --multiprocessing-fork
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...