在 Dockerfile 中激活 python virtualenv

发布于 2025-01-14 00:31:40 字数 681 浏览 2 评论 0原文

我有一个 Dockerfile,我尝试在其中激活 python virtualenv,以便它应该在该环境中安装所有依赖项。然而,一切仍然在全球范围内安装。我使用了不同的方法,但没有一个有效。我也没有收到任何错误。 问题出在哪里?

1. ENV 路径 $PATH:env/bin

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

3. 运行。 env/bin/activate

我还遵循了 一个示例Google Cloud 上的 python 运行时映像的 Dockerfile 配置,与上面的内容基本相同。

设置这些环境变量与运行 source /env/bin/activate 相同。

ENV VIRTUAL_ENV /env

ENV PATH /env/bin:$PATH

另外,ENV VIRTUAL_ENV /env 是什么意思以及如何使用它?

I have a Dockerfile where I tried to activate python virtualenv so that, it should install all dependencies within this env. However, everything still gets installed globally. I used different approaches and none of them worked. I am also not getting any errors.
Where is the problem?

1.
ENV PATH $PATH:env/bin

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

3.
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.

Setting these environment variables are the same as running 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

暗喜 2025-01-21 00:31:41

设置此变量

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

与仅运行并不完全相同

RUN . env/bin/activate

,因为单个 RUN 内的激活不会影响 Dockerfile 中该 RUN 下面的任何行。但是通过 ENV 设置环境变量将为所有 RUN 命令激活虚拟环境。

看这个例子:

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

所以如果你确实需要为整个 Dockerfile 激活 virtualenv,你需要这样做:

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

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. But setting environment variables through ENV will activate your virtual environment for all RUN commands.

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:

RUN virtualenv env
ENV VIRTUAL_ENV /env                     # activating environment
ENV PATH /env/bin:$PATH                  # activating environment
RUN which python                         # -> /env/bin/python
九厘米的零° 2025-01-21 00:31:41

虽然我同意 Marcus 的观点,这不是 Docker 的做法,但你可以做你想做的事。

直接使用 Docker 的 RUN 命令不会给你答案,因为它不会从虚拟环境中执行你的指令。相反,使用 /bin/bash 将执行的指令压缩在一行中。以下 Dockerfile 对我有用:

FROM python:2.7

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

这应该仅在虚拟环境上安装 pyserial 模块。

Although I agree with Marcus that this is not the way of doing with Docker, you can do what you want.

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. Instead squeeze the instructions executed in a single line using /bin/bash. The following Dockerfile worked for me:

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.

木森分化 2025-01-21 00:31:41

有时您必须在 docker 容器中使用 venv。

一些 docker 镜像作者构建容器的方式不允许您在不先创建 venv 的情况下进行 pip install

(可能有办法解决这个问题,但为什么要对抗系统呢?)

使其工作的一种方法是执行以下操作:

RUN python3 -m venv venv
RUN ./venv/bin/pip install <list of packages to install>
ENTRYPOINT ["./venv/bin/python3", "main.py"]

换句话说,调用 python3pip直接从 venv 中获取。

如果您有 requirements.txt

COPY ./requirements.txt .
RUN python3 -m venv venv
RUN ./venv/bin/pip3 install --no-cache-dir -r requirements.txt
ENTRYPOINT ["./venv/bin/python3", "main.py"]

更多信息请参见:

Sometimes you have to use venv within a docker container.

Some docker image authors build their containers in such a way that they will not allow you to pip install without creating a venv first.

(There may be ways around this, but why fight against the system?)

One way to make it work is to do the following:

RUN python3 -m venv venv
RUN ./venv/bin/pip install <list of packages to install>
ENTRYPOINT ["./venv/bin/python3", "main.py"]

In other words, call python3 and pip from within the venv directly.

If you have a requirements.txt:

COPY ./requirements.txt .
RUN python3 -m venv venv
RUN ./venv/bin/pip3 install --no-cache-dir -r requirements.txt
ENTRYPOINT ["./venv/bin/python3", "main.py"]

Further info here:

╰◇生如夏花灿烂 2025-01-21 00:31:41

对我有用的唯一解决方案是这个

CMD ["/bin/bash", "-c", "source <your-env>/bin/activate && cd src && python main.py"]

The only solution that worked to me is this

CMD ["/bin/bash", "-c", "source <your-env>/bin/activate && cd src && python main.py"]

初心 2025-01-21 00:31:41

在虚拟环境中执行的所有 python 程序都必须首先激活该环境。激活必须由父进程在运行子 python 之前或在子 python 进程的早期完成。父级通常是 bash,但在 Dockerfile 中,父级可能是您的 ENTRYPOINT 程序。要激活,您必须:

  1. 取消设置 PYTHONHOME
  2. 将虚拟环境的路径添加到 PATH
  3. 执行 exec 时至少将这些环境变量传递给子 python 进程

例如,如果您的父进程或 ENTRYPOINT 是 golang 进程,您可能会执行以下操作在执行 python 子进程之前:

    // Our python program uses virtual environments, so activate the virtual
    // environment for python sub-processes before running it, so the
    // env vars can be inherited when its executed.
    execpath := os.Getenv("PATH")
    os.Setenv("PATH", "/venv/bin:"+execpath)
    os.Unsetenv("PYTHONHOME")

...如果虚拟环境位于 /venv 例如。

All python programs executing within a virtual env have to have that env activated first. Activation must be done by a parent process, before running the child python, or very early in the child python process. The parent is often bash, but in a Dockerfile, the parent could be your ENTRYPOINT program. To activate you must:

  1. Un-set PYTHONHOME
  2. Prepend the virtual env's path to PATH
  3. Pass in at least these environment vars to the child python process when doing exec

For example, if your parent process or ENTRYPOINT were a golang process you might do something like this before executing the python sub-process:

    // Our python program uses virtual environments, so activate the virtual
    // environment for python sub-processes before running it, so the
    // env vars can be inherited when its executed.
    execpath := os.Getenv("PATH")
    os.Setenv("PATH", "/venv/bin:"+execpath)
    os.Unsetenv("PYTHONHOME")

...if the virtual env were at /venv for example.

初与友歌 2025-01-21 00:31:41

如果您使用 python 3.x :

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

如果您使用 python 2.x :

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

If you your using 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 :

RUN pip install virtualenv
RUN virtualenv virtual
RUN /bin/bash -c "source /virtual/bin/activate"
_失温 2025-01-21 00:31:41

考虑迁移到 pipenv - 一个自动执行 virtualenv 的工具并为您进行 pip 互动。 PyPA 推荐。

通过 docker 镜像中的 pipenv 重现环境非常简单:

FROM python:3.7

RUN pip install pipenv

COPY src/Pipfile* ./

RUN pipenv install --deploy

...

Consider a migration to pipenv - a tool which will automate virtualenv and pip interactions for you. It's recommended by PyPA.

Reproduce environment via pipenv in a docker image is very simple:

FROM python:3.7

RUN pip install pipenv

COPY src/Pipfile* ./

RUN pipenv install --deploy

...
梨涡 2025-01-21 00:31:40

您不需要在 Docker 容器内使用 virtualenv。

virtualenv 用于依赖隔离。您希望防止安装的任何依赖项或包在应用程序之间泄漏。 Docker 实现了同样的目标,它隔离了容器内的依赖关系,并防止容器之间和应用程序之间的泄漏。

因此,在 Docker 容器中使用 virtualenv 是没有意义的,除非你在同一个容器中运行多个应用程序,如果是这种情况,我会说你做错了什么,解决方案是在一个容器中构建你的应用程序。更好的方法是将它们分成多个容器。


编辑 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", ]

:在上面的 Dockerfile 示例中,我们在 /opt/venv 创建一个 virtualenv 并使用 ENV 语句激活它,然后将所有依赖项安装到此中/opt/venv 并且可以简单地将此文件夹复制到构建的 runner 阶段。这有助于最小化 docker 映像的大小。

You don't need to use virtualenv inside a Docker Container.

virtualenv is used for dependency isolation. 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.

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.


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:

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. This can help with minimizing docker image size.

甜味拾荒者 2025-01-21 00:31:40

在容器中使用 virtualenv 是有充分理由的。

您不一定需要激活 virtualenv 来安装软件或使用它。尝试直接从 virtualenv 的 bin 目录调用可执行文件:

FROM python:2.7

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

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

您也可以设置 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"]

There are perfectly valid reasons for using a virtualenv within a container.

You don't necessarily need to activate the virtualenv to install software or use it. Try invoking the executables directly from the virtualenv's bin directory instead:

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/

FROM python:2.7

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

CMD ["python", "yourcode.py"]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文