We could notice there are several intermediate containers removed, they’re layers from the first stage and prepare the executable for the second stage.
Most importantly, the docker image size is below 12MB.
The most important factor is we changed the FROM image to alpine which is only 4.2MB, so the extra size is almost the size of the golang process.
Yeah, the base image could be smaller, FROM scratch is a base image that will make the next command to be the first layer in your image.
I changed the FROM alpine:latest to FROM scratch, the image size is 7MB now, but I would suggest using alpine because it’ll be hard for you in scratch if you want to debug within the container. So you’ll need a balance between the image size and functionality :)
Some pitfalls you may face
Unnecessary large build context
Docker build will send the build context to docker daemon at first, the context is default to the current directory, so please be sure the files in the current directory is necessary or is small enough. If the file size is big, it will affect docker build speed terribly.
Wrong command order
Just remember to put the stable layers before the changeable layers, because docker will cache the layers if they are not changed, it’s calculated by the hash value of their content.
1 2 3 4
FROM ubuntu COPY changeable.txt . RUN apt-get update && apt-get install curl RUN ...
In the above example, every time the changeable.txt is changed, it will rerun every commands after it and waste time doing the things it could prevent. Just turn to the following form.
1 2 3 4
FROM ubuntu RUN apt-get update && apt-get install curl RUN ... COPY changeable.txt .