在docker中构建软件 - 在`build`或`run`时间?

时间:2018-05-01 19:30:22

标签: docker

我目前正在使用docker创建一个可重现的构建环境(用于构建Android ROM)。现在我想运行多个构建,每个构建都有轻微的变化。每个构建都包含几个步骤,例如

  1. 构建Linux内核
  2. 构建Android
  3. 包含自定义应用
  4. 包装图片
  5. 如果两个版本仅在步骤3中有所不同,那么能够重复使用前两个步骤会很棒。

    我在考虑两个选择:

    • 输入我的docker容器,运行构建,并在每一步保存构建工件。稍后检查我是否可以重复使用它们。这需要相当多的编码和手动管理构建工件。
    • 滥用docker build。为每个配置创建一个dockerfile,每个步骤都有一个RUN命令。我想这会让我使用docker的缓存 - 如果两个版本在步骤3只有不同,docker将重用一个包含步骤1和2的图层。我只会"运行"我建立的容器,用于复制完成的ROM。

    是否有最好的"或规范的方式来做到这一点?以这种方式使用docker build有什么不利之处吗?

2 个答案:

答案 0 :(得分:2)

您可以构建名为" base image"的内容,然后将其推送到docker注册表。然后,对于该图片的两个分支,您使用FROM关键字。但是,您可以使用基本图像来代替使用FROM ubuntu:latest这样的基本图像:

使用基本图像:

FROM repo/base-image:tag

所以你的基地可能是:

FROM ubuntu:14.04

# Step 1
COPY /tmp /tmp

# Step 2
ADD /src /src

你建立并推动:

docker build -t repo/base-image .
docker push repo/base-image

然后,在你的另外两个Dockerfiles中......

Dockerfile1

FROM repo/base-image:tag

# Step 3 specific to this Dockerfile1
ADD /something /somewhere

# Do different things
EXPOSE 443

Dockerfile2

FROM repo/base-image:tag

# Step 3 specific to this Dockerfile2
ADD /something-else /somewhere-else

# Do different things
EXPOSE 80

这样他们共有前两层,而第三层只有不同。 docker文件中的行称为层。有点像穿越树。您拥有的线越多,您拥有的层/级别就越多。但是,基于FROM repo/img:tag行,它会告诉您从哪里继承所有以前的图层。

答案 1 :(得分:1)

第二个选项(依赖Dockerfile s + docker build)绝对是可行的方法。

事实上,正如您在问题中已经提到的那样,这将使Docker能够使用缓存。

另外,我记得即使只有一个Dockerfile涉及单个FROM ...命令,Docker的缓存也已经处于活动状态。这就是为什么在Dockerfile中,命令的顺序很重要(最好事先运行在每次构建时不太可能改变的命令,然后是可能的命令 - 例如自定义的编译应用程序)。

您可以按照@ JabariDash的答案中详述的步骤操作,但如果您注意到中间图像repo/some-image仅使用一次(通过另一个FROM repo/some-image中的命令Dockerfile),请注意,您可以避免在单独的repo/some-image中定义此Dockerfile:事实上,您可以将多个FROM ...命令放在同一个Dockerfile中,并依赖于所谓的>= 17.05 3}} Docker {{1}}的功能。