为Python项目构buildDocker镜像时如何避免重新安装软件包?

我的Dockerfile是类似的

FROM my/base ADD . /srv RUN pip install -r requirements.txt RUN python setup.py install ENTRYPOINT ["run_server"] 

每当我build立一个新的形象,依赖关系必须重新安装,这可能是在我的地区非常缓慢。

我想要cache已经安装的软件包的一种方法是用这样的新图像覆盖my/base图像:

 docker build -t new_image_1 . docker tag new_image_1 my/base 

所以下次我用这个Dockerfile构build时,我的/ base已经安装了一些软件包。

但是这个解决scheme有两个问题:

  1. 覆盖基本图像并不总是可能的
  2. 随着更新的图像分层,基本图像变得越来越大

那么我能用什么更好的解决scheme来解决这个问题呢?

编辑##:

关于我的机器上的泊坞窗的一些信息:

 ☁ 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 

尝试使用下面的Dockerfile来构build。

 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"] 

如果有一些变化. (您的项目),docker工通过使用caching跳过pip install线。

在编辑requirements.txt文件时,Docker只能在build上运行pip install


我写简单的Hello, World! 程序。

 $ 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") 

以下是输出。

 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并尝试再次构build。

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

以下是输出。

 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使用构buildcaching。 我这次更新requirements.txt。

 # requirements.txt pytest==2.3.4 ipython 

以下是输出。

 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不使用构buildcaching。 如果不起作用,请检查您的docker版本。

 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 

为了最大限度地减lessnetworking活动,您可以将pip指向主机上的caching目录。

在您的docker run命令中,将主机的pipcaching目录安装为容器中的卷,例如:

 docker run -v $HOME/.cache/pip/:/pip-cache image_1 

然后在你的Dockerfile中,告诉pip使用共享caching目录:

 FROM my/base ADD . /srv RUN pip install -r requirements.txt --cache-dir /pip-cache RUN python setup.py install ENTRYPOINT ["run_server"] 

如果主机系统的默认pip目录将被用作caching(例如,Linux上的$HOME/.cache/pip/或OSX上的$HOME/Library/Caches/pip/ ),那么最好的办法就是像我在示例docker run命令。

我发现更好的方法是将Python站点包目录作为卷添加。

 services: web: build: . command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/code - /usr/local/lib/python2.7/site-packages/ 

这样我就可以安装新的库,而不必进行完整的重build。

编辑 :无视这个答案, jkukul上面答案为我工作。 我的意图是cachingsite-packages文件夹。 那看起来更像是:

 volumes: - .:/code - ./cached-packages:/usr/local/lib/python2.7/site-packages/ 

caching下载文件夹虽然很清洁。 这也caching轮子,所以它适当地完成任务。