为什么 Python 进程的父 pid 在具有 docker-compose 的 Docker 容器中有时为 0?
Why is the parent pid of a Python process sometimes 0 in Docker containers with docker-compose?
当运行直接从docker-compose run
中调用pythonshell时,父PID显示为0,感觉很不对。我在下面整理了一个非常简单、可重现的案例:
# Dockerfile
FROM python:3.7-buster
COPY . /code/
WORKDIR /code
# docker-compose.yml
version: '3'
services:
thing:
build: .
volumes:
- .:/code
当我从这个里面运行一个pythonshell时,它的ppid是0;同样以这种方式 python 代码 运行ning(如果 运行ning 使用 pytest
进行测试):
$ docker-compose run thing python
>>> import os
>>> os.getpid()
1
>>> os.getppid()
0
当我从 bash shell 中 运行 python shell 时,我看到了一个更理智的值...
$ docker-compose run thing bash
root@<id> # python
>>> import os
>>> os.getpid()
6
>>> os.getppid()
1
当我直接在主机上 运行 python shell 时,我也看到了更合理的 PID 值...
$ python
>>> import os
>>> os.getpid()
25552
>>> os.getppid()
1133
我确定这是关于 docker
如何处理 运行ning 容器中的进程的一些奇怪行为,但在我看来 PID 不应该为 0。是这种预期的行为,如果是这样,是否有 Python 代码 运行 以这种方式依赖于父 PID 的解决方法?
这是预期的行为。容器内的主进程是 PID 1 并且没有父进程。这是容器隔离的一部分——进程似乎是整个系统中唯一的进程。
When I run a python shell from within a bash shell, I see a more sane value...
在那种情况下,根进程是 bash 并且它有一个 python 子进程。
这既不奇怪也不错误 -- 父 PID 为 0,因为 Docker 容器中没有父进程。
当 运行 类似 docker-compose run thing python
时,有史以来第一个进程 在该容器中启动(或更准确地说,在 PID namespace 中)将是 python
进程本身。因此,它将获得 PID 1,并且没有父进程。
注意:完全相同的事情也会发生在常规(非容器化)Linux 系统上; PID 为 1 的进程也是第一个进程(在这种情况下由内核在启动后启动)并且通常是一个像 systemd. The init system then handles the user-space part of booting your Linux system (like setting up your network, mounting file systems and starting system services) -- in a Docker container, there's typically no need for any of this, which also eliminates the need for any init system. However, there are init systems like dumb-init 这样的初始化系统,它是专门为容器中的 运行 创建的。
当容器中有 运行 一个 shell,并从 shell 开始 Python 时,shell 将是 PID 1。在这种情况下, 运行 os.getppid()
从你的 Python 脚本应该 return 1
.
Is this expected behavior, and if so is there a workaround for Python code running this way that relies on a parent PID?
如前所述,您可以从shell(或任何其他进程)启动您的Python环境,然后获得PID 1 而不是 python。您还可以使用专为 dumb-init
.
等容器设计的初始化系统
当运行直接从docker-compose run
中调用pythonshell时,父PID显示为0,感觉很不对。我在下面整理了一个非常简单、可重现的案例:
# Dockerfile
FROM python:3.7-buster
COPY . /code/
WORKDIR /code
# docker-compose.yml
version: '3'
services:
thing:
build: .
volumes:
- .:/code
当我从这个里面运行一个pythonshell时,它的ppid是0;同样以这种方式 python 代码 运行ning(如果 运行ning 使用 pytest
进行测试):
$ docker-compose run thing python
>>> import os
>>> os.getpid()
1
>>> os.getppid()
0
当我从 bash shell 中 运行 python shell 时,我看到了一个更理智的值...
$ docker-compose run thing bash
root@<id> # python
>>> import os
>>> os.getpid()
6
>>> os.getppid()
1
当我直接在主机上 运行 python shell 时,我也看到了更合理的 PID 值...
$ python
>>> import os
>>> os.getpid()
25552
>>> os.getppid()
1133
我确定这是关于 docker
如何处理 运行ning 容器中的进程的一些奇怪行为,但在我看来 PID 不应该为 0。是这种预期的行为,如果是这样,是否有 Python 代码 运行 以这种方式依赖于父 PID 的解决方法?
这是预期的行为。容器内的主进程是 PID 1 并且没有父进程。这是容器隔离的一部分——进程似乎是整个系统中唯一的进程。
When I run a python shell from within a bash shell, I see a more sane value...
在那种情况下,根进程是 bash 并且它有一个 python 子进程。
这既不奇怪也不错误 -- 父 PID 为 0,因为 Docker 容器中没有父进程。
当 运行 类似 docker-compose run thing python
时,有史以来第一个进程 在该容器中启动(或更准确地说,在 PID namespace 中)将是 python
进程本身。因此,它将获得 PID 1,并且没有父进程。
注意:完全相同的事情也会发生在常规(非容器化)Linux 系统上; PID 为 1 的进程也是第一个进程(在这种情况下由内核在启动后启动)并且通常是一个像 systemd. The init system then handles the user-space part of booting your Linux system (like setting up your network, mounting file systems and starting system services) -- in a Docker container, there's typically no need for any of this, which also eliminates the need for any init system. However, there are init systems like dumb-init 这样的初始化系统,它是专门为容器中的 运行 创建的。
当容器中有 运行 一个 shell,并从 shell 开始 Python 时,shell 将是 PID 1。在这种情况下, 运行 os.getppid()
从你的 Python 脚本应该 return 1
.
Is this expected behavior, and if so is there a workaround for Python code running this way that relies on a parent PID?
如前所述,您可以从shell(或任何其他进程)启动您的Python环境,然后获得PID 1 而不是 python。您还可以使用专为 dumb-init
.