Although there were some articles about how to create a minimal go Docker image, I also wrote an article, but with the release of the new release of Go and the evolution of Docker itself, some techniques have changed, this article describes the latest way to create an ultra-small go image.
Image of a simple Go program
Let's start by creating a very simple Go program:
1234567 |
Package mainimport"FMT"func Main () {FMT. Println ("Hello World")} |
Running the following command creates an ultra-small image, which is our first way:
1 |
Goos=linux cgo_enabled=0go build-ldflags="-s-w" -o app app.goimport - App:latest |
The following section describes the compilation parameters
To view the image, the resulting image is only 1.21MB :
123 |
# Docker Images app REPOSITORY TAG IMAGE ID CREATED sizeapp latest b716e13758cd Seconds ago 1.21MB |
This command integrates the compilation, packaging, and input mirrors into a single command.
The second way is to use one of the Dockerfile files:
123 |
from Scratchadd app/cmd ["/app"] |
Run the following command to create a mirror:
View the generated image, also 1.21MB :
123 |
# docker Images app2 REPOSITORY TAG IMAGE ID CREATED SIZEapp2 latest 4e2af2ffb695 4 seconds ago 1.21MB |
The third Way is to use Docker's multistage function to compile in the image, Dockerfile files:
Dockerfile.multistage
1 |
- F Dockerfile.multistage. |
View the generated image, also ":
123 |
# docker Images app3 REPOSITORY TAG IMAGE ID CREATED SIZEapp3 latest 9177859dad64 seconds ago 1.21MB |
You can choose a way to generate images in combination with your situation.
Compiling go Programs
In the example above we use the following command to compile the Go program:
1 |
Goos=linux cgo_enabled=0 go build-ldflags="-s-w" -o app App.go |
You may also see the parameters in some other articles installsuffix :
1 |
goos= cgo_enabled= 0 -ldflags= "-s-w" -installsuffix cgo-o App App.go |
Since go 1.10, you no longer have to use installsuffix parameters (perhaps earlier versions), Go's core developer Ian Lance Taylor has confirmed this.
You may also have -a a parameter that forces the compiler to recompile the associated package, which you would not normally use.
-sIgnoring the symbol table and debugging information, -w ignoring the dwarf symbol table, through these two parameters, you can further reduce the size of the compiled program, more parameters can refer to go link, or go tool link -help (another useful command is go tool compile -help ).
You can also use the strip tool to crop the compiled go program.
The go is statically compiled, for CGO, if set CGO_ENABLED=0 , then completely statically compiled, no longer dependent on the dynamic library.
If you set up and CGO_ENABLED=0 use the standard library package in your code net , it is possible that the compiled image cannot be run and reported sh: /app: not found errors, even though /app the file actually exists and centos can be executed if the underlying image is changed or not ubuntu . This is a strange mistake, because:
By default net , the package uses a static-link library, such as libc
Knowing the reason, the solution is also simple, either a full static link or a libc library added to the underlying image.
Here are a few workarounds:
- Set up
CGO_ENABLED=0
- Compiling is net using pure go:
go build -tags netgo -a -v
- Use base image plus glibc (or equivalent library MUSL, UCLIBC), such as BUSYBOX:GLIBC, Alpine +
RUN apk add --no-cache libc6-compat , FROLVLAD/ALPINE-GLIBC
Some students have said that I do have to use CGO in my code, because I need to rely on a few C + + libraries. Currently there is no corresponding go library to replace, then you can use -extldflags "-static" , go tool link help introduced extldflags the function:
-extldflags Flags
Set space-separated flags to pass to the external linker.
-static means do not link against shared libraries
Base image
In fact, there are some common base images listed earlier:
- Scratch: Empty base image, minimum base image
- BusyBox: With some common tools, easy to debug, and some of its extensions BUSYBOX:GLIBC
- Alpine: Another common base image with package management features for easy download of other dependent packages
Obviously. You should only use the go mirror during the compilation phase to minimize your image.