【问题标题】:What is a good way to add python dependencies to a Docker container?将 python 依赖项添加到 Docker 容器的好方法是什么?
【发布时间】:2015-07-05 00:51:04
【问题描述】:

我正在尝试将 docker 集成到我的 django 工作流程中,除了一个非常烦人的问题外,我已经完成了所有设置。如果我想将依赖项添加到我的 requirements.txt 文件中,我基本上只需要重建整个容器映像以使这些依赖项保持不变。

例如,我遵循了 django here 的 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

用于构建 Web 容器的 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/

因此,当为此容器构建镜像时,requirements.txt 会安装其中最初包含的任何依赖项。

如果我使用它作为我的开发环境,那么将任何新的依赖项添加到该 requirements.txt 文件变得非常困难,因为我必须重建容器才能安装 requirements.txt 中的更改。

在 django 社区中是否有某种最佳实践来处理这个问题?如果不是,我会说 docker 在应用程序完成后看起来非常适合打包应用程序,但用作开发环境并不是很好。重建容器需要很长时间,因此浪费了很多时间。

我感谢任何见解。谢谢。

【问题讨论】:

    标签: python django docker pip docker-compose


    【解决方案1】:

    您可以在使用 docker run 时将 requirements.txt 挂载为卷(未经测试,但您明白了要点):

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

    然后您可以将脚本与您的容器捆绑在一起,该脚本将在启动您的应用程序之前运行pip install -r requirements.txt,并将其用作您的ENTRYPOINT。我喜欢自定义入口点脚本方法,它让我无需制作新容器即可完成一些额外的工作。

    也就是说,如果您正在更改您的依赖项,您可能正在更改您的应用程序,您可能应该创建一个新容器并使用更高版本对其进行标记,不是吗? :)

    【讨论】:

    • 是的,好主意。我可以让它在容器启动时安装依赖项。我要试试这个。
    • @SpencerCooley 根据你有多少依赖项,你可能想让容器拥有你知道你将永远拥有的那些,然后添加添加更多的能力。您不希望容器需要几分钟才能启动。
    • true,所以基本映像将具有所有基础,并且启动脚本将安装我在开发过程中使用的依赖项,例如一种临时依赖项列表。当我准备好全力以赴时,我可以转移我认为对系统永久存在的依赖项。有时我只是在尝试我最终不会使用的库。它就像一个依赖开发环境。 final_requirments.txt temp_requirements.txt
    • 是的,当您使用 docker 时,有很多方法可以给猫剥皮。那只是一个。你也可以在你的容器中创建一个新进程来进入并改变它正在做的事情,也许安装依赖项或运行 Django 管理控制台,而无需做太多额外的工作:docker exec -it /bin/bash
    • 我之前使用过 docker exec,但如果你曾经使用 docker-compose run 做任何事情,它会抹去你之前使用 exec 所做的事情。
    【解决方案2】:

    所以我把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,作为一种依赖暂存环境。

    当我对 dev-requirements.txt 中的依赖项感到满意时,我会将其移至 requirements.txt 以提交到映像的下一个构建。这使我可以灵活地在开发时添加和删除依赖项。

    【讨论】:

      【解决方案3】:

      我认为最好的方法是忽略当前最常见的安装 python 依赖项的方法 (pip install -r requirements.txt) 并直接在 Dockerfile 中指定您的要求,从而有效地摆脱 requirements.txt 文件。此外,您还可以免费获得 dockers 层缓存。

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

      【讨论】:

      • 我可能弄错了,但我认为这种方法是有缺陷的,因为它不能确保从这个 dockerfile 构建的其他人将获得相同版本的库。即它不会创建可重现的构建。
      • 前段时间我用过这样的docker。你能详细说明一下吗?
      猜你喜欢
      • 2016-01-14
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-01
      相关资源
      最近更新 更多