【问题标题】:Python 3 virtualenv and DockerPython 3 virtualenv 和 Docker
【发布时间】:2018-06-17 14:36:35
【问题描述】:

我正在尝试使用 python 3 和 virtualenv 构建一个 docker 映像。 我知道我不需要在 docker 映像中使用 wirtualenv,因为我将只使用 python 3,但无论如何我都看到了使用 virtualenv 的一些干净的隔离优势。

最佳做法是什么?我应该避免在 docker 上使用 virtualenv 吗? 如果是这种情况,我该如何设置 python3 和 pip3 用作 python 和 pip(没有 3)?

这是我的 Dockerfile:

FROM openjdk:8-alpine

RUN apk update && apk add bash gcc musl-dev
RUN apk add python3 python3-dev
RUN apk add py3-pip
RUN apk add libxslt-dev libxml2-dev

ENV PROJECT_HOME /opt/app

RUN mkdir -p /opt/app
RUN mkdir -p /opt/app/modules

ENV LD_LIBRARY_PATH /usr/lib/python3.6/site-packages/jep
ENV LD_PRELOAD /usr/lib/libpython3.6m.so

RUN pip3 install jep
RUN pip3 install ads
RUN pip3 install gspread
RUN pip3 list

COPY target/my-server-1.0-SNAPSHOT.jar $PROJECT_HOME/my-server-1.0-SNAPSHOT.jar

WORKDIR $PROJECT_HOME

CMD ["java", "-Dspring.data.mongodb.uri=mongodb://my-mongo:27017/mydb","-jar","./my-server-1.0-SNAPSHOT.jar"]

谢谢

=== 更新 1 === 我正在尝试在 WORKDIR 中创建一个新的虚拟环境,安装一些库,然后执行一个 shell 脚本,即使我在构建映像时看到它创建了整个东西,但在运行容器时环境文件夹是空的。

这是来自我的 Dockerfile:

RUN virtualenv ./env && source ./env/bin/activate && pip install jep \
    googleads gspread oauth2client

ENTRYPOINT ["/bin/bash", "./startup.sh"]

startup.sh:

#!/bin/sh
source ./env/bin/activate
java -Dspring.data.mongodb.uri=mongodb://my-mongo:27017/mydb -jar ./my-server-1.0-SNAPSHOT.jar

它构建得很好,但是在 docker-compose up -d 这是输出:

./startup.sh: source: line 2: can't open './env/bin/activate'

env 文件夹存在,但它为空

有什么想法吗?

谢谢!

=== 更新 2 === 这是工作配置:

RUN virtualenv ./my-env && source ./my-env/bin/activate \
    && pip install gspread==0.6.2 jep oauth2client googleads pandas

CMD ["/bin/bash", "-c", "./startup.sh"]

这是startup.sh:

#!/bin/sh
source ./my-env/bin/activate
java -Dspring.data.mongodb.uri=mongodb://my-mongo:27017/mydb -jar ./my-server-1.0-SNAPSHOT.jar

【问题讨论】:

  • 编辑PATH 变量以包含python3 安装的位置,然后将python3pip3 分别符号链接到pythonpip

标签: python-3.x docker pip virtualenv


【解决方案1】:

我认为在 docker 中使用 virtualenv 并没有什么负面影响,它只会稍微减慢您的容器构建速度。

至于重命名pip3和python3,你可以这样创建一个硬链接:

ln /usr/bin/python3 /usr/bin/python
ln /usr/bin/pip3 /usr/bin/pip

假设 python3 可执行文件位于 /usr/bin/ 中。你可以通过运行which python3找到它的位置

P.S.:您的 dockerfile 包含大量 RUN 指令,这些指令正在创建不必要的中间容器。将它们组合起来以节省空间和时间:

RUN apk update && apk add bash gcc musl-dev \
    python3 python3-dev py3-pip \
    libxslt-dev libxml2-dev

RUN mkdir -p /opt/app/modules # you don't need the first one, -p will create it for you

RUN pip3 install jep ads gspread

如果您不打算经常更改它们,或者进一步组合它们:

RUN apk update
 && apk add bash gcc musl-dev    \
    python3 python3-dev py3-pip  \
    libxslt-dev libxml2-dev      \
 && mkdir -p /opt/app/modules    \
 && pip3 install jep ads gspread

【讨论】:

  • 首先感谢您的提示,好消息!现在,如果我确实想使用 virtualenv,在 Dockerfile 中激活它并从最后一个 CMD 访问它的正确方法是什么?最终,如果我通过 ssh 进入容器,我也需要激活它。我尝试了正常的方式,如果我打开终端,它没有被激活(从它的启动),就像它是一个不同的终端/tty。我应该使用 bash 脚本来激活它并运行 jar 吗?
  • 好吧,如果您激活环境并在一个 RUN 块内执行操作,那么一切都应该正常工作。使用 && 和 \
  • 我可以从 RUN 块内部激活环境,但是当容器启动时,我无法启动 java jar 应用程序,而是在最后的 CMD 中启动。我需要我的 java 应用程序在激活的 virtualenv 下运行,有什么建议吗?
  • 创建 entrypoint.sh 脚本来激活虚拟环境并启动 java 应用程序,将其复制到容器中并将其放入 CMD。不要忘记在你的本地机器上chmod +x它。
  • @magnoz 我怀疑您在不同的目录中工作。将 echo "$PWD" 添加到 RUN 块 (virtualenv ./env && echo "$PWD" && ...) 和您的 startup.sh 并比较...
【解决方案2】:

为了从我的 docker 容器中使用 virtualenv,我发现的唯一“解决方法”是通过 ssh 进入 docker,创建环境,安装库并将其文件夹设置为 docker-compose 配置中的卷所以它不会被删除,我以后可以使用它。

(或者准备好它并在构建时复制文件夹)这可能是节省构建时间的好选择,不是吗?

否则,如果我在 Dockerfile 上创建它并在那里安装库,当容器运行时,它的文件夹会变空。不知道为什么。

如果有人能提出更好的处理方法,我将不胜感激。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2018-12-01
  • 1970-01-01
  • 2019-07-29
  • 2015-04-06
  • 2014-09-17
  • 2017-09-16
  • 2014-07-13
  • 2015-07-08
相关资源
最近更新 更多