DOCKER+UPX to build smaller mirrors

Source: Internet
Author: User
Tags docker run

Whether in our production environment or test environment, when it comes to Docker pull and push, we are eager to hope that the Docker image is a very small file, on the one hand, in the case of limited network bandwidth, the smaller the image size, the less time it takes to download, On the other hand, the image is always a file, size has a certain impact on storage space, it seems to be a productivity improvement problem, then how do we build a small size image?

content of this article
    • Single Stage Build image
    • Multi-stage Build image
    • Smaller image build-up

Note: Multi-stage builds are features offered by Docker 17.05 and later

Take a look at the image list:

$ docker imagesREPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZEgolang                                     1.10.3              d0e7a411e3da        6 weeks ago         794MBalpine                                     3.8                 11cd0b38bc3c        8 weeks ago         4.41MB

Usually when we do not consider the situation, to build a Golang application image is very simple, only need to pull the official Golang environment, copy our program into it, we will first create a project directory as follows:

$ tree -L 2   -C.├── Dockerfile└── src    └── main.go    1 directory, 2 files

Single Stage Build image

    • Dockerfile:
FROM golang:1.10.3WORKDIR /go/src/testRUN go get github.com/gin-gonic/ginCOPY src srcRUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.goCMD ["./main"]
    • Build
$ docker build -t zev/test:1.0.0 .Sending build context to Docker daemon  17.41kBStep 1/6 : FROM golang:1.10.3 ---> d0e7a411e3daStep 2/6 : WORKDIR /go/src/test ---> Running in 94d1ede51e17Removing intermediate container 94d1ede51e17 ---> 2b643ce8b3cfStep 3/6 : RUN go get github.com/gin-gonic/gin ---> Running in de5e9adb7c10Removing intermediate container de5e9adb7c10 ---> ff970f45de1eStep 4/6 : COPY src src ---> 6b79fef06e45Step 5/6 : RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.go ---> Running in 6d4ef8c0b580Removing intermediate container 6d4ef8c0b580 ---> 59678a3ab4d8Step 6/6 : CMD ["./main"] ---> Running in a5cea54f2ccbRemoving intermediate container a5cea54f2ccb ---> a253cfcddd6aSuccessfully built a253cfcddd6aSuccessfully 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 imagesREPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZEzev/test                                   1.0.0               a253cfcddd6a        4 minutes ago       857MB

Image has a size of 857MB, the interior contains the entire Golang environment, such a large file in the transmission is absolutely a disaster, next we use multi-stage to build a relatively small image.

Multi-stage Build image

    • Dockerfile:
FROM golang:1.10.3 as builderWORKDIR /go/src/testRUN go get github.com/gin-gonic/ginCOPY src srcRUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.goFROM alpine:3.8WORKDIR /rootCOPY --from=builder /go/src/test/main .CMD ["./main"]
    • Build
$ docker build-t zev/test:1.0.1. Sending build context to Docker daemon 17.41kBStep 1/9: from golang:1.10.3 as builder---> d0e7a 411e3dastep 2/9: Workdir/go/src/test---> Using cache---> 2b643ce8b3cfstep 3/9: RUN go get github.com/gin-gonic/  Gin---> Using cache---> ff970f45de1estep 4/9: COPY src src---> Using cache---> 6b79fef06e45step 5/9: RUN Cgo_enabled=0 goos=linux Go build-a-installsuffix cgo-o main src/main.go---> Using cache---> 59678a3ab4d8step 6/9: from alpine:3.8---> 11cd0b38bc3cstep 7/9: Workdir/root---> Running in 1640c71479d6removing Intermediate Co Ntainer 1640c71479d6---> ec68dc839562step 8/9: COPY--from=builder/go/src/test/main. ---> 5bb444c91affstep 9/9: CMD ["./main"]---> Running in a80305feba6eremoving Intermediate container a80305feba6e ---> 5923597f59c2successfully built 5923597F59C2SUCCessfully 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 imagesREPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZEzev/test                                   1.0.1               5923597f59c2        2 minutes ago       19.8MB

Multi-stage builds reduce images by 40 times times, and 19.8M size works well in both test and production environments, but is it over?
Of course not, our goal is to make the image smaller, see our operation below.

Smaller image build-up

    • Dockerfile:
FROM golang:1.10.3 as builderRUN 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/localRUN 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/upxWORKDIR /go/src/testRUN go get github.com/gin-gonic/ginCOPY src srcRUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main src/main.goRUN strip --strip-unneeded mainRUN upx mainFROM alpine:3.8WORKDIR /rootCOPY --from=builder /go/src/test/main .CMD ["./main"]
    • Build
$ docker build-t zev/test:1.0.2. Sending build context to Docker daemon 17.92kBStep 1/14:from golang:1.10.3 as builder---> D0e7 A411e3dastep 2/14:run apt-get update && apt-get install-y xz-utils && rm-rf/var/lib/apt/lists/*- -Running in 65772cb8fdabign:1 Http://deb.debian.org/debian stretch inreleaseget: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 omitted here Copyright (C) 1996-2018upx 3.95 Markus Oberhumer, Laszlo Molnar & John Reiser 26th 2 018 File size Ratio Format Name  ------------------------------------------------9848136, 2945384 29.91% linux/amd64 mainpacked 1 file. Removing intermediate container d802406ee44a---> 0c29f4b2272dstep 11/14:from alpine:3.8---> 11cd0b38bc3cstep 12/ 14:workdir/root---> Using cache---> Ec68dc839562step 13/14:copy--from=builder/go/src/test/main. ---> A2c265cc9affstep 14/14:cmd ["./main"]---> Running in 7e350a4620eeremoving Intermediate container 7e350a4620e E---> a4d7753c8112successfully built a4d7753c8112successfully 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 imagesREPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZEzev/test                                   1.0.2               a4d7753c8112        4 minutes ago       7.36MB

OK very beautiful, until now we have seen the size of the image has shrunk to 7.36MB, which is very small, converted to our program only 2.95M.
Let's take a look at the panorama comparison:

$ docker imagesREPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZEzev/test                                   1.0.2               a4d7753c8112        6 minutes ago       7.36MBzev/test                                   1.0.1               5923597f59c2        About an hour ago   19.8MBzev/test                                   1.0.0               a253cfcddd6a        About an hour ago   857MBgolang                                     1.10.3              d0e7a411e3da        6 weeks ago         794MBalpine                                     3.8                 11cd0b38bc3c        8 weeks ago         4.41MB

So how to do it, the principle is very simple, because the size of the Alpine has been fixed, can make image smaller starting point can only be executable file, using UPX Shell technology can compress the main executable, you can reduce the main volume of 50%-70%.

tip:upx (The Ultimate Packer for executables) is a free and open source executable program file Shell that supports many different operating systems in the file format. For more information about UPX you can click here, or click here to find out more.

Summarize:

Okay, that's it. This article first shows a single-stage build image, and a ~857mb image, and then builds a multi-stage image containing only the executable ~19.8MB, finally we use multi-stage +UPX compression to reduce our image to ~7.36MB, Such a mirror in both the test environment and production environment, will certainly be able to greatly improve our productivity.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.