Docker Compose中的多阶段构建?

90
我该如何在docker-compose.yml中指定多阶段构建?
对于每个变体(例如dev,prod...),我都有一个包含2个Docker文件的多阶段构建:
- dev: Dockerfile.base + Dockerfile.dev - 或者 prod: Dockerfile.base + Dockerfile.prod 文件Dockerfile.base(适用于所有变体):
FROM python:3.6
RUN apt-get update && apt-get upgrade -y
RUN pip install pipenv pip
COPY Pipfile ./
# some more common configuration...

文件 Dockerfile.dev:

FROM flaskapp:base
RUN pipenv install --system --skip-lock --dev
ENV FLASK_ENV development
ENV FLASK_DEBUG 1

文件 Dockerfile.prod:

FROM flaskapp:base
RUN pipenv install --system --skip-lock
ENV FLASK_ENV production

没有docker-compose,我可以这样构建:

# Building dev
docker build --tag flaskapp:base -f Dockerfile.base .
docker build --tag flaskapp:dev -f Dockerfile.dev .
# or building prod
docker build --tag flaskapp:base -f Dockerfile.base .
docker build --tag flaskapp:dev -f Dockerfile.dev .

根据compose-file doc,我可以指定一个Dockerfile进行构建。
# docker-compose.yml
version: '3'
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate

但是我如何在docker-compose.yml中指定2个Dockerfile(用于多阶段构建)?

2
多阶段构建是一个单独的Dockerfile。https://docs.docker.com/develop/develop-images/multistage-build/ - BMitch
我确实可以将通用的第一个阶段Docker文件复制/粘贴到其他所有Docker文件中,但我想避免重复代码(即保留2个Docker文件)。不确定是否支持这一点。 - nicolas
2个回答

163

正如评论中提到的那样,多阶段构建涉及单个Dockerfile执行多个阶段,而你所拥有的是一个共同的基础镜像。

你可以将它们转换为非传统的多阶段构建,语法如下(我说非传统,因为你不在层之间执行任何复制,而是仅使用from行从先前的阶段中选择):

FROM python:3.6 as base
RUN apt-get update && apt-get upgrade -y
RUN pip install pipenv pip
COPY Pipfile ./
# some more common configuration...

FROM base as dev
RUN pipenv install --system --skip-lock --dev
ENV FLASK_ENV development
ENV FLASK_DEBUG 1

FROM base as prod
RUN pipenv install --system --skip-lock
ENV FLASK_ENV production

然后,您可以使用--target语法或类似于以下内容的compose文件来构建一个阶段或另一个阶段:

# docker-compose.yml
version: '3.4'
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile
      target: prod

最大的缺点是当前构建引擎将通过每个阶段直到达到目标。构建缓存可以意味着这只是一个子秒的过程。而BuildKit将在18.09中从实验中推出,并且需要来自docker-compose的上游支持,它将更加智能,只运行必要的命令来构建所需的目标。

尽管如此,我认为这是把方形钉子放进圆孔的尝试。docker-compose开发人员鼓励用户不要在compose文件中进行构建,因为它不支持swarm模式。相反,推荐的解决方案是使用CI/CD构建服务器执行构建,并将这些镜像推送到注册表中。然后,您可以使用docker-composedocker stack deploy甚至一些k8s等效工具运行相同的compose文件,无需重新设计工作流程。


很不幸,我无法让它正常工作,似乎与此有关:https://github.com/docker/compose/issues/7262 - mikey
8
请注意 docker-compose 的版本。旧版本(例如“3”)不会识别“target”参数。 - Francisco Cardoso

4

您可以使用docker-compose文件的连接,同时包含指向现有dockerfile的dockerfile,并运行docker-compose -f docker-compose.yml -f docker-compose.prod.yml build


该命令用于构建生产环境中的Docker容器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接