如何将镜像体积海量缩减

news2024/11/19 2:46:43

点击上方蓝色字体,选择“设为星标”

回复”云原生“获取基础架构实践

d2b594bb06b9165b60cd90f889d7a566.jpeg

镜像的传统构建

我们随便找个Golang代码项目作为案例,来开始构建一个镜像。下面我们以我的一个实战项目开始讲解:https://gitee.com/damon_one/uranus

第一步:我们把项目代码克隆到本地:

git clone https://gitee.com/damon_one/uranus

第二步,书写其编译的Dockerfile:

FROM golang:1.20
WORKDIR /opt/app
COPY . .
go build -o hz-zeus ./zeus
CMD ["/opt/app/hz-zeus"]

这个 Dockerfile 描述的构建过程非常简单,我们首选 Golang:1.20 版本的镜像作为编译环境,将源码拷贝到镜像中,然后运行 go build 编译源码生成二进制可执行文件,最后配置启动命令。

第三步,构建镜像:

docker build -t hz-zeus -f Dockerfile .

这样编译构建的镜像会很大,这里就不展示最后的镜像信息了。

Dockerfile 优化

从上面的 Dockerfile 可以看出,我们在容器内运行了 go build -o hz-zeus ./zeus,这条命令将会编译生成二进制的可执行文件,由于编译的过程中需要 Golang 编译工具的支持,所以我们必须要使用 Golang 镜像作为基础镜像,这是导致镜像体积过大的直接原因。

既然依赖基础镜像比较大,那么我们是否可以替换为轻量级的镜像呢?发现可以将 Golang:1.20 基础镜像替换为 golang:1.20-alpine 版本。

但,这样的构建之后,发现镜像还是很大。毕竟是在镜像内镜像编译二进制文件后构建镜像。那是否可以在外部进行构建后再同步到镜像内部呢?

$ CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o hz-zeus ./zeus
$ ls -lh
...

最简单的办法就是在本地先编译出可执行文件,再将它复制到一个更小体积的 ubuntu 镜像内。具体做法是,首先在本地使用交叉编译生成 Linux 平台的二进制可执行文件。接下来,使用 Dockerfile 文件构建镜像。

FROM ubuntu:latest
WORKDIR /opt/app
COPY hz-zeus ./

CMD ["/opt/app/hz-zeus"]

因为不再需要在容器里进行编译,所以我们直接引入了不包含 Golang 编译工具的 ubuntu 镜像作为基础运行环境,接下来使用 docker build 命令构建镜像。

这种构建方式生成的镜像在体积上比最初的缩小了几乎 90% 。镜像的最终大小就相当于 ubuntu:latest 的大小加上 Golang 二进制可执行文件的大小。不过,这种方式将应用的编译过程拆分到了宿主机上,这会让 Dockerfile 失去描述应用编译和打包的作用,不是一个好的实践。

多阶段构建

多阶段构建的本质其实就是将镜像构建过程拆分成编译过程和运行过程。第一个阶段对应编译的过程,负责生成可执行文件;第二个阶段对应运行过程,也就是拷贝第一阶段的二进制可执行文件,并为程序提供运行环境,最终镜像也就是第二阶段生成的镜像。

FROM golang:1.20 as builder
WORKDIR /opt/app
COPY . .
RUN go build -o hz-zeus ./zeus


FROM ubuntu:latest
WORKDIR /opt/app
COPY --from=builder /opt/app/hz-zeus ./hz-zeus

CMD ["/opt/app/hz-zeus"]

这段内容里有两个 FROM 语句,所以这是一个包含两个阶段的构建过程。

第二阶段,它的作用是将第一阶段生成的二进制可执行文件复制到当前阶段,把 ubuntu:latest 作为运行环境,并设置 CMD 启动命令。

最后,我们执行docker build后会发现镜像大小与上面的先编译后copy到镜像种的操作生成的镜像一样大小。

到这里,对镜像大小的优化已经基本上完成了,镜像大小也在可接受的范围内。在实际的项目中,我也推荐你使用 ubuntu:latest 作为第二阶段的程序运行镜像。

如何复用构建缓存

在第一阶段的构建过程中,我们先是用 COPY . .  的方式拷贝了源码,又进行了编译,这会产生一个缺点,那就是如果只是源码变了,但依赖并没有变,Docker 将无法复用依赖的镜像层缓存。在实际构建过程中,你会发现 Docker 每次都会重新下载 Golang 依赖。

这就引出了另外一个构建镜像的小技巧:尽量使用 Docker 构建缓存。

要使用 Golang 依赖的缓存,最简单的办法是:先复制依赖文件,再下载依赖,最后再复制源码进行编译。基于这种思路,我们可以将第一阶段的构建修改如下:

FROM golang:1.20 as builder
WORKDIR /opt/app
COPY go.* ./
RUN go mod download
COPY . .
RUN go build -o hz-zeus ./zeus

这样,在每次代码变更而依赖不变的情况下,Docker 都会复用之前产生的构建缓存,这可以加速镜像构建过程。

下面给大家介绍几本好书,目前销售火热,有原理加实战,感兴趣可以点击下方链接购买。

开源项目

  实践项目代码开源:https://gitee.com/damon_one/microservice-k8s

欢迎大家star、fork,欢迎联系我,一起学习。

号内回复“云原生”,获取云原生基础架构实践

93d530814821a9da4c53fb11baff5a88.png

云原生社区合肥站

云原生社区合肥站正式启动啦,欢迎Base合肥、关注云原生、长期从事云原生的同志们踊跃加入,云原生社区合肥站会因为你们的加入而变得更加美好~

详情参见Issue:https://github.com/cloudnativeto/community/issues/107

联系号主

7294862a1769125bd28fa0cbcf8c2b4e.jpeg

欢迎关注个站

714c532e12f4f613307c0d3af60d6b3d.png

往期回顾

微服务自动化部署CI/CD

如何利用k8s拉取私有仓库镜像

个站建设基础教程

ArrayList、LinkedList 你真的了解吗?

大佬整理的mysql规范,分享给大家

如果张东升是个程序员

微服务架构设计之解耦合

浅谈负载均衡

Oauth2的认证实战-HA篇

Oauth2的授权码模式《上》

浅谈开发与研发之差异

浅谈 Java 集合 | 底层源码解析

基于 Sentinel 作熔断 | 文末赠资料

基础设施服务k8s快速部署之HA篇

今天被问微服务,这几点,让面试官刮目相看

Spring cloud 之多种方式限流(实战)

Spring cloud 之熔断机制(实战)

面试被问finally 和 return,到底谁先执行?

Springcloud Oauth2 HA篇

Spring Cloud Kubernetes之实战一配置管理

Spring Cloud Kubernetes之实战二服务注册与发现

Spring Cloud Kubernetes之实战三网关Gateway

103b5f60e6ca968c22faeeee032fce3d.gif

4b9bc527ccb5fe16ec3eebbb8f2bf05c.gif

点击 "damon8.cn" 获取更好的阅读体验!

❤️给个「在看」,是对我最大的支持❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/831054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uC-OS2 V2.93 STM32L476 移植:系统移植篇

前言 上一篇已经 通过 STM32CubeMX 搭建了 NUCLEO-L476RG STM32L476RG 的 裸机工程,并且下载了 uC-OS2 V2.93 的源码,接下来,开始系统移植 开发环境 win10 64位 Keil uVision5,MDK V5.36 uC-OS2 V2.93 开发板:NUC…

机器学习深度学习——从全连接层到卷积

👨‍🎓作者简介:一位即将上大四,正专攻机器学习的保研er 🌌上期文章:机器学习&&深度学习——非NVIDIA显卡怎么做深度学习(坑点排查) 📚订阅专栏:机器…

D. Different Arrays

Problem - 1783D - Codeforces 思路: 这是一个计数问题,我们要统计不同数组的个数,可以用dp,让f[i][j]表示只考虑前i个,并且结尾为j的情况,那么转移方程为我们枚举i,与枚举前一个是多少&#xf…

电脑安装新系统不知道去哪里下载,看我就够了

大家在日常生活中肯定都会遇到电脑安装系统的需求,如果去微软官方购买正版的系统又很贵,又不太想花这个冤枉钱,这个时候我们就不得不去网上查找一些免费好用的系统,可是百度一下,或者Google一下,各种下载系…

【css】css设置表格样式-边框线合并

<style> table, td, th {border: 1px solid black;//设置边框线 }table {width: 100%; }td {text-align: center;//设置文本居中 } </style> </head> <body><table><tr><th>Firstname</th><th>Lastname</th><t…

【uniapp】样式合集

1、修改uni-data-checkbox多选框的样式为单选框的样式 我原先是用的单选&#xff0c;但是单选并不支持选中后&#xff0c;再次点击取消选中&#xff1b;所以我改成了多选&#xff0c;然后改变多选样式&#xff0c;让他看起来像单选 在所在使用的页面上修改样式即可 <uni-d…

1-搭建一个最简单的验证平台UVM,已用Questasim实现波形!

UVM-搭建一个最简单的验证平台&#xff0c;已用Questasim实现波形 1&#xff0c;背景知识2&#xff0c;".sv"文件搭建的UVM验证平台&#xff0c;包括代码块分享3&#xff0c;Questasim仿真输出&#xff08;1&#xff09;compile all&#xff0c;成功&#xff01;&…

kubernetes 集群利用 efk 收集容器日志

文章目录 [toc]前情提要制作 centos 基础镜像准备 efk 二进制文件部署 efk 组件配置 namespace配置 gfs 的 endpoints配置 pv 和 pvc部署 elasticsearchefk-cmefk-svcefk-sts 部署 filebeatfilebeat-cmfilebeat-ds 部署 kibanakibana-cmkibana-svckibana-dp使用 nodeport 访问 …

免费快速下载省市区县行政区的Shp数据

摘要&#xff1a;一般非专业的GIS应用通常会用到省市等行政区区划边界空间数据做分析&#xff0c;本文简单介绍了如何在互联网上下载省&#xff0c;市&#xff0c;区县的shp格式空间边界数据&#xff0c;并介绍了一个好用的在线数据转换工具&#xff0c;并且开源。 一、首先&am…

图卷积网络(GCN)和池化

一、说明 GCN&#xff08;Graph Convolutional Network&#xff09;是一种用于图形数据处理和机器学习的神经网络架构。GCN 可以在图形中捕获节点之间的关系&#xff0c;从而能够更好地处理图形数据。GCN 可以沿着图形上的边缘执行滤波器操作&#xff0c;将每个节点的特征向量进…

OA是什么意思?OA系统是什么

阅读本文您可以了解&#xff1a;1、OA是什么&#xff1b;2、OA系统是什么&#xff1b;3、OA系统有什么功能 一、OA是什么 当提到OA&#xff0c;我们通常指的是"Office Automation"&#xff08;办公自动化&#xff09;。 办公自动化指的是在办公室环境中使用计算机技…

培训系统中的技术创新与发展趋势

随着互联网和信息技术的快速发展&#xff0c;培训系统也进入了一个全新的时代。传统的面对面培训逐渐被在线培训所取代&#xff0c;培训系统中的技术创新和发展成为了推动整个行业发展的关键因素。 1. VR和AR技术的应用 虚拟现实&#xff08;VR&#xff09;和增强现实&#x…

并查集和哈希表的实现

并查集和哈希表的实现 文章目录 并查集和哈希表的实现1.并查集的功能2.并查集的基本原理3.并查集的实现 哈希表&#xff08;hash&#xff09;1.拉链法2.开放寻址法方法流程代码演示 3,字符串哈希 1.并查集的功能 1.将两个集合进行合并 2.询问两个元素是否在一个集合里面 2.并…

js中exec与match的区别

const regex1 RegExp(f(o.?),g); const str1 table foatball, fobsball; let array1; let array2; array1 regex1.exec(str1) array2 str1.match(regex1)console.log(array1, array1); console.log(array2, array2); //没有g的情况下,都是找到第一个匹配,并且如果有分组,…

SPSS数据分析--假设检验的两种原假设取舍决定方式

假设检验的两种原假设取舍决定方式 在t检验&#xff0c;相关分析&#xff0c;回归分析&#xff0c;方差分析&#xff0c;卡方检验等等分析方法中&#xff0c;都需要用到假设检验。假设检验的步骤一般如下&#xff1a; 提出假设&#xff1a;H0 vs H1 ;假设原假设H0 成立的情况…

Java课题笔记~ 动态SQL详解

一、动态 sql 是什么&#xff1f; 1、动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中&#xff0c;开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。 例如&#xff0c;拼接时要确保添加了必要的空格&#xff0c;还要…

AWS多账户单点登录 IAM Identity Center(AWS SSO)

需求场景 多个aws账户&#xff0c;登陆麻烦且不安全&#xff0c;SSO单点功能并且外部身份提供者 — 如果您要管理外部身份提供者&#xff08;IdP&#xff09;&#xff08;例如 Okta 或 Active Directory&#xff09;中的用户。 官方文档&#xff1a;https://docs.aws.amazon.c…

Maven引入本地jar包

maven做为一种强大的依赖管理工具&#xff0c;可以帮助我们更方便的管理项目中的依赖&#xff1b;而在使用过程中我们难免会有需要引入本地jar包的需求&#xff0c;这里踩过坑之后我分享俩种引入方式&#xff1b; 1.上传jar到本地maven仓库&#xff0c;再引入 使用此方法后可…

基于Translators的多语言翻译解决方案

当Translators库,一个用Python为个人和学生提供免费、多样、愉快翻译的库。 文章目录 Translators支持的翻译服务安装与入门参数和功能支持的语言调试和运行环境API服务Translators Translators库是一个强大的Python库,旨在为个人和学生提供免费、多样、愉快的翻译体验。它支…

文件传输协议FTP与托管文件传输MFT有什么区别?

传输敏感数据是日常业务中不可或缺的一环。但是&#xff0c;在把敏感数据从A点搬到B点的过程中&#xff0c;保证该敏感数据的安全是组织的重要任务&#xff0c;因此最好选择一种能够确保文件安全的方案。 FTP与MFT有什么不同&#xff1f; FTP&#xff08;文件传输协议&#xf…