在运行时将pip需求添加到docker镜像

ral*_*rez 9 python pip requirements.txt docker

我希望能够为自己的创建docker镜像添加一些额外的要求.我的策略是使用CMD命令从dockerfile构建映像,该命令将在运行时使用已安装的卷执行"pip install -r"命令.

这是我的dockerfile:

FROM ubuntu:14.04

RUN apt-get update
RUN apt-get install -y python-pip python-dev build-essential 
RUN pip install --upgrade pip

WORKDIR /root

CMD ["pip install -r /root/sourceCode/requirements.txt"]
Run Code Online (Sandbox Code Playgroud)

有了dockerfile我构建了图像:

sudo docker build -t test .
Run Code Online (Sandbox Code Playgroud)

最后我尝试使用此命令附加我的新需求:

sudo docker run -v $(pwd)/sourceCode:/root/sourceCode -it test /bin/bash
Run Code Online (Sandbox Code Playgroud)

我的本地文件夹"sourceCode"包含一个有效的requirements.txt文件(它只包含一行值为"gunicorn").当我收到提示时,我可以看到需求文件存在,但是如果我执行pip freeze命令,则不会列出gunicorn包.

为什么requirements.txt文件已正确附加但pip命令无法正常工作?

Rao*_*Rao 7

您可以更改最后一个语句,即CMD下面的语句.

- 在下面的语句中指定pip位置的绝对路径

CMD ["/usr/bin/pip", "install", "-r", "/root/sourceCode/requirements.txt"]
Run Code Online (Sandbox Code Playgroud)

更新:根据评论添加其他答案.

必须注意的一点是,如果需要具有附加要求的自定义图像,那应该是图像的一部分而不是在运行时进行.

使用下面的基本图像来测试:

docker pull colstrom/python:legacy
Run Code Online (Sandbox Code Playgroud)

因此,应使用RUNDockerfile命令运行安装包.
并且CMD应该使用您实际想要作为容器内部进程运行的应用程序.

只需通过运行以下命令检查基本映像是否包含任何pip包,结果无效.

docker run --rm --name=testpy colstrom/python:legacy /usr/bin/pip freeze
Run Code Online (Sandbox Code Playgroud)

以下是演示相同的简单示例:

Dockerfile

FROM colstrom/python:legacy
COPY requirements.txt /requirements.txt
RUN ["/usr/bin/pip", "install", "-r", "/requirements.txt"]
CMD ["/usr/bin/pip", "freeze"]
Run Code Online (Sandbox Code Playgroud)

requirements.txt

selenium
Run Code Online (Sandbox Code Playgroud)

使用pip包构建映像希望您知道将Dockerfile,requirements.txt文件放在新目录中.

D:\dockers\py1>docker build -t pypiptest .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM colstrom/python:legacy
 ---> 640409fadf3d
Step 2 : COPY requirements.txt /requirements.txt
 ---> abbe03846376
Removing intermediate container c883642f06fb
Step 3 : RUN /usr/bin/pip install -r /requirements.txt
 ---> Running in 1987b5d47171
Collecting selenium (from -r /requirements.txt (line 1))
  Downloading selenium-3.0.1-py2.py3-none-any.whl (913kB)
Installing collected packages: selenium
Successfully installed selenium-3.0.1
 ---> f0bc90e6ac94
Removing intermediate container 1987b5d47171
Step 4 : CMD /usr/bin/pip freeze
 ---> Running in 6c3435177a37
 ---> dc1925a4f36d
Removing intermediate container 6c3435177a37
Successfully built dc1925a4f36d
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
Run Code Online (Sandbox Code Playgroud)

现在运行映像 如果你没有传递任何外部命令,那么容器接受命令CMD,只显示pip包列表.在这种情况下,selenium.

D:\dockers\py1>docker run -itd --name testreq pypiptest
039972151eedbe388b50b2b4cd16af37b94e6d70febbcb5897ee58ef545b1435

D:\dockers\py1>docker logs testreq
selenium==3.0.1
Run Code Online (Sandbox Code Playgroud)

因此,上面显示包已成功安装.

希望这是有帮助的.


R0M*_*RMY 7

TLDR

pip该命令未运行,因为您正在告诉Docker运行/bin/bash

docker run -v $(pwd)/sourceCode:/root/sourceCode -it test /bin/bash
                                                              ^
                                                             here
Run Code Online (Sandbox Code Playgroud)

更长的解释

ENTRYPOINT容器的默认值为/bin/sh -c。您不会在Dockerfile中覆盖它,因此仍然存在。默认CMD指令可能为空。您确实在Dockerfile中覆盖了它。运行时(为简洁起见,忽略音量)

docker run -it test
Run Code Online (Sandbox Code Playgroud)

容器内部实际执行的是

/bin/sh -c pip install -r /root/sourceCode/requirements.txt
Run Code Online (Sandbox Code Playgroud)

很简单,看起来像pip在启动容器时将运行。

现在,让我们看一下用于启动容器的命令(再次忽略卷)

docker run -v -it test /bin/bash
Run Code Online (Sandbox Code Playgroud)

容器内部实际执行的是

/bin/sh -c /bin/bash
Run Code Online (Sandbox Code Playgroud)

CMD您在Dockerfile中指定的参数将被COMMAND您在命令行中指定的参数覆盖。回想一下docker run 命令采用这种形式

docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
Run Code Online (Sandbox Code Playgroud)

进一步阅读

  1. 这个答案对要点CMDENTRYPOINT说明做了一个很真实的解释。

    ENTRYPOINT指定容器启动时就一定会执行的命令。

    CMD指定参数,将被输送到ENTRYPOINT

  2. 博客文章之间的区别ENTRYPOINTCMD值得阅读的说明。