您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“如何使用Docker多階段構(gòu)建來減小鏡像大小”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“如何使用Docker多階段構(gòu)建來減小鏡像大小”這篇文章吧。
如何通過 Docker 的多階段構(gòu)建功能來大幅度減小鏡像大小,適用于需要在 Dockerfile 中構(gòu)建程式(如 javac),且需要另外安裝編譯工具鏈的鏡像。(如 Java)
先來學(xué)習(xí)單詞(本文全部采用中文詞匯,如需查詢外文文檔可對照該詞匯表。理論上個人不贊成翻譯術(shù)語):
multi-stage 多階段
build 構(gòu)建
image 鏡像
stage 階段
再來看一下效果: 原 110M+,現(xiàn) 92M。
對比一下 Dockerfile
優(yōu)化前 Dockerfile:
FROM openjdk:8u171-jdk-alpine3.8 ADD . /app WORKDIR /app RUN apk add maven \ && mvn clean package \ && apk del maven \ && mv target/final.jar / \ && cd / \ && rm -rf /app \ && rm -rf /root/.m2 ENTRYPOINT java -jar /final.jar
優(yōu)化后 Dockerfile:
FROM openjdk:8u171-jdk-alpine3.8 as builder ADD . /app WORKDIR /app RUN apk add maven \ && mvn clean package \ && apk del maven \ && mv target/final.jar / FROM openjdk:8u181-jre-alpine3.8 as environment WORKDIR / COPY --from=builder /final.jar . ENTRYPOINT java -jar /final.jar
很明顯,優(yōu)化后的 Dockerfile 新增了 FROM AS 這個命令,并出現(xiàn)了兩個 FROM。這就是多階段構(gòu)建。
了解一下多階段構(gòu)建
多階段構(gòu)建是 Docker 17.05 的新增功能,它可以在一個 Dockerfile 中使用多個 FROM 語句,以創(chuàng)建多個 Stages(階段)。每個階段間獨立(來源請求),可以通過 COPY --from 來獲取其它階段的文件。我們來打個比方,把最終鏡像比作一盤菜(炒青椒)。把原料青椒炒完后上桌。
# 對比清單 鏡像 -> 一盤菜 第一個階段 -> 炒 第二個階段 -> 上桌
兩個階段的目標(biāo)是做好(生成)最終的菜(鏡像)。我們要做的是將第一個階段「炒」出來的食物進(jìn)行「上桌」。我們的目標(biāo)是 做出菜,且 菜盤子(盛菜和中間產(chǎn)物)最輕。
可視化流程如下:
# 做菜流程 ... 省略原料 原料 -> [第一個階段——炒] # 此時盤子里有炒的工具、炒的結(jié)果和中間產(chǎn)物 # 這時候開啟第二個階段,只保留炒的結(jié)果,而不再需要其它。 -> 炒的結(jié)果 -> [開始上桌,只保留結(jié)果] # 把炒出來的青椒拿來(COPY --from),其它不要 -> 最終是一盤菜。
現(xiàn)在應(yīng)該大致理解多階段構(gòu)建的流程了吧。我們把話筒交給 Java,看看在 Dockerfile 中使用編譯工具構(gòu)建一個 JAR,并只保留構(gòu)建完的 JAR 和運行時交給 Image,其它則扔掉應(yīng)該怎么做:
# 第一階段——編譯(炒) FROM openjdk:8u171-jdk-alpine3.8 as builder # 自帶編譯工具 ADD . /app WORKDIR /app RUN ... 省略編譯和清理工作... # 現(xiàn)在,JAR 已經(jīng)出爐。JDK 不再需要,所以不能留在鏡像中。 # 所以我們開啟第二階段——運行(上桌),并扔掉第一階段的所有文件(包括編譯工具) FROM openjdk:8u181-jre-alpine3.8 as environment # 只帶運行時 # 目前,編譯工具等上一階段的東西已經(jīng)被我們拋下。目前的鏡像中只有運行時,我們需要把上一階段(炒)的結(jié)果拿來,其它不要。 COPY --from=0 /final.jar . # 好了,現(xiàn)在鏡像只有必要的運行時和 JAR 了。 ENTRYPOINT java -jar /final.jar
如上就是多階段構(gòu)建的介紹。
使用多階段構(gòu)建
多階段構(gòu)建的核心命令是 FROM。FORM 對于身經(jīng)百戰(zhàn)的你來說已經(jīng)不用多講了。在多階段構(gòu)建中,每次 FROM 都會開啟一個新的 Stage(階段),可以看作一個新的 Image(不夠準(zhǔn)確、來源請求),與其它階段隔離(甚至包括環(huán)境變量)。只有最后的 FROM 才會被納入 Image 中。
我們來做一個最 simple 的多階段構(gòu)建例子:
# Stage 1 FROM alpine:3.8 WORKDIR /demo RUN echo "Hello, stage 1" > /demo/hi-1.txt # Stage 2 FROM alpine:3.8 WORKDIR /demo RUN echo "Hello, stage 2" > /demo/hi-2.txt
可以自己構(gòu)建一下這個 Dockerfile,然后 docker save <tag> > docker.tar 看看其中的內(nèi)容。不出意外應(yīng)該只有 /demo/hi-2.txt 和 Alpine。
在這個 Dockerfile 中,我們創(chuàng)建了兩個階段。第一個階段創(chuàng)建 hi-1.txt,第二個階段創(chuàng)建 hi-2.txt,且第二個階段會被加入最終 Image,其它不會。
復(fù)制文件——階段間的橋梁
如果階段間完全隔離,那么多階段就沒有意義——上一個階段的結(jié)果會被完全拋棄,并進(jìn)入全新的下一階段。
我們可以通過 COPY 命令來獲取其它階段的文件。在多階段中使用 COPY 和普通應(yīng)用完全一致,僅需要添加 –form ` 即可。那么,我們修正上一個例子,使最終鏡像包含兩個階段的產(chǎn)物:
# Stage 1 FROM alpine:3.8 WORKDIR /demo RUN echo "Hello, stage 1" > /demo/hi-1.txt # Stage 2 FROM alpine:3.8 WORKDIR /demo COPY --from=0 /demo/hi-1.txt /demo RUN echo "Hello, stage 2" > /demo/hi-2.txt
重新構(gòu)建并保存(Save),你會發(fā)現(xiàn)多了一層 Layer,其中包含 hi-1.txt。
階段命名——快速識別
對于只有七秒記憶的我們來說,每次使用 stage index 并不是一件很妙的事情。這時候,可以通過階段命名的方式給它們賦予名字,以方便識別。
為階段添加名字很簡單,只需要在 FROM 后加上 as <name> 即可。
現(xiàn)在,我們更新 Dockerfile,給予階段名稱并使用名稱來 COPY。
# Stage 1, it's name is "build1" FROM alpine:3.8 as build1 WORKDIR /demo RUN echo "Hello, stage 1" > /demo/hi-1.txt # Stage 2, it's name is "build2" FROM alpine:3.8 as build2 WORKDIR /demo # No longer use indexes COPY --from=build1 /demo/hi-1.txt /demo RUN echo "Hello, stage 2" > /demo/hi-2.txt
重新構(gòu)建并保存,結(jié)果應(yīng)該同上次相同。
僅構(gòu)建部分階段——輕松調(diào)試
Docker 還為我們提供了一個很方便的調(diào)試方式——僅構(gòu)建部分階段。它可以使構(gòu)建停在某個階段,并不構(gòu)建后面的階段。這可以方便我們調(diào)試;區(qū)分生產(chǎn)、開發(fā)和測試。
仍然沿用上次的 Dockerfile,但使用 --target <stage> 參數(shù)進(jìn)行構(gòu)建:
$ docker build --target build1 .
再次 Save,你會發(fā)現(xiàn)只有 build1 的內(nèi)容。
以上是“如何使用Docker多階段構(gòu)建來減小鏡像大小”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。