什么是向Docker容器添加python依赖关系的好方法?

我正在尝试将docker集成到我的django工作stream程中,除了一个非常烦人的问题之外,我已经设置了一切。 如果我想添加依赖到我的requirements.txt文件,我基本上只需要重build整个容器图像的依赖粘附。

例如,我在这里跟随了django的docker-compose例子。 yaml文件是这样设置的:

db: image: postgres web: build: . command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/code ports: - "8000:8000" links: - db 

和用于构buildWeb容器的Docker文件是这样设置的:

 FROM python:2.7 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code ADD requirements.txt /code/ RUN pip install -r requirements.txt ADD . /code/ 

所以当为这个容器构build镜像的时候,require.txt被安装在最初的任何依赖关系中。

如果我使用这个作为我的开发环境,那么添加任何新的依赖到这个requirements.txt文件是非常困难的,因为我将不得不重build容器来安装在requirements.txt中的变化。

在Django社区有没有一些最好的做法来解决这个问题? 如果不是的话,我会说Docker看起来非常好,因为一旦完成了应用程序的封装,但是作为一个开发环境并不是很好。 重build容器需要很长时间,所以浪费了很多时间。

我很欣赏任何见解。 谢谢。

在使用docker run时,你可以将requirements.txt作为一个卷挂载(未经testing,但你得到的要点):

 docker run container:tag -v /code/requirements.txt ./requirements.txt 

然后你可以绑定一个脚本和你的容器,在启动你的应用程序之前运行pip install -r requirements.txt ,并将其用作你的ENTRYPOINT 。 我喜欢自定义的入口脚本方法,它可以让我做一些额外的工作,而无需创build一个新的容器。

也就是说,如果你正在改变你的依赖关系,你可能正在改变你的应用程序,你应该创build一个新的容器,并用更高版本来标记它,不是吗? 🙂

所以我把yaml文件改成这样:

 db: image: postgres web: build: . command: sh startup.sh volumes: - .:/code ports: - "8000:8000" links: - db 

我做了一个简单的shell脚本startup.sh:

 #!/bin/bash #restart this script as root, if not already root [ `whoami` = root ] || exec sudo $0 $* pip install -r dev-requirements.txt python manage.py runserver 0.0.0.0:8000 

然后将由上述shell脚本安装的dev-requirements.txt作为一种依赖性分段环境进行sorting。

当我满足dev-requirements.txt中的一个依赖关系时,我将把它移动到requirements.txt中,以提交给图像的下一个版本。 这使我可以灵活地在开发过程中添加和删除依赖项。

我认为最好的办法是忽略当前最常见的安装python依赖( pip install -r requirements.txt )的方法,并直接在Dockerfile中指定你的需求,从而有效地去掉requirements.txt文件。 另外你可以免费获得docker层的caching。

 FROM python:2.7 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code # make sure you install requirements before the ADD, since everything after ADD is not cached RUN pip install flask==0.10.1 RUN pip install sqlalchemy==1.0.6 ... ADD . /code/ 

如果docker容器是你的应用程序运行的唯一方式,那么我build议你这样做。 如果你想支持其他的设置你的代码的方法(例如virtualenv),那么这当然不适合你,你应该回到使用需求文件或使用setup.py例程。 无论哪种方式,我发现这种方式是最简单和直接的,而不处理所有python包分发问题。