摘要:更小的鏡像構建此處省略非常漂亮,到現在我們已經看到的已經縮小到這已經非常的小了,換算過來我們的程序只有。是一個免費且開源的可執行程序文件加殼器,支持許多不同操作系統下的可執行文件格式。
無論是在我們的生產環境或測試環境中,一旦涉及到docker pull和push的時候,我們都迫切希望Docker鏡像是一個非常小的file,一方面在網絡帶寬有限的情況下,image的size越小下載所付出的時間代價就越小,另一方面image始終是一個文件,size對存儲空間是有一定影響的,看來這是個提高生產力的問題,那么我們如何去構建一個size很小的image呢?
本文內容
單階段構建鏡像
多階段構建鏡像
更小的鏡像構建
注:多階段構建是 Docker 17.05 及更高版本提供的功能
查看一下image列表:
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE golang 1.10.3 d0e7a411e3da 6 weeks ago 794MB alpine 3.8 11cd0b38bc3c 8 weeks ago 4.41MB
通常在我們什么都不考慮的情況下,構建一個golang的應用鏡像是非常簡單的,只需要pull官方的golang環境,把我們的程序copy進去就可以了,下面我們先創建一個工程的目錄如下:
$ tree -L 2 -C . ├── Dockerfile └── src └── main.go 1 directory, 2 files
Dockerfile:
FROM golang:1.10.3 WORKDIR /go/src/test RUN go get github.com/gin-gonic/gin COPY src src RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go CMD ["./main"]
Build
$ docker build -t zev/test:1.0.0 . Sending build context to Docker daemon 17.41kB Step 1/6 : FROM golang:1.10.3 ---> d0e7a411e3da Step 2/6 : WORKDIR /go/src/test ---> Running in 94d1ede51e17 Removing intermediate container 94d1ede51e17 ---> 2b643ce8b3cf Step 3/6 : RUN go get github.com/gin-gonic/gin ---> Running in de5e9adb7c10 Removing intermediate container de5e9adb7c10 ---> ff970f45de1e Step 4/6 : COPY src src ---> 6b79fef06e45 Step 5/6 : RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go ---> Running in 6d4ef8c0b580 Removing intermediate container 6d4ef8c0b580 ---> 59678a3ab4d8 Step 6/6 : CMD ["./main"] ---> Running in a5cea54f2ccb Removing intermediate container a5cea54f2ccb ---> a253cfcffffd6a Successfully built a253cfcffffd6a Successfully tagged zev/test:1.0.0
RUN
$ docker run -it -p 8080:8080 zev/test:1.0.0 [GIN-debug] [WARNING] Now Gin requires Go 1.6 or later and Go 1.7 will be required soon. [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode) [GIN-debug] GET /ping --> main.main.func1 (3 handlers) [GIN-debug] Listening and serving HTTP on :8080
Images
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE zev/test 1.0.0 a253cfcffffd6a 4 minutes ago 857MB
image的size為857MB,內部包含了整個golang環境,這么大的文件在傳輸中絕對是個災難,接下來我們用多階段構建一個相對比較小的image。
Dockerfile:
FROM golang:1.10.3 as builder WORKDIR /go/src/test RUN go get github.com/gin-gonic/gin COPY src src RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go FROM alpine:3.8 WORKDIR /root COPY --from=builder /go/src/test/main . CMD ["./main"]
Build
$ docker build -t zev/test:1.0.1 . Sending build context to Docker daemon 17.41kB Step 1/9 : FROM golang:1.10.3 as builder ---> d0e7a411e3da Step 2/9 : WORKDIR /go/src/test ---> Using cache ---> 2b643ce8b3cf Step 3/9 : RUN go get github.com/gin-gonic/gin ---> Using cache ---> ff970f45de1e Step 4/9 : COPY src src ---> Using cache ---> 6b79fef06e45 Step 5/9 : RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go ---> Using cache ---> 59678a3ab4d8 Step 6/9 : FROM alpine:3.8 ---> 11cd0b38bc3c Step 7/9 : WORKDIR /root ---> Running in 1640c71479d6 Removing intermediate container 1640c71479d6 ---> ec68dc839562 Step 8/9 : COPY --from=builder /go/src/test/main . ---> 5bb444c91aff Step 9/9 : CMD ["./main"] ---> Running in a80305feba6e Removing intermediate container a80305feba6e ---> 5923597f59c2 Successfully built 5923597f59c2 Successfully tagged zev/test:1.0.1
RUN
$ docker run -it -p 8080:8080 zev/test:1.0.1 [GIN-debug] [WARNING] Now Gin requires Go 1.6 or later and Go 1.7 will be required soon. [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode) [GIN-debug] GET /ping --> main.main.func1 (3 handlers) [GIN-debug] Listening and serving HTTP on :8080
Images
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE zev/test 1.0.1 5923597f59c2 2 minutes ago 19.8MB
多階段構建讓images縮小了40倍,19.8M的size無論在測試環境還是生產環境都能很好的工作了,但是這樣就結束了嗎?
當然不是了,我們的目的是讓image變得更小,下面看我們的操作。
Dockerfile:
FROM golang:1.10.3 as builder RUN apt-get update && apt-get install -y xz-utils && rm -rf /var/lib/apt/lists/* ADD https://github.com/upx/upx/releases/download/v3.95/upx-3.95-amd64_linux.tar.xz /usr/local RUN xz -d -c /usr/local/upx-3.95-amd64_linux.tar.xz | tar -xOf - upx-3.95-amd64_linux/upx > /bin/upx && chmod a+x /bin/upx WORKDIR /go/src/test RUN go get github.com/gin-gonic/gin COPY src src RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go RUN strip --strip-unneeded main RUN upx main FROM alpine:3.8 WORKDIR /root COPY --from=builder /go/src/test/main . CMD ["./main"]
Build
$ docker build -t zev/test:1.0.2 . Sending build context to Docker daemon 17.92kB Step 1/14 : FROM golang:1.10.3 as builder ---> d0e7a411e3da Step 2/14 : RUN apt-get update && apt-get install -y xz-utils && rm -rf /var/lib/apt/lists/* ---> Running in 65772cb8fdab Ign:1 http://deb.debian.org/debian stretch InRelease Get:2 http://security.debian.org/debian-security stretch/updates InRelease [94.3 kB] Get:3 http://deb.debian.org/debian stretch-updates InRelease [91.0 kB] Get:4 http://security.debian.org/debian-security stretch/updates/main amd64 Packages [392 kB] .....此處省略 Step 10/14 : RUN upx main ---> Running in d802406ee44a Ultimate Packer for eXecutables Copyright (C) 1996 - 2018 UPX 3.95 Markus Oberhumer, Laszlo Molnar & John Reiser Aug 26th 2018 File size Ratio Format Name -------------------- ------ ----------- ----------- 9848136 -> 2945384 29.91% linux/amd64 main Packed 1 file. Removing intermediate container d802406ee44a ---> 0c29f4b2272d Step 11/14 : FROM alpine:3.8 ---> 11cd0b38bc3c Step 12/14 : WORKDIR /root ---> Using cache ---> ec68dc839562 Step 13/14 : COPY --from=builder /go/src/test/main . ---> a2c265cc9aff Step 14/14 : CMD ["./main"] ---> Running in 7e350a4620ee Removing intermediate container 7e350a4620ee ---> a4d7753c8112 Successfully built a4d7753c8112 Successfully tagged zev/test:1.0.2
RUN
$ docker run -it -p 8080:8080 zev/test:1.0.2 [GIN-debug] [WARNING] Now Gin requires Go 1.6 or later and Go 1.7 will be required soon. [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached. [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production. - using env: export GIN_MODE=release - using code: gin.SetMode(gin.ReleaseMode) [GIN-debug] GET /ping --> main.main.func1 (3 handlers) [GIN-debug] Listening and serving HTTP on :8080
Images
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE zev/test 1.0.2 a4d7753c8112 4 minutes ago 7.36MB
OK 非常漂亮,到現在我們已經看到image的size已經縮小到7.36MB,這已經非常的小了,換算過來我們的程序只有2.95M。
我們來一張全景對比看下:
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE zev/test 1.0.2 a4d7753c8112 6 minutes ago 7.36MB zev/test 1.0.1 5923597f59c2 About an hour ago 19.8MB zev/test 1.0.0 a253cfcffffd6a About an hour ago 857MB golang 1.10.3 d0e7a411e3da 6 weeks ago 794MB alpine 3.8 11cd0b38bc3c 8 weeks ago 4.41MB
那么怎么做到的呢,原理很簡單,因為alpine的size已經固定了,能讓image變得更小的入手點只能是可執行文件,利用UPX的加殼技術可以壓縮main可執行程序,可以把main體積縮小50%-70%。
Tip:UPX(the Ultimate Packer for eXecutables)是一個免費且開源的可執行程序文件加殼器,支持許多不同操作系統下的可執行文件格式。想了解更多關于UPX的信息可以點擊這里 ,也可點擊這里.
總結:
好的,到此為止本文首先展示了單階段構建鏡像,并得到了一個~857MB的鏡像,然后利用多階段構建了一個只包含可執行文件的鏡像~19.8MB,最后我們利用多階段+UPX壓縮把我們的鏡像縮小到了~7.36MB,這樣的鏡像無論在測試環境還是生產環境,都一定能大大的提高我們的生產力。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/27436.html
摘要:接下來我們將逐步的減少這個鏡像的體積。優化生產環境鏡像使用鏡像大幅減小鏡像體積的最簡單和最快的方法是選擇一個小得多的基本鏡像。使用多階段構建可以充分利用鏡像的緩存,大大減少最終部署到生產環境的時間。 關注作者github每日一道面試題詳解 你討厭部署你的應用程序花費很長時間嗎? 對于單個容器來說,超過gb并不是最佳實踐。每次部署新版本時都要處理數十億字節,這對我們來說并不太合適。 本文...
摘要:我一直在尋找盡可能小的容器入手,并且發現了一個鏡像是完美的,真正的完美它簡潔,小巧以及快速。所以這可能就是最小的鏡像。盡管如此,這樣看起來會很復雜并且導致容器很大。 注:本文由 Adriaan de Jonge 編寫,本文的原文地址為 Create The Smallest Possible Docker Container 當我們在使用 Docker 的時候,你會很快注意到...
摘要:編寫代碼的開發人員必須負責代碼的生產部署。構建和部署鏈需要重大更改,以便為微服務環境提供正確的關注點分離。該對象會在之后的時被這時的回調函數會被調用,并輸出。微服務部署及集成部署微服務時有一個原則一個容器中只放一個服務,可以使用編 前幾天在微信群做的一次分享,整理出來分享給大家,相關代碼請戳 https://github.com/Carrotzpc/docker_web_app sho...
摘要:編寫代碼的開發人員必須負責代碼的生產部署。構建和部署鏈需要重大更改,以便為微服務環境提供正確的關注點分離。該對象會在之后的時被這時的回調函數會被調用,并輸出。微服務部署及集成部署微服務時有一個原則一個容器中只放一個服務,可以使用編 前幾天在微信群做的一次分享,整理出來分享給大家,相關代碼請戳 https://github.com/Carrotzpc/docker_web_app sho...
閱讀 2272·2021-11-16 11:51
閱讀 3501·2021-09-26 10:14
閱讀 1789·2021-09-22 15:58
閱讀 1094·2019-08-30 15:52
閱讀 2012·2019-08-30 15:43
閱讀 2612·2019-08-30 13:46
閱讀 907·2019-08-30 13:10
閱讀 1020·2019-08-29 18:32