多阶段docker映像是否具有相同的图层?

时间:2018-11-13 07:45:18

标签: docker dockerfile

假设我决定进行以下多阶段构建:

FROM node:8.6-alpine AS build1
#some other commands
FROM node:8.5-alpine AS build2
# yet another commands

在build1和build2之间肯定有一些相同的层。码头工人会复制图层,还是以某种方式附加引用已构建的图层?

2 个答案:

答案 0 :(得分:1)

接下来是在新机器上构建dockerfile的结果:

# docker build -t test:1 .
Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM node:8.6-alpine AS build1
8.6-alpine: Pulling from library/node
88286f41530e: Pull complete
d0e8a23136b3: Pull complete
5ad5b12a980e: Pull complete
Digest: sha256:60cd58a7a2bd9fec161f53f8886e451f92db06b91f4f72d9188eeea040d195eb
Status: Downloaded newer image for node:8.6-alpine
 ---> b7e15c83cdaf
Step 2/2 : FROM node:8.5-alpine AS build2
8.5-alpine: Pulling from library/node
88286f41530e: Already exists
aa0be12c5610: Pull complete
719d346e6de2: Pull complete
Digest: sha256:945cf56668d3e58a3b045291564963ccde29a68da9c1483e19d8a0b06749db06
Status: Downloaded newer image for node:8.5-alpine
 ---> 7a779c246a41
Successfully built 7a779c246a41
Successfully tagged test:1

从输出中,您可以看到图像ID 88286f41530e被重新用作Already exists

docker images输出:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
node                8.6-alpine          b7e15c83cdaf        13 months ago       67.2MB
node                8.5-alpine          7a779c246a41        14 months ago       67MB

因此,多重构建中第一阶段的基础映像也保留在缓存中。

从这个post

  

通常,从Docker v1.10开始,图像和图层不再是同义词。   取而代之的是,映像直接引用一层或多层,这些层最终构成派生容器的文件系统。

因此,当某些图像被重用时,这些图层肯定会被重用。

当然,这取决于您在multibuild中使用的基础映像,它们需要重用。

无论如何,我认为与传统构建相比,multibuild只是增加了一些技巧,但是层重用机制是相同的。

答案 1 :(得分:1)

我相信可以使用普通的docker build层缓存,但是还有其他更好的答案。

FROM ubuntu:18.04 AS first
RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive \
    apt-get install -y --no-install-recommends \
      python3
RUN echo first

FROM ubuntu:18.04 AS second
RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive \
    apt-get install -y --no-install-recommends \
      python3
RUN echo second

规则是,您必须从相同的基本镜像开始(在您的示例中没有共享),并且必须重复相同的精确命令(或COPY 完全相同的文件内容);一旦您偏离此路径,就不会共享任何内容,包括以后的所有相同命令。

您可以use the AS alias in later FROM directives,因此,如果您确实要共享某个基础层,最好进行显式地操作

FROM ubuntu:18.04 AS base
RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive \
    apt-get install -y --no-install-recommends \
      python3

FROM base AS first
RUN echo first

FROM base AS second
RUN echo second

在多阶段构建中更常见的情况是,它具有非常不同的“构建”和“运行时”映像,因此这通常不适用。

FROM golang:1.11 AS build
WORKDIR /go/src/github.com/me/myapp
COPY ./ ./
RUN go install .

FROM alpine
COPY --from=build /go/bin/myapp /usr/bin
CMD ["myapp"]