百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Docker 镜像构建的最佳做法 docker镜像操作

lipiwang 2024-10-15 18:38 14 浏览 0 评论

一、镜像分层


使用docker image history命令,可以看到用于在镜像中创建每个层的命令。


1、 使用docker image history命令查看创建的入门镜像中的层。


docker image history getting-started


您应该得到如下所示的输出:


IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
a78a40cbf866        18 seconds ago      /bin/sh -c #(nop)  CMD ["node" "src/index.ja|    0B                  
f1d1808565d6        19 seconds ago      /bin/sh -c yarn install --production            85.4MB              
a2c054d14948        36 seconds ago      /bin/sh -c #(nop) COPY dir:5dc710ad87c789593a|   198kB               
9577ae713121        37 seconds ago      /bin/sh -c #(nop) WORKDIR /app                  0B                  
b95baba1cfdb        13 days ago         /bin/sh -c #(nop)  CMD ["node"]                 0B                  
<missing>           13 days ago         /bin/sh -c #(nop)  ENTRYPOINT ["docker-entrya|   0B                  
<missing>           13 days ago         /bin/sh -c #(nop) COPY file:238737301d473041a|   116B                
<missing>           13 days ago         /bin/sh -c apk add --no-cache --virtual .buia|   5.35MB              
<missing>           13 days ago         /bin/sh -c #(nop)  ENV YARN_VERSION=1.21.1      0B                  
<missing>           13 days ago         /bin/sh -c addgroup -g 1000 node     && addua|   74.3MB              
<missing>           13 days ago         /bin/sh -c #(nop)  ENV NODE_VERSION=12.14.1     0B                  
<missing>           13 days ago         /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B                  
<missing>           13 days ago         /bin/sh -c #(nop) ADD file:e69d441d729412d24a|   5.59MB   


每条线表示镜像中的一个层。此处的显示在底部显示底部,最新层在顶部。使用此选项,您还可以快速查看每个层的大小,帮助诊断大型镜像。


2、您将注意到有几行被截断。如果添加--no trunc标志,则将获得完整的输出。


docker image history --no-trunc getting-started


二、图层缓存


现在您已经看到了分层的作用,有一个重要的教训需要学习,以帮助减少容器映像的构建时间。一旦层更改,也必须重新创建所有下游层。
请查看您为入门应用程序创建的以下Dockerfile。


# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]


回到镜像历史记录输出,您会看到Dockerfile中的每个命令都成为镜像中的新层。您可能记得,当您对镜像进行更改时,必须重新安装纱线依赖项。每次构建时都围绕相同的依赖项进行交付是没有多大意义的。
要修复它,您需要重新构造Dockerfile,以帮助支持依赖项的缓存。对于基于节点的应用程序,这些依赖项在package.json文件中定义。您可以首先只复制该文件,安装依赖项,然后复制其他所有文件。然后,只有在package.json发生更改时,才重新创建纱线依赖项。


1、更新Dockerfile以首先在package.json中复制,安装依赖项,然后复制中的所有其他内容。


# syntax=docker/dockerfile:1
FROM node:18-alpine
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --production
COPY . .
CMD ["node", "src/index.js"]


2、在与Dockerfile相同的文件夹中创建一个名为.dockerignore的文件,其中包含以下内容。
node_modules
.dockerignore文件是一种简单的方法,可以选择性地仅复制与映像相关的文件。你可以在这里阅读更多关于这方面的内容。在这种情况下,应该在第二个COPY步骤中省略node_modules文件夹,因为否则,它可能会覆盖由RUN步骤中的命令创建的文件。
3、使用docker Build构建新镜像。


docker build -t getting-started .


您应该看到如下输出。


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


4、现在,对src/static/index.html文件进行更改。例如,将<title>更改为“the Awesome Todo App”。
5、现在使用Docker Build-t getting started构建Docker镜像。再次。这一次,您的输出应该看起来有点不同。


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


首先,您应该注意到构建速度快得多。并且,您将看到几个步骤正在使用以前缓存的层。推拉此镜像以及对其的更新也将快得多。


三、多阶段构建


多阶段构建是一个非常强大的工具,可以帮助使用多个阶段来创建镜像。它们有几个优点:


  • 将构建时依赖项与运行时依赖项分离
  • 通过仅传送应用程序运行所需的内容来减少总体镜像大小


1、Maven/Tomcat示例


在构建基于Java的应用程序时,需要JDK将源代码编译为Java字节码。然而,生产中不需要JDK。此外,您可能正在使用Maven或Gradle等工具来帮助构建应用程序。在最终的镜像中也不需要这些。多阶段构建帮助。


# syntax=docker/dockerfile:1
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package

FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps 


在这个例子中,您使用一个阶段(称为构建)来使用Maven执行实际的Java构建。在第二个阶段(从FROM tomcat开始),从构建阶段复制文件。最终镜像只是正在创建的最后一个阶段,可以使用--target标志覆盖它。


2、React示例


在构建React应用程序时,需要一个Node环境来将JS代码(通常是JSX)、SASS样式表等编译为静态HTML、JS和CSS。如果不进行服务器端渲染,则生产构建甚至不需要节点环境。您可以在静态nginx容器中运送静态资源。


# 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


在前面的Dockerfile示例中,它使用node:18镜像执行构建(最大化层缓存),然后将输出复制到nginx容器中。

Doker 技术人的数码品牌!!!

文章下方有交流学习区!一起学习进步!也可以前往官网,加入官方微信交流群!!!你的支持和鼓励是我创作的动力???

官网:Doker 多克; 官方旗舰店首页-Doker 多克创新官方店-淘宝网 全品大优惠优惠!!!

相关推荐

Go语言图书管理RESTful API开发实战

Go(Golang)是最近流行起来,且相对较新的编程语言。它小而稳定,使用和学习简单,速度快,经过编译(原生代码),并大量用于云工具和服务(Docker、Kubernetes...)。考虑到它所带来的...

轻松搞定Golang 中的内存管理(golang设置内存大小)

除非您正在对服务进行原型设计,否则您可能会关心应用程序的内存使用情况。内存占用更小,基础设施成本降低,扩展变得更容易/延迟。尽管Go以不消耗大量内存而闻名,但仍有一些方法可以进一步减少消耗。其中一...

golang实现deepseek 聊天功能(golang deepcopy)

在搭建完deepseek环境后在docker内部署deepseekrag环境,我们可以用golang实现聊天功能。在实现这个功能之前,我们先了解下提示词工程(prompt)。大模型虽然知道的东西多...

golang slice的扩容机制(golang设置内存大小)

在Go语言中,切片(slice)是一种动态数组,其长度可以在运行时改变。当向切片中添加元素时,如果切片的容量不足以容纳新元素,就会触发扩容机制。下面详细介绍Go语言切片的扩容机制。扩容触发条件...

Etcd服务注册与发现封装实现--golang

服务注册register.gopackageregisterimport("fmt""time"etcd3"github.com/cor...

嘿,轻松获取区间内所有日期的Golang小技巧!

在Go语言中,获取两个日期之间的所有日期可以手动实现一个函数来完成。以下是一个示例函数,它会返回一个日期切片,包含从开始日期到结束日期(包括这两个日期)的所有日期:packagemainimpo...

仓颉、Java、Golang性能测试——数组扩容

版本信息仓颉版本0.53.18Golang版本1.22.8Java版本corretto-1.8.0_452源码仓颉packagecangjie_testimportstd.collect...

Golang 58个坑 – 中级篇:36-51(golang cef)

36.关闭HTTP的响应体37.关闭HTTP连接38.将JSON中的数字解码为interface类型39.struct、array、slice和map的值比较40.从panic...

一篇文章学会golang语法,golang简明教程快速入门

Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。——Go-wikipedia.org1Go安装最新版本下载地址官方下载https...

运维大神如何使用 Golang 日志监控应用程序

你是如何使用Golang日志监控你的应用程序的呢?Golang没有异常,只有错误。因此你的第一印象可能就是开发Golang日志策略并不是一件简单的事情。不支持异常事实上并不是什么问题,异常在...

Golang操作elasticsearch(golang操作word)

简介开源的Elasticsearch是目前全文搜索引擎的首选,很多日志都是放到elasticsearch里面,然后再根据具体的需求进行分析。目前我们的运维系统是使用golang开发的,需要定时到e...

一文带你看懂Golang最新特性(golang x)

作者:腾讯PCG代码委员会经过十余年的迭代,Go语言逐渐成为云计算时代主流的编程语言。下到云计算基础设施,上到微服务,越来越多的流行产品使用Go语言编写。可见其影响力已经非常强大。一、Go语言发展历史...

Golang 最常用函数(备用查询)(golang函数和方法)

hello.gopackagemainimport"fmt"funcmain(){fmt.Println("Hello,world!")}直...

Golang:将日志以Json格式输出到Kafka

在上一篇文章中我实现了一个支持Debug、Info、Error等多个级别的日志库,并将日志写到了磁盘文件中,代码比较简单,适合练手。有兴趣的可以通过这个链接前往:https://github.com/...

如何从 PHP 过渡到 Golang?(php转go需要多久)

我是PHP开发者,转Go两个月了吧,记录一下使用Golang怎么一步步开发新项目。本着有坑填坑,有错改错的宗旨,从零开始,开始学习。因为我司没有专门的Golang大牛,所以我也只能一步步自己去...

取消回复欢迎 发表评论: