Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建

这篇具有很好参考价值的文章主要介绍了Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

old dockerfile

# syntax=docker/dockerfile:1

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

# syntax=docker/dockerfile:1 是 Dockerfile 的一个解析器指令,它用于声明构建时使用的 Dockerfile 语法版本。

如果你不指定这个指令,BuildKit 将使用它内置的 Dockerfile 前端版本。声明一个语法版本可以让你自动使用最新的 Dockerfile 版本,而无需升级 BuildKit 或 Docker Engine,甚至可以使用自定义的 Dockerfile 实现。

大多数用户会将这个解析器指令设置为 docker/dockerfile:1,这会让 BuildKit 在构建前拉取 Dockerfile 语法的最新稳定版本。

在你的 Dockerfile 中,# syntax=docker/dockerfile:1 指令告诉 Docker 使用最新稳定版本的 Dockerfile 语法来解析和构建这个 Dockerfile。

note 1 :

 EXPOSE 3000  和 docker run -dp 127.0.0.1:3001:3000 getting-started-2  的关联

Dockerfile 中的 EXPOSE 指令只是声明了应用程序在容器内部监听的端口,它并不会自动映射这个端口到宿主机。如果你想让应用程序可以从宿主机访问,你需要在启动容器时使用 -p 或 --publish 参数来映射端口。

容器启动时映射的端口并不一定要和 EXPOSE 指令声明的端口相同。例如,你的 Dockerfile 中有 EXPOSE 3000,但你可以在启动容器时使用 -p xxxx:3000 来将容器的 3000 端口映射到宿主机的 xxxx 端口。

但是,如果你的应用程序在容器内部监听的端口和 EXPOSE 指令声明的端口不同,那么 EXPOSE 指令就没有意义了。因为 EXPOSE 指令的主要目的就是告诉使用这个镜像的人,应用程序在哪个端口提供服务。镜像就是一个模版,可以同时生成多个容器实例服务

这样就相当于你可以将启动多个主机端口 映射同样的实例服务

3001 -> 3000    3002 -> 3000 

 note 2 : caching of the dependencies

watching the old dockerFile command line 。 at some circumstance , we will recreated image when update code ,but it will download  dependencies again 。 that's  terrible , please following to optimize the dockerFile 。

# syntax=docker/dockerfile:1

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

原因 :

Once a layer changes, all downstream layers have to be recreated as well

一旦一个图层改变,所有的下游层都会重新构建 

Docker 使用一种称为层(layer)的概念来构建和存储镜像。每个 Dockerfile 指令都会创建一个新的层,并在此基础上进行下一步操作。这些层是只读的,但可以被后续的层修改。

Docker 会尽可能地使用缓存来加速镜像构建过程。当 Docker 构建镜像时,它会查看每个指令和之前构建的镜像层。如果 Docker 发现一个指令和一个已经缓存的层完全匹配,那么它就会使用这个缓存的层,而不是重新执行指令。

例如,如果你的 Dockerfile 的前两个指令是 FROM node:18-alpine 和 WORKDIR /app,并且你之前已经构建过一个使用相同指令的镜像,那么 Docker 就会使用这两个缓存的层。

但是,如果一个指令的上下文(例如,被复制的文件)发生了改变,那么 Docker 就不能使用缓存,而必须重新执行指令。这就是为什么在 Dockerfile 中,我们通常先复制 package.json 和 yarn.lock,然后运行 yarn install,最后再复制其余的文件。这样,即使源代码发生改变,只要依赖没有改变,yarn install 的步骤就可以使用缓存,从而加速构建过程。

Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建,docker,docker,容器

Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建,docker,docker,容器 

如果指令不变,那么就会用缓存的老的 layer 

修改  /app 为  /gyk 后 ,/app 后的所有layer 全部失效。

 Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建,docker,docker,容器

 所以:

Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建,docker,docker,容器

Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建,docker,docker,容器

重新 build

Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建,docker,docker,容器 

note3   .dockerignore

 文章来源地址https://www.toymoban.com/news/detail-832417.html

.dockerignore 文件用于指定哪些文件或目录应该被 Docker 忽略,不应该被复制到镜像中。这与 .gitignore 文件的作用类似,但是用于 Docker。

在你提供的例子中,.dockerignore 文件的内容是:

node_modules

这意味着 node_modules 目录不会被复制到 Docker 镜像中。这是因为 node_modules 目录通常包含大量的文件,而且这些文件在构建过程中会被 yarn install 或 npm install 命令重新创建。因此,将 node_modules 目录复制到镜像中不仅会浪费空间,还可能导致问题,因为它可能会覆盖由 RUN 步骤创建的文件。

note 4  muti-stage builds 多阶段构建

多阶段构建(Multi-stage builds)是 Docker 提供的一种强大的工具,它允许你在一个 Dockerfile 中定义多个阶段来构建镜像。这有几个优点:

  1. 分离构建时依赖和运行时依赖:在构建阶段,你可能需要一些额外的工具和库来编译你的应用程序(例如,编译器,构建工具等)。但是在运行阶段,这些工具和库可能就不再需要了。通过使用多阶段构建,你可以在一个阶段安装和使用这些工具,然后在另一个阶段只复制你的应用程序和它需要的运行时依赖。

  2. 减少总体镜像大小:由于你只复制了应用程序和它的运行时依赖,所以最终的镜像会比包含所有构建工具和库的镜像小得多。这可以减少存储和网络传输的开销,使你的应用程序更快地启动,并且减少了安全风险,因为镜像中包含的组件更少。

下面是一个简单的多阶段构建的例子:

 

# 第一阶段:构建应用程序
FROM node:18-alpine AS build
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install
COPY . .
RUN yarn build

# 第二阶段:运行应用程序
FROM node:18-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY package.json yarn.lock ./
RUN yarn install --production
CMD ["node", "dist/index.js"]

在这个例子中,第一阶段使用 node:18-alpine 镜像来安装所有依赖并构建应用程序。然后,第二阶段使用同样的 node:18-alpine 镜像,但只复制了构建的应用程序和运行时依赖,并安装了这些运行时依赖。这样,最终的镜像就只包含了运行应用程序所需要的东西。

 

在 Dockerfile 中,WORKDIR /app 指令设置了工作目录为 /app。这意味着后续的指令(如 COPYRUN 等)都会在这个目录下执行。

在你提供的 Dockerfile 的第二阶段中,COPY --from=build /app/dist ./dist 这行指令的作用是从构建阶段(被命名为 build)的镜像中复制 /app/dist 目录到当前工作目录下的 dist 目录。

这里的 ./dist 是相对于当前的工作目录 /app 的,所以 ./dist 实际上就是 /app/dist

所以,这行指令的效果是将构建阶段生成的应用程序(位于 /app/dist)复制到最终镜像的 /app/dist 目录下。

然后,CMD ["node", "dist/index.js"] 这行指令在容器启动时会运行 /app/dist/index.js,也就是你刚刚复制过来的应用程序

React example

When building React applications, you need a Node environment to compile the JS code (typically JSX), SASS stylesheets, and more into static HTML, JS, and CSS. If you aren't doing server-side rendering, you don't even need a Node environment for your production build. You can ship the static resources in a static nginx container. 

# syntax=docker/dockerfile:1
FROM node:18 AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build

FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html

 

example:

# syntax=docker/dockerfile:1

FROM node:18-alpine AS build
WORKDIR /gyk
COPY package.json yarn.lock ./ 
# 依赖文件不变,不会重新下载依赖,一旦变化,后面layer失效,重新下载依赖
RUN yarn install --production
COPY . .
# 如只改动源代码,则之后执行 COPY .. 后的 指令
CMD ["node", "server/test.js"]
EXPOSE 3044


FROM nginx:alpine
COPY --from=build /gyk/. /usr/share/nginx/html
#/gyk/* 表示 gyk 目录下的所有文件和子目录,如果你想使用 . 来表示 gyk 目录下的所有内容,你可以直接写成 /gyk/.。这样,Docker 就会复制 gyk 目录下的所有文件和子目录,在 Dockerfile 中,COPY 指令不支持 ** 这种形式的通配符。** 通常在 shell 脚本或某些编程语言中用于匹配任意多级的子目录,但在 Dockerfile 的 COPY 指令中,这种语法是不被支持的

优化后 43.37 M 

Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建,docker,docker,容器

在 Docker 的多阶段构建中,每个阶段都必须以 FROM 指令开始,这是 Dockerfile 语法的要求。FROM 指令用于指定基础镜像,如果你不指定基础镜像,Docker 就不知道如何创建新的镜像。

如果你的第二阶段不需要任何特定的镜像,你可以使用一个非常小的基础镜像,如 scratchscratch 是一个特殊的 Docker 镜像,它是空的,不包含任何文件。这通常用于创建非常小的镜像,只包含你的应用程序和它的运行时依赖。

 

note 5 :node:18-alpine 和 nginx:alpine 的 alpine 是什么意思

alpine 是一个轻量级的 Linux 发行版,它的设计目标是尽可能地减小体积。alpine 镜像通常只有 5MB 左右,相比其他的 Linux 发行版,如 Ubuntu 或 Debian,它的体积小很多。

在 Docker 中,alpine 通常用作基础镜像,用于构建更小的 Docker 镜像。例如,node:18-alpine 是一个包含 Node.js 18 版本和 Alpine Linux 的 Docker 镜像,nginx:alpine 是一个包含 Nginx 和 Alpine Linux 的 Docker 镜像。

使用 alpine 作为基础镜像的好处是可以减小最终 Docker 镜像的体积,这可以减少存储和网络传输的开销,使你的应用程序更快地启动,并且减少了安全风险,因为镜像中包含的组件更少

 

 

到了这里,关于Docker chapter 6 镜像构建优化 - 依赖缓存 与 多阶段构建的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot gradle kotlin 多模块(或微服务)统一依赖及版本管理和构建不同环境打包task,docker镜像构建task

    在maven里可以在pom.xml中统一定义项目依赖,依赖版本,插件,多环境构建,子模块;定义packaging 为pom类型,各子模块按需引入,并且指定环境profiles构建。 在gradle中也可以实现依赖统一管理,各模块按需引入,区分环境的构建任务。 先上效果图 统一定义依赖,依赖版本,插

    2024年02月04日
    浏览(37)
  • 不依赖docker客户端导出docker镜像

    此项目已经开源发布至GitHub https://github.com/DockerContainerService/image-save 1、支持linux、windows的amd64、arm64架构机器 2、支持不安装docker客户端情况下导出镜像tar包 3、支持公开镜像仓库/私有镜像仓库 4、支持多线程加速下载镜像 5、支持使用自定义镜像源加速下载镜像 大家在使用过

    2023年04月08日
    浏览(42)
  • Docker 镜像的缓存特性

    Author :rab 首先我们要清楚,Docker 的镜像结构是分层的,镜像本身是只读的(不管任何一层), 当我们基于某镜像运行一个容器时,会有一个新的可写层被加载到镜像的顶部, 我们通常将这一层称之为 容器层 , 容器层 之下的都称之为 镜像层 。我们所有对容器的增删操作

    2024年02月07日
    浏览(36)
  • docker清缓存、日志、无用镜像

    查看docker各类型文件占用情况 该命令列出了 docker 使用磁盘的 4 种类型: Images: 所有镜像占用的空间,包括拉取的镜像、本地构建的镜像 Containers: 运行中的容器所占用的空间(没运行就不占空间),其实就是每个容器读写层的空间 Local Volumes: 本地数据卷的空间 Build Cache: 镜像

    2024年02月06日
    浏览(38)
  • Docker 构建镜像(docker build)

    docker build 命令用于从Dockerfile构建镜像。 典型用法 选项 -t 给镜像加一个Tag ImageName 给镜像起的名称 TagName 给镜像的Tag名 Dir Dockerfile所在目录 执行结果 根据目录下的 Dockerfile 文件构建镜像 例子 chinaskill-redis 是镜像名 v1.1 是 tag 标签 . 表示当前目录,即Dockerfile所在目录 查看镜

    2024年02月11日
    浏览(45)
  • Docker构建缓存

    Docker镜像是由一层一层的文件系统组成,UnionFS将这些镜像层堆叠在一起 镜像层是只读的,构建完成后就不能更改了,即使在新的镜像层修改或删除了某些文件,也不会影响之前的镜像层内容 用Dockerfile构建镜像时,每个指令都会创建一个新的镜像层,镜像层会被缓存和复用

    2024年02月03日
    浏览(35)
  • [Docker精进篇] Docker镜像构建和实践 (三)

    前言: Docker镜像构建的作用是将应用程序及其依赖打包到一个可移植、自包含的镜像中,以便在不同环境中快速、可靠地部署和运行应用程序。 这篇文章是我的笔记,旨在带您快速入门上手docker,更加深入学习docker知识 做事三步走:是什么,为什么,怎么办 我们一步一步来

    2024年02月12日
    浏览(48)
  • Docker 深度清除镜像缓存 (overlay2)

    Docker 深度清除镜像缓存 (overlay2) 一般情况下,运维清理镜像是通过命令 docker rm i 删除镜像的。但是这条命令不会删除docker build命令产生的缓存文件。 这个时候需要使用 docker system 的系列命令来做相关处理。 输出: 参数: -a 删除全部未使用的镜像 -f 或 --force 不经过确认

    2024年02月08日
    浏览(41)
  • docker入门(Linux环境下安装Docker,Docker构建镜像)

    1.1 官方解释 Docker is the world’s leading software containerization platform。 Docker公司开发,开源,托管在github跨平台, 支持Windows、Macos、Linux。 1.2 抽象解释 2.1 集装箱-类似一个容器 没有集装箱之前运输货物,东西零散容易丢失,有了集装箱之后货物不容易丢失,我们可以把货物想象成程

    2024年02月15日
    浏览(49)
  • Docker[1] Docke环境是什么 安装部署 依赖兼容解决 简介 Centos安装Docker 配置镜像加速 启动Docker

    1.1.什么是Docker 微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来了很大的麻烦。 ● 分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。 ● 在数百上千台服务中重复部署,环境不一定一致,会遇到各种问题 1.1.1.应用部署的环境问题

    2024年04月10日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包