注冊用戶即可下載全站資源 關注Java幫幫微信公眾號
 

三個技巧,將Docker鏡像體積減小90%【面試+工作】

12
發表時間:2018-11-10 17:48

在構建Docker容器時,應該盡量想辦法獲得體積更小的鏡像,因為傳輸和部署體積較小的鏡像速度更快。

日本韩国三级aⅴ在线观看但RUN語句總是會創建一個新層,而且在生成鏡像之前還需要使用很多中間文件,在這種情況下,該如何獲得體積更小的鏡像呢?

日本韩国三级aⅴ在线观看你可能已經注意到了,大多數Dockerfiles都使用了一些奇怪的技巧:

為什么使用&&?而不是使用兩個RUN語句代替呢?比如:

日本韩国三级aⅴ在线观看從Docker 1.10開始,COPY、ADD和RUN語句會向鏡像中添加新層。前面的示例創建了兩個層而不是一個。

鏡像的層就像Git的提交(commit)一樣。

Docker的層用于保存鏡像的上一版本和當前版本之間的差異。就像Git的提交一樣,如果你與其他存儲庫或鏡像共享它們,就會很方便。

實際上,當你向注冊表請求鏡像時,只是下載你尚未擁有的層。這是一種非常高效地共享鏡像的方式。

日本韩国三级aⅴ在线观看但額外的層并不是沒有代價的。

層仍然會占用空間,你擁有的層越多,最終的鏡像就越大。Git存儲庫在這方面也是類似的,存儲庫的大小隨著層數的增加而增加,因為Git必須保存提交之間的所有變更。

過去,將多個RUN語句組合在一行命令中或許是一種很好的做法,就像上面的第一個例子那樣,但在現在看來,這樣做并不妥。

1. 通過Docker多階段構建將多個層壓縮為一個

日本韩国三级aⅴ在线观看當Git存儲庫變大時,你可以選擇將歷史提交記錄壓縮為單個提交。

事實證明,在Docker中也可以使用多階段構建達到類似的目的。

日本韩国三级aⅴ在线观看在這個示例中,你將構建一個Node.js容器。

日本韩国三级aⅴ在线观看讓我們從index.js開始:

日本韩国三级aⅴ在线观看和package.json:

你可以使用下面的Dockerfile來打包這個應用程序:

然后開始構建鏡像:

日本韩国三级aⅴ在线观看然后用以下方法驗證它是否可以正常運行:

你應該能訪問http://localhost:3000,并收到“Hello World!”。

日本韩国三级aⅴ在线观看Dockerfile中使用了一個COPY語句和一個RUN語句,所以按照預期,新鏡像應該比基礎鏡像多出至少兩個層:

日本韩国三级aⅴ在线观看但實際上,生成的鏡像多了五個新層:每一個層對應Dockerfile里的一個語句。

現在,讓我們來試試Docker的多階段構建。

你可以繼續使用與上面相同的Dockerfile,只是現在要調用兩次:

日本韩国三级aⅴ在线观看Dockerfile的第一部分創建了三個層,然后這些層被合并并復制到第二個階段。在第二階段,鏡像頂部又添加了額外的兩個層,所以總共是三個層。

日本韩国三级aⅴ在线观看現在來驗證一下。首先,構建容器:

查看鏡像的歷史:

文件大小是否已發生改變?

日本韩国三级aⅴ在线观看最后一個鏡像(node-multi-stage)更小一些。

你已經將鏡像的體積減小了,即使它已經是一個很小的應用程序。

但整個鏡像仍然很大!

有什么辦法可以讓它變得更小嗎?

2. 用distroless去除容器中所有不必要的東西

這個鏡像包含了Node.js以及yarn、npm、bash和其他的二進制文件。因為它也是基于Ubuntu的,所以你等于擁有了一個完整的操作系統,其中包括所有的小型二進制文件和實用程序。

但在運行容器時是不需要這些東西的,你需要的只是Node.js。

日本韩国三级aⅴ在线观看Docker容器應該只包含一個進程以及用于運行這個進程所需的最少的文件,你不需要整個操作系統。

實際上,你可以刪除Node.js之外的所有內容。

但要怎么做?

日本韩国三级aⅴ在线观看所幸的是,谷歌為我們提供了distroless。

日本韩国三级aⅴ在线观看以下是distroless存儲庫的描述:

這正是你所需要的!

你可以對Dockerfile進行調整,以利用新的基礎鏡像,如下所示:

日本韩国三级aⅴ在线观看你可以像往常一樣編譯鏡像:

這個鏡像應該能正常運行。要驗證它,可以像這樣運行容器:

日本韩国三级aⅴ在线观看現在可以訪問http://localhost:3000頁面。

不包含其他額外二進制文件的鏡像是不是小多了?

只有76.7MB!

比之前的鏡像小了600MB!

日本韩国三级aⅴ在线观看但在使用distroless時有一些事項需要注意。

當容器在運行時,如果你想要檢查它,可以使用以下命令attach到正在運行的容器上:

日本韩国三级aⅴ在线观看attach到正在運行的容器并運行bash命令就像是建立了一個SSH會話一樣。

但distroless版本是原始操作系統的精簡版,沒有了額外的二進制文件,所以容器里沒有shell!

日本韩国三级aⅴ在线观看在沒有shell的情況下,如何attach到正在運行的容器呢?

答案是,你做不到。這既是個壞消息,也是個好消息。

日本韩国三级aⅴ在线观看之所以說是壞消息,因為你只能在容器中執行二進制文件。你可以運行的唯一的二進制文件是Node.js:

說它是個好消息,是因為如果攻擊者利用你的應用程序獲得對容器的訪問權限將無法像訪問shell那樣造成太多破壞。換句話說,更少的二進制文件意味著更小的體積和更高的安全性,不過這是以痛苦的調試為代價的。

日本韩国三级aⅴ在线观看但如果你確實需要調試,又想保持小體積該怎么辦?

3. 小體積的Alpine基礎鏡像

你可以使用Alpine基礎鏡像替換distroless基礎鏡像。

Alpine Linux是:

日本韩国三级aⅴ在线观看換句話說,它是一個體積更小也更安全的Linux發行版。

日本韩国三级aⅴ在线观看不過你不應該理所當然地認為他們聲稱的就一定是事實,讓我們來看看它的鏡像是否更小。

日本韩国三级aⅴ在线观看先修改Dockerfile,讓它使用node:8-alpine:

使用下面的命令構建鏡像:

現在可以檢查一下鏡像大小:

69.7MB!

日本韩国三级aⅴ在线观看甚至比distrless鏡像還小!

日本韩国三级aⅴ在线观看現在可以attach到正在運行的容器嗎?讓我們來試試。

讓我們先啟動容器:

你可以使用以下命令attach到運行中的容器:

看來不行,但或許可以使用shell?

日本韩国三级aⅴ在线观看成功了!現在可以attach到正在運行的容器中了。

日本韩国三级aⅴ在线观看看起來很有希望,但還有一個問題。

Alpine基礎鏡像是基于muslc的——C語言的一個替代標準庫,而大多數Linux發行版如Ubuntu、Debian和CentOS都是基于glibc的。這兩個庫應該實現相同的內核接口。

日本韩国三级aⅴ在线观看但它們的目的是不一樣的:

  • glibc更常見,速度也更快;

  • 日本韩国三级aⅴ在线观看muslc使用較少的空間,并側重于安全性。

日本韩国三级aⅴ在线观看在編譯應用程序時,大部分都是針對特定的libc進行編譯的。如果你要將它們與另一個libc一起使用,則必須重新編譯它們。

換句話說,基于Alpine基礎鏡像構建容器可能會導致非預期的行為,因為標準C庫是不一樣的。

日本韩国三级aⅴ在线观看你可能會注意到差異,特別是當你處理預編譯的二進制文件(如Node.js C++擴展)時。

日本韩国三级aⅴ在线观看例如,PhantomJS的預構建包就不能在Alpine上運行。

你應該選擇哪個基礎鏡像?

日本韩国三级aⅴ在线观看你應該使用Alpine、distroless還是原始鏡像?

日本韩国三级aⅴ在线观看如果你是在生產環境中運行容器,并且更關心安全性,那么可能distroless鏡像更合適。

添加到Docker鏡像的每個二進制文件都會給整個應用程序增加一定的風險。

只在容器中安裝一個二進制文件可以降低總體風險。

例如,如果攻擊者能夠利用運行在distroless上的應用程序的漏洞,他們將無法在容器中使用shell,因為那里根本就沒有shell!

日本韩国三级aⅴ在线观看如果你只關心更小的鏡像體積,那么可以考慮基于Alpine的鏡像。

它們的體積非常小,但代價是兼容性較差。Alpine使用了略微不同的標準C庫——muslc。你可能會時不時地遇到一些兼容性問題。

原始基礎鏡像非常適合用于測試和開發。

日本韩国三级aⅴ在线观看它雖然體積很大,但提供了與Ubuntu工作站一樣的體驗。此外,你還可以訪問操作系統的所有二進制文件。

日本韩国三级aⅴ在线观看再回顧一下各個鏡像的大小:

日本韩国三级aⅴ在线观看node:8  681MB

node:8  使用多階段構建為678MB

日本韩国三级aⅴ在线观看gcr.io/distroless/nodejs  76.7MB

node:8-alpine  69.7MB


支付寶贊助-Java幫幫社區
微信贊助-Java幫幫社區
Java幫幫公眾號生態

Java幫幫公眾號生態

總有一款適合你

Java幫幫-微信公眾號

Java幫幫-微信公眾號

將分享做到極致

Python幫幫-公眾號

Python幫幫-公眾號

人工智能,爬蟲,學習教程

大數據驛站-微信公眾號

大數據驛站-微信公眾號

一起在數據中成長

九點編程-公眾號

九點編程-公眾號

深夜九點學編程

程序員生活志-公眾號

程序員生活志-公眾號

互聯網,職場,程序員那些事兒

Java幫幫學習群生態

Java幫幫學習群生態

總有一款能幫到你

Java學習群

Java學習群

與大牛一起交流

大數據學習群

大數據學習群

在數據中成長

九點編程學習群

九點編程學習群

深夜九點學編程

python學習群

python學習群

人工智能,爬蟲

測試學習群

測試學習群

感受測試的魅力

Java幫幫生態承諾

Java幫幫生態承諾

一直堅守,不負重望

初心
勤儉
誠信
正義
分享
合作品牌 非盈利生態-優質內容分享傳播者
關于我們
友鏈申請
友鏈交換:加幫主QQ2524138991 留言即可 24小時內答復  
全站內容非商業用途,內容來源于網友,并遵循 許可,如有異議請聯系客服。
會員登錄
獲取驗證碼
登錄
登錄
我的資料
留言
回到頂部