在运行时对 docker 图像添加 pip 要求
Add pip requirements to docker image in runtime
我希望能够对自己创建的 docker 图像添加一些额外要求。我的策略是使用 CMD 命令从 docker 文件构建映像,该命令将在运行时使用已安装的卷执行 "pip install -r" 命令。
这是我的docker文件:
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"]
有了那个 docker 文件,我构建了图像:
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 命令无法正常工作?
您可以将最后一条语句,即 CMD
更改为以下内容。
--在下面的语句中指定pip位置的绝对路径
CMD ["/usr/bin/pip", "install", "-r", "/root/sourceCode/requirements.txt"]
更新: 根据评论添加额外的答案。
必须注意一件事,如果需要自定义图像并有其他要求,那应该是图像的一部分,而不是在 运行 时做。
使用下面的基础图像进行测试:
docker pull colstrom/python:legacy
因此,安装包应该 运行 使用 Dockerfile 的 RUN
命令。
并且 CMD
应该使用你真正想要的应用程序 运行 作为容器内部的进程。
仅通过 运行ning 下面的命令检查基本映像是否有任何 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 包构建镜像希望你知道将 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
所以,上面显示包安装成功。
希望这对您有所帮助。
TLDR
pip
命令不是 运行ning,因为你告诉 Docker 到 运行 /bin/bash
。
docker run -v $(pwd)/sourceCode:/root/sourceCode -it test /bin/bash
^
here
更长的解释
容器的默认 ENTRYPOINT
是 /bin/sh -c
。您不会在 Docker 文件中覆盖它,所以它仍然存在。默认的 CMD
指令可能什么都没有。您确实会在 Docker 文件中覆盖它。当您 运行 (为简洁起见忽略音量)
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
您在 Docker 文件中指定的 CMD
参数会被您在命令行中指定的 COMMAND
覆盖。回想一下 docker run
command takes this form
docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
进一步阅读
This answer 对 CMD
和 ENTRYPOINT
指令的作用有一个非常中肯的解释
The ENTRYPOINT
specifies a command that will always be executed when the container starts.
The CMD
specifies arguments that will be fed to the ENTRYPOINT
.
这篇关于 ENTRYPOINT
和 CMD
的区别的 blog post 值得一读。
使用@Rao 和@ROMANARMY 在他们的答案中解释的概念,我终于找到了一种做我想做的事情的方法:向自创建的 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
最后我使用这些命令构建并 运行 图像:
docker build --tag test .
docker run -itd --name container_test -v $(pwd)/sourceCode:/root/sourceCode test <- without any parameter at the end
正如我在 post 开头所解释的,我在本地文件夹中有一个名为 sourceCode 的文件夹,其中包含一个有效的 requirements.txt 文件,只有一行 "gunicorn"
所以我终于能够向给定的 docker 图像添加一些额外的要求(在本例中为 gunicorn 包)。
构建并 运行 完成我的实验后如果我检查日志 (docker logs container_test
),我会看到类似这样的内容:
Downloading gunicorn-19.6.0-py2.py3-none-any.whl (114kB)
100% |################################| 122kB 1.1MB/s
Installing collected packages: gunicorn
此外,容器在已安装的卷中创建了一个 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
现在我对新创建的文件的权限有其他问题,但这可能会在新的 post.
中
谢谢!
我希望能够对自己创建的 docker 图像添加一些额外要求。我的策略是使用 CMD 命令从 docker 文件构建映像,该命令将在运行时使用已安装的卷执行 "pip install -r" 命令。
这是我的docker文件:
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"]
有了那个 docker 文件,我构建了图像:
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 命令无法正常工作?
您可以将最后一条语句,即 CMD
更改为以下内容。
--在下面的语句中指定pip位置的绝对路径
CMD ["/usr/bin/pip", "install", "-r", "/root/sourceCode/requirements.txt"]
更新: 根据评论添加额外的答案。
必须注意一件事,如果需要自定义图像并有其他要求,那应该是图像的一部分,而不是在 运行 时做。
使用下面的基础图像进行测试:
docker pull colstrom/python:legacy
因此,安装包应该 运行 使用 Dockerfile 的 RUN
命令。
并且 CMD
应该使用你真正想要的应用程序 运行 作为容器内部的进程。
仅通过 运行ning 下面的命令检查基本映像是否有任何 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 包构建镜像希望你知道将 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
所以,上面显示包安装成功。
希望这对您有所帮助。
TLDR
pip
命令不是 运行ning,因为你告诉 Docker 到 运行 /bin/bash
。
docker run -v $(pwd)/sourceCode:/root/sourceCode -it test /bin/bash
^
here
更长的解释
容器的默认 ENTRYPOINT
是 /bin/sh -c
。您不会在 Docker 文件中覆盖它,所以它仍然存在。默认的 CMD
指令可能什么都没有。您确实会在 Docker 文件中覆盖它。当您 运行 (为简洁起见忽略音量)
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
您在 Docker 文件中指定的 CMD
参数会被您在命令行中指定的 COMMAND
覆盖。回想一下 docker run
command takes this form
docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
进一步阅读
This answer 对
CMD
和ENTRYPOINT
指令的作用有一个非常中肯的解释The
ENTRYPOINT
specifies a command that will always be executed when the container starts.The
CMD
specifies arguments that will be fed to theENTRYPOINT
.这篇关于
ENTRYPOINT
和CMD
的区别的 blog post 值得一读。
使用@Rao 和@ROMANARMY 在他们的答案中解释的概念,我终于找到了一种做我想做的事情的方法:向自创建的 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
最后我使用这些命令构建并 运行 图像:
docker build --tag test .
docker run -itd --name container_test -v $(pwd)/sourceCode:/root/sourceCode test <- without any parameter at the end
正如我在 post 开头所解释的,我在本地文件夹中有一个名为 sourceCode 的文件夹,其中包含一个有效的 requirements.txt 文件,只有一行 "gunicorn"
所以我终于能够向给定的 docker 图像添加一些额外的要求(在本例中为 gunicorn 包)。
构建并 运行 完成我的实验后如果我检查日志 (docker logs container_test
),我会看到类似这样的内容:
Downloading gunicorn-19.6.0-py2.py3-none-any.whl (114kB)
100% |################################| 122kB 1.1MB/s
Installing collected packages: gunicorn
此外,容器在已安装的卷中创建了一个 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
现在我对新创建的文件的权限有其他问题,但这可能会在新的 post.
中谢谢!