Python多处理崩溃docker容器

Python多处理崩溃docker容器,python,python-3.x,docker,docker-compose,Python,Python 3.x,Docker,Docker Compose,当我在控制台中运行它时,有一个简单的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()

当我在控制台中运行它时,有一个简单的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
然后,我用Dockerfile创建了一个简单的Docker容器:

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}')
现在我用docker compose运行
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
到目前为止,一切都是好的,可以理解的。但是,当我试图在docker容器中运行
mp.py
时,它崩溃了,没有任何消息:

> $ docker exec -it mpbug_bug_1 /bin/bash
root@09779ec47f9d:/app# python mp.py 
something
root@09779ec47f9d:/app# % 
可在此处找到代码的要点:

您能解释一下为什么docker容器会崩溃,以及如何在不崩溃的情况下做到这一点吗


提前谢谢你

mp.py
看起来不像是
forever.py
的等价物
mp.py
将运行新的辅助进程,该进程将只打印
something
,然后它将退出=>
join()
,当此辅助进程完成时,主进程将立即退出

更好地等效于
forever.py
:工作进程在无限循环中打印hello消息,主进程将在
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 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

对于快速修复,请不要使用
spawn
start方法和/或不要使用
su-c…
,这两种方法都是不必要的。请更改为:

p = mp.Process(target=do_smth, args=tuple())
或者您可以使用
--init
选项启动容器

使用<代码>生成> <代码>启动方法,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
,PID 1是
su-c
,因此
su
采用死信号量跟踪器进程

<> > <代码> SU/COD>认为死子进程是命令进程(<代码>永久性.Py <代码>)错误,不检查关系,所以<代码> SU/COD>盲目退出,作为PID 1退出,内核杀死容器中的所有其他进程,包括<代码>永远。Py < /代码> ./P> 这种行为可以通过
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:

看起来并没有崩溃。看起来它已经退出了。容器在执行完脚本后会退出。@Neil但是
forever.py
不能在没有崩溃的情况下退出。或者可以?如果您正在
exec
-ing到
forever.py
正在运行的容器中,那么当
exec
-ing到容器中时,您正在停止该进程并启动
bash
@C.Nivs,日志显示
forever.py
仍在工作并打印hello消息,直到我运行
mp.py
Hm OK。还有一个问题,“docker ps”的输出是什么?a)在您的exec进入并运行mp.py之前,b)在容器退出之后。当然,它们彼此并不等价。问题是在运行python多处理时容器意外停止。请参阅复制步骤的要点。您的
mp.py
不会永远运行-它将打印“某物”,并以退出代码0结束。那么为什么您希望容器将永远运行呢?我希望当我运行
mp.py
时,
forever.py
不会停止运行。它们之间没有逻辑联系。为什么容器永远停止
.py
?这是我的问题。当你同时运行
mp.py
时,你能重现
forever.py的停止吗?不,我不能重现。
strace: Exit of unknown pid 14 ignored