python子进程无法使用docker中的popen从stdout读取

时间:2018-02-19 17:55:33

标签: python bash docker

我有一个docker文件,它以bash脚本和python脚本从主机复制到docker文件系统中的/ root:

FROM centos
RUN yum install -y nc
COPY filter_text_telemetry.sh /root/
COPY read_data.py /root/
EXPOSE 8071
RUN cd /root

我的python脚本应该作为子进程启动bash脚本,然后按如下方式从中收集数据:

p = Popen(["./filter_text_telemetry.sh"], stdout=PIPE, stderr=PIPE)
p.stdout.readline()

在我的主机上,python代码工作正常,能够打印出它收集的数据。在我的docker容器中,它什么都没打印,我不知道为什么。 docker容器默认以root身份运行所有内容。这会影响stdout管道吗?如果不是,那么我该怎么做才能解决我的问题呢?

1 个答案:

答案 0 :(得分:0)

您错过了一条关键信息:您给docker run的命令是什么?

那就是说,看看你的Dockerfile,你似乎误解了RUN指令是如何工作的,我怀疑这是什么让你沮丧。

正如the documentation所说,

  

RUN指令将在当前图像之上的新图层中执行任何命令并提交结果。生成的已提交映像将用于Dockerfile中的下一步。

这意味着由RUN命令对文件系统所做的任何更改都将保留在正在构建的文件系统映像中。但是,cd对文件系统中的任何内容都不做任何更改;它只是更改当前进程的当前工作目录(CWD)。因此,虽然由RUN启动的进程将具有不同的CWD,但这不会被保存,并且新进程(例如从该图像开始创建新容器的进程)将以默认CWD开始。

所以这很有可能发生了什么:

  1. 该图片在filter_text_telemetry.sh目录中有read_data.py/root
  2. 您可以使用docker run MYIMAGE /usr/bin/python /root/read_data.py
  3. 之类的内容从该图片启动容器
  4. python解释器以/的默认CWD启动,读取/root/read_data.py并开始执行该代码。
  5. Python程序尝试运行./filter_text_telemetry.sh,因为.(CWD)为/,尝试将该文件设为/filter_text_telemetry.sh
  6. 它不存在(因为它在/root/filter_text_telemtry.sh中),因此Popen失败。
  7. 有各种“正确”的方法可以解决这个问题(例如让Python程序找出它所在的目录并在该目录中查找filter_text_telemetry.sh,无论CWD如何),但这是一种常见且容易的方法解决方案只是将脚本放在/而不是/root中,以便启动时的CWD是包含脚本的目录。 (并删除RUN cd /root指令,因为它是一个无操作,只能误导人。