• 使用构建缓存优化 Docker 镜像构建


    使用构建缓存优化 Docker 镜像构建

    目录

    • 实践
    • 构建应用程序
    • 额外资源
    • 后续步骤

    假设一个简单的nodejs程序的 Dockerfile如下:

    FROM node:20-alpine
    WORKDIR /app
    COPY . .
    RUN yarn install --production
    CMD ["node", "./src/index.js"]
    

    当你运行 docker build 命令来创建新镜像时,Docker 会按指定顺序执行 Dockerfile 中的每条指令,为每个命令创建一个层。对于每条指令,Docker 会检查是否可以重用之前构建中的指令。如果发现之前已经执行过类似的指令,Docker 就不需要重新执行,而是使用缓存的结果。这样,你的构建过程会变得更快、更高效,节省宝贵的时间和资源。

    有效使用构建缓存可以通过重用之前构建的结果并跳过不必要的工作来实现更快的构建。为了最大化缓存的使用并避免资源密集型和耗时的重建,理解缓存失效的工作原理非常重要。以下是一些可能导致缓存失效的情况:

    • RUN 指令的任何更改 会使该层失效。如果 Dockerfile 中的 RUN 命令有任何修改,Docker 会检测到变化并使构建缓存失效。
    • 使用 COPYADD 指令复制到镜像中的文件的任何更改Docker 会监视项目目录中的任何更改,无论是内容的变化还是属性(如权限)的变化,Docker 都会将这些修改视为触发缓存失效的原因。
    • 一旦某一层失效,所有后续层也会失效。如果由于更改导致任何之前的层(包括基础镜像或中间层)失效,Docker 会确保依赖于它的后续层也失效。这保持了构建过程的同步,防止不一致。

    在编写或编辑 Dockerfile 时,注意避免不必要的缓存失效,以确保构建尽可能快速和高效地进行。

    实践

    在本指南中,你将学习如何有效使用 Docker 构建缓存来优化 Node.js 应用程序的构建过程。

    构建应用程序

    下载并安装 Docker Desktop

    打开终端并克隆这个示例应用程序:

    git clone https://github.com/dockersamples/todo-list-app
    

    进入 todo-list-app 目录:

    cd todo-list-app
    

    在这个目录中,你会找到名为 Dockerfile 的文件,内容如下:

    FROM node:20-alpine
    WORKDIR /app
    COPY . .
    RUN yarn install --production
    EXPOSE 3000
    CMD ["node", "./src/index.js"]
    

    执行以下命令来构建 Docker 镜像:

    docker build .
    

    构建过程如下所示:

    [+] Building 20.0s (10/10) FINISHED
    

    第一行表示整个构建过程花费了 20.0 秒。第一次构建可能会花费一些时间,因为需要安装依赖项。

    不做任何更改进行重建

    现在,在不更改源代码或 Dockerfile 的情况下重新运行 docker build 命令:

    docker build .
    

    后续构建由于缓存机制而变得更快,只要命令和上下文保持不变。Docker 会缓存构建过程中生成的中间层。当你在不更改 Dockerfile 或源代码的情况下重新构建镜像时,Docker 可以重用缓存的层,从而显著加快构建过程。

    [+] Building 1.0s (9/9) FINISHED
    

    后续构建仅在 1.0 秒内完成,通过利用缓存层,无需重复耗时的步骤,如安装依赖项。

    步骤描述第一次运行时间第二次运行时间
    1Dockerfile 加载构建定义0.0 秒0.0 秒
    2加载 docker.io/library/node:20-alpine 的元数据2.7 秒0.9 秒
    3加载 .dockerignore0.0 秒0.0 秒
    4加载构建上下文 (上下文大小: 4.60MB)0.1 秒0.0 秒
    5设置工作目录 (WORKDIR)0.1 秒0.0 秒
    6将本地代码复制到容器中0.0 秒0.0 秒
    7运行 yarn install --production10.0 秒0.0 秒
    8导出层2.2 秒0.0 秒
    9导出最终镜像3.0 秒0.0 秒

    优化 Dockerfile

    为了避免每次构建都重新安装相同的依赖项,可以重新组织 Dockerfile 以保持依赖项缓存的有效性,除非确实需要使其失效。对于基于 Node 的应用程序,依赖项定义在 package.json 文件中。你可以在该文件更改时重新安装依赖项,但如果文件未更改,则使用缓存的依赖项。因此,首先复制 package.json 文件,然后安装依赖项,最后复制其他所有内容。这样,只有在 package.json 文件更改时才需要重新创建 yarn 依赖项。

    更新 Dockerfile 以首先复制 package.json 文件,安装依赖项,然后复制其他所有内容:

    FROM node:20-alpine
    WORKDIR /app
    COPY package.json yarn.lock ./
    RUN yarn install --production 
    COPY . . 
    EXPOSE 3000
    CMD ["node", "src/index.js"]
    

    在与 Dockerfile 相同的文件夹中创建一个名为 .dockerignore 的文件,内容如下:

    node_modules
    

    构建新镜像:

    docker build .
    

    输出如下:

    [+] Building 16.1s (10/10) FINISHED
    => [internal] load build definition from Dockerfile                                               0.0s
    => => transferring dockerfile: 175B                                                               0.0s
    => [internal] load .dockerignore                                                                  0.0s
    => => transferring context: 2B                                                                    0.0s
    => [internal] load metadata for docker.io/library/node:21-alpine                                  0.0s
    => [internal] load build context                                                                  0.8s
    => => transferring context: 53.37MB                                                               0.8s
    => [1/5] FROM docker.io/library/node:21-alpine                                                    0.0s
    => CACHED [2/5] WORKDIR /app                                                                      0.0s
    => [3/5] COPY package.json yarn.lock ./                                                           0.2s
    => [4/5] RUN yarn install --production                                                           14.0s
    => [5/5] COPY . .                                                                                 0.5s
    => exporting to image                                                                             0.6s
    => => exporting layers                                                                            0.6s
    => => writing image     
    sha256:d6f819013566c54c50124ed94d5e66c452325327217f4f04399b45f94e37d25        0.0s
    => => naming to docker.io/library/node-app:2.0                                                 0.0s
    

    现在,修改 src/static/index.html 文件(例如将标题更改为 “The Awesome Todo App”)。

    构建 Docker 镜像。此时,你的输出应有所不同:

    docker build -t node-app:3.0 .
    

    输出如下:

    [+] Building 1.2s (10/10) FINISHED 
    => [internal] load build definition from Dockerfile                                               0.0s
    => => transferring dockerfile: 37B                                                                0.0s
    => [internal] load .dockerignore                                                                  0.0s
    => => transferring context: 2B                                                                    0.0s
    => [internal] load metadata for docker.io/library/node:21-alpine                                  0.0s 
    => [internal] load build context                                                                  0.2s
    => => transferring context: 450.43kB                                                              0.2s
    => [1/5] FROM docker.io/library/node:21-alpine                                                    0.0s
    => CACHED [2/5] WORKDIR /app                                                                      0.0s
    => CACHED [3/5] COPY package.json yarn.lock ./                                                    0.0s
    => CACHED [4/5] RUN yarn
    
     install --production                                                     0.0s
    => [5/5] COPY . .                                                                                 0.5s 
    => exporting to image                                                                             0.3s
    => => exporting layers                                                                            0.3s
    => => writing image     
    sha256:91790c87bcb096a83c2bd4eb512bc8b134c757cda0bdee4038187f98148e2eda       0.0s
    => => naming to docker.io/library/node-app:3.0                                                 0.0s
    

    首先,你会注意到构建速度快了很多。你会看到多个步骤使用了之前缓存的层。这是个好消息;你正在使用构建缓存。推送和拉取此镜像及其更新也会快得多。

    通过遵循这些优化技术,你可以加快 Docker 构建速度,提高开发效率,缩短迭代周期,提高开发生产力。

  • 相关阅读:
    R语言从列表中移除元素、删除列表中的指定元素(单个元素或者多个元素)
    Spring概述
    【六袆 - MySQL】SQL优化;Explain SQL执行计划分析;
    Springboot萌宠社交分享系统的设计与实现hfdwz计算机毕业设计-课程设计-期末作业-毕设程序代做
    用匠心创造可期未来!与广州流辰信息科技一起携手创佳绩!
    215 数组中的第K个最大元素
    Pandas数据的导入与导出
    Vue 源码解读(9)—— 编译器 之 优化
    tail -f 、tail -F、tailf的区别
    ubuntu云服务器怎么做好初始安全设置
  • 原文地址:https://blog.csdn.net/qcpm1983/article/details/139906911