用于多阶段Docker构建的工件缓存

时间:2018-10-08 08:09:21

标签: docker docker-compose

我有一个像这样的Dockerfile

# build-home
FROM node:10 AS build-home
WORKDIR /usr/src/app
COPY /home/package.json /home/yarn.lock /usr/src/app/
RUN yarn install
COPY ./home ./
RUN yarn build

# build-dashboard
FROM node:10 AS build-dashboard
WORKDIR /usr/src/app
COPY /dashboard/package.json /dashboard/yarn.lock /usr/src/app/
RUN yarn install
COPY ./dashboard ./
RUN yarn build

# run
FROM nginx
EXPOSE 80
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build-home /usr/src/app/dist /usr/share/nginx/html/home
COPY --from=build-dashboard /usr/src/app/dist /usr/share/nginx/html/dashboard

在这里构建两个react应用程序,然后将构建工件放入nginx中。为了提高构建性能,我需要在distbuild-home的构建阶段中缓存build-dashboard文件夹。 为此,我在volume

中创建了一个docker-compose.yml
...
  web:
    container_name: web
    build:
      context: ./web
    volumes:
      - ./web-build-cache:/usr/src/app
    ports:
      - 80:80
    depends_on:
      - api

我已停止在此阶段,因为我不知道如何在volume阶段先添加docker-compose创建的build-home,然后再添加volumebuild-dashboard。 也许我应该创建两个卷并将每个卷附加到每个构建阶段,但是该怎么做?

更新:

Initial build.

家庭应用程序:

  1. 安装模块:100.91s
  2. 构建应用:39.51秒

仪表板应用程序:

  1. 安装模块:100.91s
  2. 构建应用:50.38秒

总时间:

real    8m14.322s
user    0m0.560s
sys     0m0.373s

Second build(无需更改代码或依赖项):

家庭应用程序:

  1. 安装模块:使用缓存
  2. 构建应用程序:使用缓存

仪表板应用程序:

  1. 安装模块:使用缓存
  2. 构建应用程序:使用缓存

总时间:

real    0m2.933s
user    0m0.309s
sys     0m0.427s

Third build(第一个应用程序中的代码更改很小):

家庭应用程序:

  1. 安装模块:使用缓存
  2. 构建应用:50.04秒

仪表板应用程序:

  1. 安装模块:使用缓存
  2. 构建应用程序:使用缓存

总时间:

real    0m58.216s
user    0m0.340s
sys     0m0.445s

Initial build(不带Docker的家庭应用程序):89.69s

real    1m30.111s
user    2m6.148s
sys     2m17.094s

Second build(不带Docker的家庭应用程序),dist文件夹存在于磁盘上(没有代码或依赖关系更改):18.16s

real    0m18.594s
user    0m20.940s
sys     0m2.155s

Third build(不带Docker的家庭应用程序),dist文件夹存在于磁盘上(代码变化很小):20.44s

real    0m20.886s
user    0m22.472s
sys     0m2.607s

在docker-container中,该应用程序的第三次构建要长2倍。这表明,如果第一个构建的结果在磁盘上,则其他构建的完成速度更快。在docker容器中,由于没有dist文件夹,第一个之后的所有程序集都将与第一个一样长地执行。

2 个答案:

答案 0 :(得分:1)

您不能在映像构建期间使用卷,无论如何,Docker已经进行了您要的缓存。如果您将Dockerfile保持原样,并且不尝试在docker-compose.yml中的卷中添加代码,则应该按预期获得对已构建Javascript文件访问重建的缓存。

运行docker build时,Docker依次检查每个步骤。如果该步骤的输入未更改,该步骤本身未更改,并且添加的任何文件均未更改,则Docker将仅重用先前运行该步骤的结果。在Dockerfile中,如果仅更改nginx配置,它将跳过所有Javascript构建步骤,并重复使用上一次的结果。

(您已经拥有的另一项相关技术是分两步构建应用程序:首先复制名为依赖项的文件package.jsonyarn.lock之类,然后安装依赖项;然后复制并构建您的应用程序。由于“安装依赖项”步骤通常很耗时,并且依赖项相对不经常更改,因此您要鼓励Docker重用上一个构建的node_modules目录。)

答案 1 :(得分:0)

如果您使用的是多阶段构建,则说明docker cache存在问题。最终图像没有带有构建步骤的图层。通过一起使用--target--cache-from,您可以保存此层并在重建中重复使用它们。

您需要类似的东西

docker build \
  --target build-home \
  --cache-from build-home:latest \
  -t build-home:latest 


docker build \
  --target build-dashboard \
  --cache-from build-dashboard:latest \
  -t build-dashboard:latest 


docker build \
  --cache-from build-dashboard:latest \
  --cache-from build-home:latest \
  -t my-image:latest \

您可以在以下位置找到更多详细信息 https://andrewlock.net/caching-docker-layers-on-serverless-build-hosts-with-multi-stage-builds---target,-and---cache-from/