如何在Dockerfile中使用另一个Dockerfile作为FROM?

20
我有一个应用程序,其中有两个 Dockerfile 文件,分别为 Dockerfile.foo 和 Dockerfile.bar,它们应该为 docker-compose.yml 的两个不同服务生成两个不同的镜像。
例如,可能如下所示:
# ...
services:
  service1:
    build:
      context: .
      dockerfile: Dockerfile.foo
  service1:
    build:
      context: .
      dockerfile: Dockerfile.bar
# ...

但是Dockerfile.{foo,bar}的前半部分相同,而它们的左侧部分不同。

如何通过使.{foo,bar}从基础Dockerfile.common扩展来避免不必要的重复构建和维护麻烦?换句话说,在docker-compose.yml中是否可能实现类似于FROM Dockerfile.common的内容存档?


更新:

我希望使用docker-compose自动化构建过程,而无需手动运行(或使用单独的build.sh):

  1. 首先运行docker build -f Dockerfile.common -t common .
  2. 然后运行docker build -f Dockerfile.foo -t foo . && docker build -f Dockerfile.bar -t bar .,以便Dockerfile.{foo,bar}可以正确引用common镜像。

你的最后一句话中是指在 Dockerfile 中吗? - samthegolden
https://stackoverflow.com/questions/59714123/docker-compose-cascade-build-images 是一个非常相似的问题(我的答案在那里更多地讨论了工作流程)。 - David Maze
创建一个 Docker 文件,用于基础镜像,这些镜像对两个项目都是通用的。将其余两个 Docker 文件裁剪为特定构建,并将所有三个文件添加到 docker-compose.yml 中。 - Sahil Sharma
@samthegolden 对不起,我的表达能力不太好。我已经更新了问题描述。 - Dummmy
@Dummmy请看下面我的答案,我猜它可以做你想要的。 - samthegolden
显示剩余2条评论
3个回答

15

如果你想避免使用不必要的中间标签,并且你使用的是Docker 20.10+,你也可以这样做:

# syntax = edrevo/dockerfile-plus

INCLUDE+ Dockerfile.common

# The rest of Dockerfile.foo would go after the INCLUDE+ instruction

RUN echo "Hello World"

INCLUDE+ 指令通过 Dockerfile 的第一行进行导入。您可以在https://github.com/edrevo/dockerfile-plus了解有关 dockerfile-plus 的更多信息。


如果您已经使用了类似于官方# syntax = docker/dockerfile:1.4的扩展语法,我不知道如何同时使用两者。 - N1ngu

5

我只是偶尔涉猎 Docker,所以不确定是否有更好和更符合 Docker 风格的方法来处理这个问题,但我使用一个好用的老式 makefile。

makefile

common:
    docker build -f Dockerfile.common -t common .

foo: common
    docker build -f Dockerfile.foo -t foo .

bar: common
    docker build -f Dockerfile.bar -t bar .

build: foo bar
    echo "Done!"

然后运行:

make build

我不知道Docker Compose是否可以更好、更优雅地完成这个任务,但是这个方法适用于我,而且不需要学习和安装新工具。 ;)

2
不,docker-compose只是用于编排(在某种程度上),因此您可以使用它同时运行容器。这不是您想要的。无论如何,我喜欢您建议的Makefile方式! - void

0

FROM用于拉取基础镜像以便进行操作。当然,该镜像在某处有一个Dockerfile,但在使用该镜像的新Dockerfile中并不重要。

因此,创建一个主要的Dockerfile_common,并从中生成一个带有基本内容的图像generated_image_with_Dockerfile_common(使用docker build),以供其他图像使用所需的基本内容。

然后,在您的Dockerfile_fooDockerfile_bar中,使用FROM generated_image_with_Dockerfile_common并在其中添加您所需的内容。


1
你读了这个问题吗?这正是需要解决的不良情况。 - Daniel Braun

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