简体   繁体   English

在 Dockerfile 中激活 python virtualenv

[英]Activate python virtualenv in Dockerfile

I have a Dockerfile where I try to activate python virtualenv after what, it should install all dependencies within this env.我有一个 Dockerfile,我尝试在其中激活 python virtualenv,它应该在这个 env 中安装所有依赖项。 However, everything still gets installed globally.但是,所有内容仍会在全局范围内安装。 I used different approaches and non of them worked.我使用了不同的方法,但没有一个有效。 I also do not get any errors.我也没有收到任何错误。 Where is a problem?哪里有问题?

1. ENV PATH $PATH:env/bin 1. ENV PATH $PATH:env/bin

2. ENV PATH $PATH:env/bin/activate 2. ENV PATH $PATH:env/bin/activate

3. RUN . env/bin/activate 3. RUN . env/bin/activate RUN . env/bin/activate

I also followed an example of a Dockerfile config for the python-runtime image on Google Cloud , which is basically the same stuff as above.我还遵循了 Google Cloud 上 python-runtime 映像的 Dockerfile 配置示例,它与上面的内容基本相同。

Setting these environment variables are the same as running source /env/bin/activate.设置这些环境变量与运行 source /env/bin/activate 相同。

ENV VIRTUAL_ENV /env

ENV PATH /env/bin:$PATH

Additionally, what does ENV VIRTUAL_ENV /env mean and how it is used?此外, ENV VIRTUAL_ENV /env是什么意思以及它是如何使用的?

You don't need to use virtualenv inside a Docker Container.您不需要在 Docker 容器中使用 virtualenv。

virtualenv is used for dependency isolation. virtualenv用于依赖隔离。 You want to prevent any dependencies or packages installed from leaking between applications.您希望防止安装的任何依赖项或软件包在应用程序之间泄漏。 Docker achieves the same thing, it isolates your dependencies within your container and prevent leaks between containers and between applications. Docker实现了同样的目标,它隔离了容器内的依赖关系,并防止容器之间和应用程序之间的泄漏。

Therefore, there is no point in using virtualenv inside a Docker Container unless you are running multiple apps in the same container, if that's the case I'd say that you're doing something wrong and the solution would be to architect your app in a better way and split them up in multiple containers.因此,除非您在同一个容器中运行多个应用程序,否则在 Docker 容器中使用 virtualenv 是没有意义的,如果是这种情况,我会说您做错了什么,解决方案是将您的应用程序构建在一个更好的方法并将它们分成多个容器。


EDIT 2022: Given this answer get a lot of views, I thought it might make sense to add that now 4 years later, I realized that there actually is valid usages of virtual environments in Docker images, especially when doing multi staged builds:编辑 2022:鉴于这个答案获得了很多观点,我认为在 4 年后的现在添加这一点可能是有意义的,我意识到 Docker 映像中实际上存在虚拟环境的有效用法,尤其是在进行多阶段构建时:

FROM python:3.9-slim as compiler
ENV PYTHONUNBUFFERED 1

WORKDIR /app/

RUN python -m venv /opt/venv
# Enable venv
ENV PATH="/opt/venv/bin:$PATH"

COPY ./requirements.txt /app/requirements.txt
RUN pip install -Ur requirements.txt

FROM python:3.9-slim as runner
WORKDIR /app/
COPY --from=compiler /opt/venv /opt/venv

# Enable venv
ENV PATH="/opt/venv/bin:$PATH"
COPY . /app/
CMD ["python", "app.py", ]

In the Dockerfile example above, we are creating a virtualenv at /opt/venv and activating it using an ENV statement, we then install all dependencies into this /opt/venv and can simply copy this folder into our runner stage of our build.在上面的Dockerfile示例中,我们在/opt/venv创建一个 virtualenv 并使用ENV语句激活它,然后我们将所有依赖项安装到这个/opt/venv ,并且可以简单地将这个文件夹复制到我们构建的runner阶段。 This can help with with minimizing docker image size.这有助于最小化 docker 图像大小。

There are perfectly valid reasons for using a virtualenv within a container.在容器中使用 virtualenv 有完全正当的理由。

You don't necessarily need to activate the virtualenv to install software or use it.您不一定需要激活 virtualenv 来安装软件或使用它。 Try invoking the executables directly from the virtualenv's bin directory instead:尝试直接从 virtualenv 的bin目录调用可执行文件:

FROM python:2.7

RUN virtualenv /ve
RUN /ve/bin/pip install somepackage

CMD ["/ve/bin/python", "yourcode.py"]

You may also just set the PATH environment variable so that all further Python commands will use the binaries within the virtualenv as described in https://pythonspeed.com/articles/activate-virtualenv-dockerfile/您也可以只设置 PATH 环境变量,以便所有进一步的 Python 命令将使用 virtualenv 中的二进制文件,如https://pythonspeed.com/articles/activate-virtualenv-dockerfile/中所述

FROM python:2.7

RUN virtualenv /ve
ENV PATH="/ve/bin:$PATH"
RUN pip install somepackage

CMD ["python", "yourcode.py"]

Setting this variables设置此变量

ENV VIRTUAL_ENV /env
ENV PATH /env/bin:$PATH

is not exactly the same as just running和刚跑不完全一样

RUN . env/bin/activate

because activation inside single RUN will not affect any lines below that RUN in Dockerfile.因为在单个RUN内激活不会影响 Dockerfile 中该RUN以下的任何行。 But setting environment variables through ENV will activate your virtual environment for all RUN commands.但是通过ENV设置环境变量会为所有RUN命令激活你的虚拟环境。

Look at this example:看这个例子:

RUN virtualenv env                       # setup env
RUN which python                         # -> /usr/bin/python
RUN . /env/bin/activate && which python  # -> /env/bin/python
RUN which python                         # -> /usr/bin/python

So if you really need to activate virtualenv for the whole Dockerfile you need to do something like this:因此,如果您确实需要为整个 Dockerfile 激活 virtualenv,您需要执行以下操作:

RUN virtualenv env
ENV VIRTUAL_ENV /env                     # activating environment
ENV PATH /env/bin:$PATH                  # activating environment
RUN which python                         # -> /env/bin/python

Although I agree with Marcus that this is not the way of doing with Docker, you can do what you want.尽管我同意 Marcus 的观点,这不是使用 Docker 的方式,但你可以做你想做的事。

Using the RUN command of Docker directly will not give you the answer as it will not execute your instructions from within the virtual environment.直接使用 Docker 的 RUN 命令不会给你答案,因为它不会在虚拟环境中执行你的指令。 Instead squeeze the instructions executed in a single line using /bin/bash.而是使用 /bin/bash 压缩在一行中执行的指令。 The following Dockerfile worked for me:以下 Dockerfile 对我有用:

FROM python:2.7

RUN virtualenv virtual
RUN /bin/bash -c "source /virtual/bin/activate && pip install pyserial && deactivate"
...

This should install the pyserial module only on the virtual environment.这应该只在虚拟环境中安装 pyserial 模块。

If you your using python 3.x :如果您使用 python 3.x :

RUN pip install virtualenv
RUN virtualenv -p python3.5 virtual
RUN /bin/bash -c "source /virtual/bin/activate"

If you are using python 2.x :如果您使用的是 python 2.x :

RUN pip install virtualenv
RUN virtualenv virtual
RUN /bin/bash -c "source /virtual/bin/activate"

Consider a migration to pipenv - a tool which will automate virtualenv and pip interactions for you.考虑迁移到pipenv - 一个可以为您自动化 virtualenv 和 pip 交互的工具。 It's recommended by PyPA . PyPA推荐它。

Reproduce environment via pipenv in a docker image is very simple:在 docker 镜像中通过pipenv重现环境非常简单:

FROM python:3.7

RUN pip install pipenv

COPY src/Pipfile* ./

RUN pipenv install --deploy

...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM