在运行时将泊位要求添加到泊坞窗图像

我希望能够添加一些额外的要求,以创build一个自己的泊坞窗图像。 我的策略是使用CMD命令从dockerfile构build映像,该命令将在运行时使用已安装的卷执行“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"] 

有了这个dockerfile我build立了图像:

 sudo docker build -t test . 

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

 sudo docker run -v $(pwd)/sourceCode:/root/sourceCode -it test /bin/bash 

我的本地文件夹“sourceCode”内有一个有效的requirements.txt文件(它只包含一行值“gunicorn”)。 当我得到提示时,我可以看到需求文件在那里,但是如果我执行pip freeze命令,gunicorn软件包不在列表中。

为什么requirements.txt文件已经正确连接,但是pip命令无法正常工作?

TLDR

pip命令没有运行,因为你告诉Docker运行/bin/bash

 docker run -v $(pwd)/sourceCode:/root/sourceCode -it test /bin/bash ^ here 

更长的解释

容器的默认ENTRYPOINT/bin/sh -c 。 你不要在Dockerfile中覆盖它,所以仍然存在。 默认的CMD指令可能什么都不是。 你可以在你的Dockerfile中覆盖它。 运行时(为了简洁,忽略音量)

 docker run -it test 

什么实际上在容器内执行

 /bin/sh -c pip install -r /root/sourceCode/requirements.txt 

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

现在让我们来看看你用来启动容器的命令(再次忽略卷)

 docker run -v -it test /bin/bash 

什么实际上在容器内执行

 /bin/sh -c /bin/bash 

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

 docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...] 

进一步阅读

  1. 这个答案对CMDENTRYPOINT指令的作用有一个真正的重点解释

    ENTRYPOINT指定一个在容器启动时总是执行的命令。

    CMD指定将被馈送到进入点的ENTRYPOINT

  2. 这篇博客文章介绍了ENTRYPOINTCMD指令之间的区别,值得一读。

您可以将最后一条语句(即CMD更改为下面的语句。

– 在下面的语句中指定点位置的绝对path

 CMD ["/usr/bin/pip", "install", "-r", "/root/sourceCode/requirements.txt"] 

更新:根据评论添加额外的答案。

有一点必须注意,如果定制的图像需要额外的需求,那应该是图像的一部分,而不是在运行时进行。

使用下面的基本图像来testing:

 docker pull colstrom/python:legacy 

所以,安装包应该使用Dockerfile的RUN命令来运行。
而且应该使用CMD作为容器内的一个进程实际上想运行的应用程序。

只要通过运行下面的命令来检查基本映像是否有任何pip包,结果什么都没有

 docker run --rm --name=testpy colstrom/python:legacy /usr/bin/pip freeze 

下面是简单的例子来演示相同的:

Dockerfile

 FROM colstrom/python:legacy COPY requirements.txt /requirements.txt RUN ["/usr/bin/pip", "install", "-r", "/requirements.txt"] CMD ["/usr/bin/pip", "freeze"] 

requirements.txt

 selenium 

用pip包构build映像希望您知道将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. 

现在运行映像如果你没有传递任何外部命令,那么容器从CMD获取命令,这只是显示了pip包的列表。 在这种情况下, selenium

 D:\dockers\py1>docker run -itd --name testreq pypiptest 039972151eedbe388b50b2b4cd16af37b94e6d70febbcb5897ee58ef545b1435 D:\dockers\py1>docker logs testreq selenium==3.0.1 

所以,上面显示的是软件包安装成功。

希望这是有帮助的。

使用@Rao和@ROMANARMY在他们的答案中已经解释的概念,我终于find了一种做我想做的事情的方式:为自创的docker镜像添加额外的python需求。

我的新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 COPY install_req.sh . CMD ["/bin/bash" , "install_req.sh"] 

我已经添加了第一个命令执行一个shell脚本,其中包含以下内容:

 #!/bin/bash pip install -r /root/sourceCode/requirements.txt pip freeze > /root/sourceCode/freeze.txt 

最后,我使用这些命令构build并运行映像:

 docker build --tag test . docker run -itd --name container_test -v $(pwd)/sourceCode:/root/sourceCode test <- without any parameter at the end 

正如我在文章开头解释的那样,我在本地文件夹中有一个名为sourceCode的文件夹,其中包含一个有效的requirements.txt文件,只有一行“gunicorn”

所以最后,我有能力添加一些额外的要求(在这个例子中的gunicorn包)到一个给定的docker图像。

build立和运行我的实验后如果我检查日志( docker logs container_test ),我看到这样的事情:

 Downloading gunicorn-19.6.0-py2.py3-none-any.whl (114kB) 100% |################################| 122kB 1.1MB/s Installing collected packages: gunicorn 

此外,容器已经在安装的卷中创build了一个freeze.txt文件,其中包含所有安装的pip软件包,包括所需的gunicorn:

 chardet==2.0.1 colorama==0.2.5 gunicorn==19.6.0 html5lib==0.999 requests==2.2.1 six==1.5.2 urllib3==1.7.1 

现在我还有其他问题与新创build的文件的权限,但这可能会在一个新的职位。

谢谢!