【问题标题】:Duplication in DockerfilesDockerfile 中的重复
【发布时间】:2018-03-17 22:44:15
【问题描述】:

我有一个 Django Web 应用程序,它在后台使用 celery 执行周期性任务。

现在我有三个 docker 图像

  • 一个用于 django 应用程序
  • 芹菜工人专用
  • 一个用于 celery 调度程序

他们的Dockerfiles 都长这样:

FROM alpine:3.7

ENV PYTHONUNBUFFERED 1

RUN mkdir /code
WORKDIR /code
COPY Pipfile Pipfile.lock ./

RUN apk update && \
 apk add python3 postgresql-libs jpeg-dev git && \
 apk add --virtual .build-deps gcc python3-dev musl-dev postgresql-dev zlib-dev && \
 pip3 install --no-cache-dir pipenv && \
 pipenv install --system && \
 apk --purge del .build-deps

COPY . ./

# Run the image as a non-root user
RUN adduser -D noroot
USER noroot

EXPOSE $PORT

CMD <Different CMD for all three containers>

所以除了最后一行之外,它们都完全相同。

在这里创建某种包含除 CMD 之外的所有内容的基本映像是否有意义。并且所有三个图像都使用它作为基础并仅添加它们各自的 CMD?

或者这不会给我带来任何好处,因为无论如何都会缓存所有内容?

您在上面看到的分离是否合理?

两个小问题:

  • 有时apk update .. 层会被 docker 缓存。 docker怎么知道这里没有更新?
  • 我经常读到我应该尽可能减少图层以减小图像大小。但这不是与缓存理念背道而驰,而且会导致构建时间更长吗?

【问题讨论】:

  • 这将是使用docker-compose 处理单个图像并为每个服务覆盖 CMD 的好地方
  • 至于apk update何时被缓存,docker不知道。您的apk update 和安装只有在您更改正在安装的软件包集(这会使该行的缓存无效)或您编辑您的PipfilePipfile.lock(这会使上面缓存的COPY 命令无效并且所有后续步骤)
  • @avigil 合理的建议,但我也想将我的应用程序部署到heroku。而且它不使用 docker-compose afaik。

标签: docker dockerfile


【解决方案1】:

我建议查看docker-compose 以简化多个容器的管理。

使用您在上面发布的单个 Dockerfile,然后创建一个可能如下所示的 docker-compose.yml

version: '3'
services:
  # a django service serving an application on port 80
  django:
    build: .
    command: python manage.py runserver
    ports:
      - 8000:80
  # the celery worker
  worker:
    build: .
    command: celery worker
  # the celery scheduler
  scheduler:
    build: .
    command: celery beat

当然,将此处的命令修改为您当前单独的 Dockerfile 使用的任何命令。

当您想要重建镜像时,docker-compose build 将从您的 Dockerfile 为第一个服务重建您的容器镜像,然后将构建的镜像重用于其他服务(因为它们已经存在于缓存中)。 docker-compose up 将启动 3 个容器映像实例,但每次都会覆盖运行命令。

如果你想变得更复杂,有plenty of resources 用于 django 和 celery 的非常常见的组合。

【讨论】:

  • 感谢您的回答,我不知道 docker-compose 中的 command 键。我实际上已经使用 docker-compose 进行本地开发。但是我也将我的应用程序部署到 Heroku 并且 afaik 不能处理 docker-compose。所以我认为我坚持使用三个 Dockerfiles
【解决方案2】:

我会建议使用一个 Dockerfile 并在运行时更新你的 CMD。一点点修改也适用于本地和 Heroku。

就 Heroku 而言,他们提供环境变量来使用环境变量启动容器。 heroku set-up-your-local-environment-variables

    FROM alpine:3.7

ENV PYTHONUNBUFFERED 1
ENV APPLICATION_TO_RUN=default_application

RUN mkdir /code
WORKDIR /code
COPY Pipfile Pipfile.lock ./

RUN apk update && \
 apk add python3 postgresql-libs jpeg-dev git && \
 apk add --virtual .build-deps gcc python3-dev musl-dev postgresql-dev zlib-dev && \
 pip3 install --no-cache-dir pipenv && \
 pipenv install --system && \
 apk --purge del .build-deps

COPY . ./

# Run the image as a non-root user
RUN adduser -D noroot
USER noroot

EXPOSE $PORT

CMD $APPLICATION_TO_RUN

因此,当您运行容器时,会将您的应用程序名称传递给运行命令。

docker run -it --name test -e APPLICATION_TO_RUN="celery beat" --rm test

【讨论】:

    猜你喜欢
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-22
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多