首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何避免在构建Python项目的Docker镜像时重新安装包?

如何避免在构建Python项目的Docker镜像时重新安装包?
EN

Stack Overflow用户
提问于 2014-08-14 18:25:21
回答 4查看 68.1K关注 0票数 172

我的Dockerfile类似于

代码语言:javascript
复制
FROM my/base

ADD . /srv
RUN pip install -r requirements.txt
RUN python setup.py install

ENTRYPOINT ["run_server"]

每次我构建新的镜像时,都必须重新安装依赖项,这在我所在的区域可能会非常慢。

对于已经安装的cache包,我想到的一种方法是用更新的镜像覆盖my/base镜像,如下所示:

代码语言:javascript
复制
docker build -t new_image_1 .
docker tag new_image_1 my/base

因此,下次我使用此Dockerfile进行构建时,我的/base已经安装了一些包。

但是这个解决方案有两个问题:

  1. 并非总是可以覆盖基本映像
  2. 随着更新的映像在其上层叠,基本映像会变得越来越大

那么我可以使用什么更好的解决方案来解决这个问题呢?

编辑:

关于我机器上的docker的一些信息:

代码语言:javascript
复制
☁  test  docker version
Client version: 1.1.2
Client API version: 1.13
Go version (client): go1.2.1
Git commit (client): d84a070
Server version: 1.1.2
Server API version: 1.13
Go version (server): go1.2.1
Git commit (server): d84a070
☁  test  docker info
Containers: 0
Images: 56
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Dirs: 56
Execution Driver: native-0.2
Kernel Version: 3.13.0-29-generic
WARNING: No swap limit support
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-08-14 20:01:48

尝试构建如下所示的Dockerfile:

代码语言:javascript
复制
FROM my/base

WORKDIR /srv
ADD ./requirements.txt /srv/requirements.txt
RUN pip install -r requirements.txt
ADD . /srv
RUN python setup.py install

ENTRYPOINT ["run_server"]

只要您不对requirements.txt进行任何更改,Docker将在pip安装过程中使用缓存,而不管Docker上的其他代码文件是否已更改。下面是一个例子。

下面是一个简单的Hello, World!程序:

代码语言:javascript
复制
$ tree
.
├── Dockerfile
├── requirements.txt
└── run.py   

0 directories, 3 file

# Dockerfile

FROM dockerfile/python
WORKDIR /srv
ADD ./requirements.txt /srv/requirements.txt
RUN pip install -r requirements.txt
ADD . /srv
CMD python /srv/run.py

# requirements.txt
pytest==2.3.4

# run.py
print("Hello, World")

docker build的输出:

代码语言:javascript
复制
Step 1 : WORKDIR /srv
---> Running in 22d725d22e10
---> 55768a00fd94
Removing intermediate container 22d725d22e10
Step 2 : ADD ./requirements.txt /srv/requirements.txt
---> 968a7c3a4483
Removing intermediate container 5f4e01f290fd
Step 3 : RUN pip install -r requirements.txt
---> Running in 08188205e92b
Downloading/unpacking pytest==2.3.4 (from -r requirements.txt (line 1))
  Running setup.py (path:/tmp/pip_build_root/pytest/setup.py) egg_info for package pytest
....
Cleaning up...
---> bf5c154b87c9
Removing intermediate container 08188205e92b
Step 4 : ADD . /srv
---> 3002a3a67e72
Removing intermediate container 83defd1851d0
Step 5 : CMD python /srv/run.py
---> Running in 11e69b887341
---> 5c0e7e3726d6
Removing intermediate container 11e69b887341
Successfully built 5c0e7e3726d6

让我们修改一下run.py

代码语言:javascript
复制
# run.py
print("Hello, Python")

尝试再次构建,以下是输出:

代码语言:javascript
复制
Sending build context to Docker daemon  5.12 kB
Sending build context to Docker daemon 
Step 0 : FROM dockerfile/python
---> f86d6993fc7b
Step 1 : WORKDIR /srv
---> Using cache
---> 55768a00fd94
Step 2 : ADD ./requirements.txt /srv/requirements.txt
---> Using cache
---> 968a7c3a4483
Step 3 : RUN pip install -r requirements.txt
---> Using cache
---> bf5c154b87c9
Step 4 : ADD . /srv
---> 9cc7508034d6
Removing intermediate container 0d7cf71eb05e
Step 5 : CMD python /srv/run.py
---> Running in f25c21135010
---> 4ffab7bc66c7
Removing intermediate container f25c21135010
Successfully built 4ffab7bc66c7

正如您在上面看到的,这一次docker在构建过程中使用缓存。现在,让我们更新requirements.txt

代码语言:javascript
复制
# requirements.txt

pytest==2.3.4
ipython

以下是docker build的输出:

代码语言:javascript
复制
Sending build context to Docker daemon  5.12 kB
Sending build context to Docker daemon 
Step 0 : FROM dockerfile/python
---> f86d6993fc7b
Step 1 : WORKDIR /srv
---> Using cache
---> 55768a00fd94
Step 2 : ADD ./requirements.txt /srv/requirements.txt
---> b6c19f0643b5
Removing intermediate container a4d9cb37dff0
Step 3 : RUN pip install -r requirements.txt
---> Running in 4b7a85a64c33
Downloading/unpacking pytest==2.3.4 (from -r requirements.txt (line 1))
  Running setup.py (path:/tmp/pip_build_root/pytest/setup.py) egg_info for package pytest

Downloading/unpacking ipython (from -r requirements.txt (line 2))
Downloading/unpacking py>=1.4.12 (from pytest==2.3.4->-r requirements.txt (line 1))
  Running setup.py (path:/tmp/pip_build_root/py/setup.py) egg_info for package py

Installing collected packages: pytest, ipython, py
  Running setup.py install for pytest

Installing py.test script to /usr/local/bin
Installing py.test-2.7 script to /usr/local/bin
  Running setup.py install for py

Successfully installed pytest ipython py
Cleaning up...
---> 23a1af3df8ed
Removing intermediate container 4b7a85a64c33
Step 4 : ADD . /srv
---> d8ae270eca35
Removing intermediate container 7f003ebc3179
Step 5 : CMD python /srv/run.py
---> Running in 510359cf9e12
---> e42fc9121a77
Removing intermediate container 510359cf9e12
Successfully built e42fc9121a77

注意docker在pip安装过程中没有使用缓存。如果它不工作,请检查您的docker版本。

代码语言:javascript
复制
Client version: 1.1.2
Client API version: 1.13
Go version (client): go1.2.1
Git commit (client): d84a070
Server version: 1.1.2
Server API version: 1.13
Go version (server): go1.2.1
Git commit (server): d84a070
票数 173
EN

Stack Overflow用户

发布于 2016-10-29 23:19:44

要最小化网络活动,您可以将pip指向主机上的缓存目录。

运行docker容器,并将主机的pip缓存目录bind挂载到容器的pip缓存目录中。docker run命令应如下所示:

代码语言:javascript
复制
docker run -v $HOME/.cache/pip-docker/:/root/.cache/pip image_1

然后,在您的Dockerfile文件中,将需求作为ENTRYPOINT语句(或CMD语句)的一部分安装,而不是作为RUN命令。这一点很重要,因为(正如注释中指出的)挂载在映像构建期间不可用(当执行RUN语句时)。Docker文件应如下所示:

代码语言:javascript
复制
FROM my/base

ADD . /srv

ENTRYPOINT ["sh", "-c", "pip install -r requirements.txt && python setup.py install && run_server"]
票数 31
EN

Stack Overflow用户

发布于 2021-06-19 07:27:06

代码语言:javascript
复制
pipenv install

默认情况下会尝试重新锁定。当它这样做的时候,Docker构建的缓存层不会被使用,因为Pipfile.lock已经改变了。See the docs

解决此问题的方法是对Pipfile.lock进行版本化,并使用

代码语言:javascript
复制
RUN pipenv sync

而不是。

感谢JFG Piñeiro。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25305788

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档