Create the smallest Docker Image for Go programs

Source: Internet
Author: User
Tags docker run
This is a creation in Article, where the information may have evolved or changed.

This article will show you how to use Docker packaging a golang written application, the final product is a dockerfile file, do not underestimate this short line of code, the knowledge points involved can be many, next we will carefully analyze it.

FROM golang:alpineADD src /go/srcRUN go install -v test ENTRYPOINT ["/go/bin/test"]CMD ["-logtostderr"]

1. Base image Selection

The first line is to specify a base image, based on which we created our image, using the Golang:alpine version,
This is a relatively small Linux system, cut off many of the tools in Linux, package management tools using the APK, you can take this image Docker pull down to play, the default shell is SH, execute command to docker run -t-i golang:alpine /bin/sh enter the command line. After entering the env view environment variable, because its Gopath this environment variable is useful for subsequent environment deployment, you can see the environment variable Gopath default value is/go

2. Map the code file and install

Using the Add SRC/GO/SRC to map the host SCR file to the/GO/SRC directory, why is this/go/src directory? Yes, that's the path to the GOPATH environment variable above, because we need to perform the Go Install command later, otherwise we'll need to reset the Gopath to install the compiled binaries.
Note that the local host in the SRC directory of the organization of the file, to perform go install will strictly follow the file structure of the generated package, test is the program's main program, Glog is the use of open source log library, the entire file structure is as follows, because the main.go when importing the package is used "github.com/golang/glog"this path, so need to give it a reasonable path.

.├── Dockerfile└── src    ├── github.com    │   └── golang    │       └── glog    │           ├── glog_file.go    │           ├── glog.go    │           ├── glog_test.go    │           ├── LICENSE    │           └── README    └── test        └── main.go

There is also a small tips is the program's log library using third-party open-source Glog, when we use Git to version of our code to manage the time we do not need to repeat the code containing glog, directly add a reference to it can be, so there are many benefits, When the code in the library is modified and can be updated directly to the remote code repository, the library can be imported automatically at clone, which means that the specific code is pulled locally, but only the reference is saved in the remote repository.
You can generate glog this submodule by command: git submodule add https://github.com/golang/glog.git src/github.com/golang/glog . Note that the git remoule command is referenced to a location src/github.com/golang other than the direct one src/ , because the local code repository after executing the command will clone glog the code repository, pull its code down, and just create the Glog directory, so some of the previous parent directories need to be created by themselves. See Git For more information about commands.
Organize the file structure to go install, the generated executable in $gopath/bin, followed by the basic specified entry procedures and parameters. Through Docker build-t= "name". Generate image

3. Further: Compile ahead

The way to do this is to copy the code into the underlying image and compile it internally, without a doubt that Golang:alpine contains a series of dependencies on the running of the program, which dynamically loads the libraries, and we can use the LDD command to see the dependencies of the generated binaries:

linux-vdso.so.1 =>  (0x00007ffc5b1e4000)libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f50a1f13000)libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f50a1b4a000)/lib64/ld-linux-x86-64.so.2 (0x00005611a4b0a000)

So that's the problem? If these dependencies are statically compiled into the executable file, then you do not need to save the extra information in the environment, so you can create a smaller image. Fortunately, both the Golang compilation mechanism and the Docker's underlying image provide such an implementation:
To generate a statically compiled binary file by using a command:CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
At this point, with LDD to see the dependencies of the generated executables, you can see the display not a dynamic executable , where we disable CGO to generate a static binary file, while setting the system to Linux. We set the base image to scratch, which is a very small image.
The re-written dockerfile is as follows:

FROM scratchADD main /ENTRYPOINT ["/main"]CMD ["-logtostderr"]

Execute Docker build-t example-scratch. To generate the image, you can see that the size of the image is only 8.27M in size and can be performed normally. The
is sometimes used in practice in conjunction with two situations, first built in one image and executed in another. The following dockerfile from Prometheus, a dockerfile of this third-party monitoring demonstration, can be seen to first download the corresponding dependencies in the builder image and compile the program, and finally execute the program in the scratch base image.

# This Dockerfile builds an image for a client_golang example.## Use as (from the root for the client_golang repository):jingx#    docker build -f examples/$name/Dockerfile -t prometheus/golang-example-$name .# Builder image, where we build the example.FROM golang:1.9.0 AS builderWORKDIR /go/src/github.com/prometheus/client_golangCOPY . .WORKDIR /go/src/github.com/prometheus/client_golang/prometheusRUN go get -dWORKDIR /go/src/github.com/prometheus/client_golang/examples/simpleRUN CGO_ENABLED=0 GOOS=linux go build -a -tags netgo -ldflags '-w'# Final image.FROM scratchLABEL maintainer "The Prometheus Authors <prometheus-developers@googlegroups.com>"COPY --from=builder /go/src/github.com/prometheus/client_golang/examples/simple .EXPOSE 8080ENTRYPOINT ["/simple"]

Reference

Building Minimal Docker Containers for Go applications

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.