在 docker 容器中调用 python 子进程时出错

Posted

技术标签:

【中文标题】在 docker 容器中调用 python 子进程时出错【英文标题】:Error while calling python subprocess in docker container 【发布时间】:2017-06-20 09:06:54 【问题描述】:

我正在尝试在 python 2.7 中调用子进程。该子进程执行一个 JAVA jar 文件并读取输出。我在 docker 容器中使用 django。

我正在调用一个函数:

def call_exec(lang)
  curdir = curdir = 'ht/exec_folder'
  tmp_files_dir = 'ht/temp_files'
  script_args = ["java","-jar",'/'+curdir + "/executable.jar",
        "-l",lang,"-s",'/'+tmp_files_dir]
  output = subprocess.check_output(script_args)
  return output

这里,ht 是我的 Django 应用程序中的一个文件夹。我正在尝试使用 executable.jar 并读取输出。其他参数用于运行可执行文件。 以下是产生的错误:

django_1    |     similarity = call_exec('english')
django_1    |   File "/app/langswipe/submissions/check_view.py", line 80, in call_exec
django_1    |     output = subprocess.check_output(script_args)
django_1    |   File "/usr/local/lib/python2.7/subprocess.py", line 567, in check_output
django_1    |     process = Popen(stdout=PIPE, *popenargs, **kwargs)
django_1    |   File "/usr/local/lib/python2.7/subprocess.py", line 711, in __init__
django_1    |     errread, errwrite)
django_1    |   File "/usr/local/lib/python2.7/subprocess.py", line 1343, in _execute_child
django_1    |     raise child_exception
django_1    | OSError: [Errno 2] No such file or directory

tmp_files_dir 中有 2 个文件。当我在本地机器上运行可执行文件时,相同的参数给了我一个结果,但这个没有。关于发生了什么的任何线索?

编辑

jar 已就位,但子进程调用失败。在本地,它运行良好。借助经验丰富的专业人员的 cmets,我查看了 docker 文件,我意识到容器内缺少 Java。我尝试在此容器上安装 Java,但构建失败。

我阅读了以下资源以在我目前的容器上安装 JAVA:

Best way to install java 8 using docker?

https://www.ivankrizsan.se/2015/08/08/creating-a-docker-image-with-ubuntu-and-java/

https://raw.githubusercontent.com/docker-library/openjdk/e6e9cf8b21516ba764189916d35be57486203c95/8-jdk/Dockerfile

我修改后的 docker 文件是:

FROM python:2.7
ENV PYTHONUNBUFFERED 1

# to accomodate slate
RUN easy_install distribute

# Requirements have to be pulled and installed here, otherwise caching won't work
COPY ./requirements /requirements

RUN pip install -r /requirements/production.txt && \
    mkdir -p /usr/share/nltk_data && \
    python -m nltk.downloader -d /usr/share/nltk_data punkt stopwords wordnet averaged_perceptron_tagger && \
    apt-get update && apt-get install poppler-utils -qy



RUN groupadd -r django && useradd -r -g django django
COPY . /app
RUN chown -R django /app

COPY ./compose/django/gunicorn.sh /gunicorn.sh
COPY ./compose/django/entrypoint.sh /entrypoint.sh
RUN sed -i 's/\r//' /entrypoint.sh
RUN sed -i 's/\r//' /gunicorn.sh
RUN chmod +x /entrypoint.sh && chown django /entrypoint.sh
RUN chmod +x /gunicorn.sh && chown django /gunicorn.sh


RUN apt-get update && apt-get install -y --no-install-recommends \
        bzip2 \
        unzip \
        xz-utils \
    && rm -rf /var/lib/apt/lists/*

RUN echo 'deb http://deb.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/jessie-backports.list

# Default to UTF-8 file.encoding
ENV LANG C.UTF-8

# add a simple script that can auto-detect the appropriate JAVA_HOME value
# based on whether the JDK or only the JRE is installed
RUN  \
        echo '#!/bin/sh'; \
        echo 'set -e'; \
        echo; \
        echo 'dirname "$(dirname "$(readlink -f "$(which javac || which java)")")"'; \
     > /usr/local/bin/docker-java-home \
    && chmod +x /usr/local/bin/docker-java-home

ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64

ENV JAVA_VERSION 8u111
ENV JAVA_DEBIAN_VERSION 8u111-b14-2~bpo8+1

# see https://bugs.debian.org/775775
# and https://github.com/docker-library/java/issues/19#issuecomment-70546872
ENV CA_CERTIFICATES_JAVA_VERSION 20140324

RUN set -x \
    && apt-get update \
    && apt-get install -y \
        openjdk-8-jdk="$JAVA_DEBIAN_VERSION" \
        ca-certificates-java="$CA_CERTIFICATES_JAVA_VERSION" \
    && rm -rf /var/lib/apt/lists/* \
    && [ "$JAVA_HOME" = "$(docker-java-home)" ]

# see CA_CERTIFICATES_JAVA_VERSION notes above
RUN /var/lib/dpkg/info/ca-certificates-java.postinst configure




WORKDIR /app

ENTRYPOINT ["/entrypoint.sh"]

构建失败。我对 docker 的了解非常有限,因为我是新手,如果有人帮助我解决问题,我将不胜感激。

【问题讨论】:

请分享你的 Dockerfile 让我们手动检查 jar 文件是否存在。运行docker exec -it <container_name> bash 并尝试执行类似 python 脚本的命令 【参考方案1】:

好的,我想通了。我使用的是 python 2.7 的基本映像,我将其更改为 ubuntu 并安装了我想使用的 Java、Python 和 Ruby。

【讨论】:

以上是关于在 docker 容器中调用 python 子进程时出错的主要内容,如果未能解决你的问题,请参考以下文章

理解Docker容器的进程管理

一个docker容器,在宿主机上有几个进程

运行docker容器时出错:启动容器进程导致“exec:”python “:$ PATH中找不到可执行文件”:未知

在python中控制用于调用外部命令的子进程数

【容器】关于docker容器中的init进程

在 Python 中分析子进程 Popen 调用