Docker鏡像優(yōu)化打包速度思考
前言
當(dāng)下主流的業(yè)務(wù)架構(gòu)大部分會(huì)選擇用容器進(jìn)行部署,并結(jié)合一些容器編排技術(shù)k8s技術(shù)。由于公司業(yè)務(wù)調(diào)整,jenkins打包的工作交付到我這邊來(lái)負(fù)責(zé)。
結(jié)果組長(zhǎng)上來(lái)就給我一個(gè)當(dāng)頭一棒,打包速度太慢,盡量?jī)?yōu)化下。我尋思過(guò)年也沒(méi)忘記給拜年啊,不行把送出去的特產(chǎn)要回來(lái)吧,沒(méi)啥用啊,凈給整這一出。
說(shuō)歸說(shuō)鬧歸鬧,別拿績(jī)效開(kāi)玩笑,畢竟這年終還沒(méi)發(fā)呢,該忍還得忍。君讓臣死,臣不得不死,硬著頭皮上吧
壓縮鏡像大小
優(yōu)化第一步,瘦身,docker images查看了下基礎(chǔ)服務(wù)的鏡像大小,好家伙沒(méi)有小于300M的,一個(gè)普通的小服務(wù)都要300多,顯然在鏡像體積上可以做做文章。
在Docker官方的建議中有一個(gè)點(diǎn),使用更小的基礎(chǔ)鏡像。而在小的基礎(chǔ)鏡像中全網(wǎng)的一致答案都是alpine了。
alpine是一個(gè)非常特別的Linux版本,大小才5M左右,最早適用于嵌入式系統(tǒng),但隨著容器的流行,這個(gè)才5M大小的Linux在Docker中流行起來(lái)了,因?yàn)樘×?,非常?jié)省空間。
這里就對(duì)比下同樣屬于Linux鏡像centeros與alpine的大小
REPOSITORY TAG IMAGE ID CREATED SIZE alpine 3.16.2 9c6f07244728 7 days ago 5.54MB centeros latest df5de72bdb3b 2 weeks ago 77.8MB
解決完基礎(chǔ)鏡像再來(lái)研究下第三方包是不是有可優(yōu)化的點(diǎn),仔細(xì)分析Dockerfile發(fā)現(xiàn)在構(gòu)建過(guò)程中去拉代碼打包的,那么構(gòu)建過(guò)程中就會(huì)存在大量運(yùn)行時(shí)不需要的包。這部分清掉基本上就可以瘦身成功了。
構(gòu)建過(guò)程中,通過(guò)apk安裝軟件包時(shí),可以指定虛擬包.build-deps
,這樣git之類(lèi)的工具歸屬到虛擬包下,由于僅是構(gòu)建階段用到的命令,如執(zhí)行npm install
或pip install
,當(dāng)把項(xiàng)目構(gòu)建完以后,通過(guò)apk del .build-deps
清理掉所有臨時(shí)命令即可。
這樣就可以保證構(gòu)建出的鏡像最小了。
利用緩存加速打包速度
docker本身是有緩存機(jī)制的,也就是每次build的時(shí)候會(huì)檢查Dockerfile是否發(fā)生了變更,這里要注意是Dockerfile發(fā)生了變更,并不是代碼發(fā)生變更。
得到這個(gè)結(jié)論的時(shí)候其實(shí)我是很迷惑的,照這么來(lái)說(shuō)的話,Dockefile基本不會(huì)變,每次走緩存為什么jenkins打包速度這么慢呢。
后來(lái)在build命令里發(fā)現(xiàn)了端倪,有人在docker build時(shí)加了--no-cache參數(shù),因?yàn)榇a是在鏡像構(gòu)建時(shí)拉取的,每次走了緩存那么代碼就不會(huì)拉取了,每次都會(huì)走緩存。所以為了避免代碼不對(duì)運(yùn)維在命令里加了--no-cache
那怎么辦呢,因?yàn)镈ockefile執(zhí)行從上到下依次執(zhí)行。把代碼放到最低端,通過(guò)定義隨機(jī)數(shù)或時(shí)間戳的方式使拉代碼的命令緩存失效而不影響上面的第三方包的安裝。
豈不美哉。
Multi-stage Build
Docker 提供了 Multi-stage Build(多階段構(gòu)建),可以實(shí)現(xiàn)鏡像瘦身。
我們將鏡像構(gòu)建分成兩個(gè)階段:
在 ”build“ 階段依然采用 JDK 作為基礎(chǔ)鏡像,并利用 Maven 進(jìn)行應(yīng)用構(gòu)建; 在最終發(fā)布的鏡像中,我們會(huì)采用 JRE 版本作為基礎(chǔ)鏡像,并從”build“ 鏡像中直接拷貝出生成的 jar 文件。這意味著在最終發(fā)布的鏡像中,只包含運(yùn)行時(shí)所需必要內(nèi)容,不包含任何編譯時(shí)依賴(lài),大大減少了鏡像體積。
FROM adoptopenjdk/openjdk8 AS build RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/' /etc/apt/sources.list RUN apt-get update RUN apt-get install -y \ git \ maven WORKDIR /tmp RUN git clone https://github.com/spring-projects/spring-petclinic.git WORKDIR /tmp/spring-petclinic RUN mvn install FROM adoptopenjdk/openjdk8:jre8u222-b10-alpine-jre COPY --from=build /tmp/spring-petclinic/target/spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar CMD ["java","-jar","spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar"]
Java打包測(cè)試
springboot背景下,在默認(rèn)的maven打包插件加入分層打包配置
????<build> ????????<plugins> ????????????<plugin> ????????????????<groupId>org.springframework.boot</groupId> ????????????????<artifactId>spring-boot-maven-plugin</artifactId> ????????????????<configuration> ????????????????????<layers> ????????????????????????<enabled>true</enabled> ????????????????????</layers> ????????????????</configuration> ????????????</plugin> ????????</plugins> ????</build>
再次進(jìn)行打包分析操作mvn clean package,現(xiàn)在我們可以用下面命令來(lái)看分層打包編譯的jar包結(jié)構(gòu) java -Djarmode=layertools -jar target/dockers-demo-0.0.1-SNAPSHOT.jar list
可以看到layertools識(shí)別出jar包內(nèi)將依賴(lài)打包到不同文件夾中,接下來(lái)我們改造下原有的dockerfile。
如果不分層打包的話,一次全量包會(huì)特別大。如果只更改部分代碼的話。
FROM?openjdk:8?as?builder RUN?mvn?clean?package?-DskipTests #?聲明端口并沒(méi)有真正運(yùn)行在這個(gè)端口 EXPOSE?8080 ADD?./target/*.jar?./app.jar RUN?java?-Djarmode=layertools?-jar?app.jar?extract FROM?openjdk:8-jre MAINTAINER?ttzommed@foxmail.com WORKDIR?application #?復(fù)制第三方依賴(lài)、SpringBoot內(nèi)部配置、快照依賴(lài) COPY?--from=builder?application/dependencies/?./ COPY?--from=builder?application/spring-boot-loader/?./ COPY?--from=builder?application/snapshot-dependencies/?./ COPY?--from=builder?application/application/?./ EXPOSE?8080 ENTRYPOINT?["java",?"org.springframework.boot.loader.JarLauncher"]
依靠docker的分層特征,分次加入文件即可達(dá)到分層加速打包的效果
到此這篇關(guān)于Docker鏡像優(yōu)化打包速度思考的文章就介紹到這了,更多相關(guān)Docker鏡像打包優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解如何使用Docker部署一個(gè)web項(xiàng)目并打包成鏡像文件
- 本地使用docker打包部署鏡像的方法
- 詳解Docker 容器基礎(chǔ)系統(tǒng)鏡像打包
- Jenkins打包微服務(wù)構(gòu)建Docker鏡像運(yùn)行的實(shí)現(xiàn)
- 打包docker鏡像推送到遠(yuǎn)程服務(wù)器并部署到k8s的方法步驟
- Docker打包鏡像及修改配置的實(shí)現(xiàn)
- idea集合docker實(shí)現(xiàn)鏡像打包一鍵部署
- docker-maven-plugin打包鏡像并上傳到私有倉(cāng)庫(kù)
- Docker的鏡像制作與整套項(xiàng)目一鍵打包部署的實(shí)現(xiàn)
相關(guān)文章
Docker?創(chuàng)建centos容器集群并實(shí)現(xiàn)遠(yuǎn)程登錄功能
這篇文章主要介紹了Docker?創(chuàng)建centos容器集群并實(shí)現(xiàn)遠(yuǎn)程登錄,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03基于docker部署skywalking實(shí)現(xiàn)全鏈路監(jiān)控功能
這篇文章主要介紹了基于docker部署skywalking實(shí)現(xiàn)全鏈路監(jiān)控,skywalking提供了在很多不同的場(chǎng)景下用于觀察和監(jiān)控分布式系統(tǒng)的方式,文中給大家介紹如何快速部署skywalking全鏈路監(jiān)控,感興趣的朋友一起看看吧2022-03-03docker-compose啟動(dòng)mongo容器的使用
這篇文章主要介紹了docker-compose啟動(dòng)mongo容器的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01docker?掛載MySQL實(shí)現(xiàn)數(shù)據(jù)持久化的實(shí)現(xiàn)
本文主要介紹了docker?掛載MySQL實(shí)現(xiàn)數(shù)據(jù)持久化的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01Docker部署Memos服務(wù)的實(shí)現(xiàn)
本文將介紹如何使用Docker部署Memos服務(wù),首先,我們將構(gòu)建Memos服務(wù)的Docker鏡像,然后將在Docker容器中運(yùn)行Memos服務(wù),感興趣的可以了解一下2023-12-12基于docker-compose構(gòu)建Mongodb副本集的示例詳解
副本集是?MongoDB?高可用性和數(shù)據(jù)安全性策略的基礎(chǔ),適用于對(duì)數(shù)據(jù)安全性和服務(wù)可用性有較高要求的場(chǎng)景,本文給大家介紹了如何基于docker-compose構(gòu)建Mongodb副本集,文中通過(guò)代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01