Evaluate every instruction
If we want to optimize the build time, we need to know how much time each instruction takes. This is an example.
1 | # Copy from: https://stackoverflow.com/a/52191994 |
If you want to do the math, changing $(date) to $(date +%s) will help a lot.
Leverage build cache
- In most cases, simply comparing the instruction in the Dockerfile with one of the child images is sufficient. However, certain instructions require more examination and explanation.
- For the ADD and COPY instructions, the contents of the file(s) in the image are examined and a checksum is calculated for each file. The last-modified and last-accessed times of the file(s) are not considered in these checksums.
Here are two Dockerfiles.
1 | # do something ... |
1 | COPY requirements.txt requirements.txt |
As we know, we rarely change requirements.txt, and it may cost a lot of time during the build.
It’s proper to make it a cached layer.
In addition, package.json(in NodeJS) and go.mod(in Golang) should be copied before the real code.
Rules in Dockerfile
These rules are not mentioned in the official document. But it helps a lot to solve the problem.
Please use git tag
Some developers use git clone in their Dockerfile. That’s not blamable by itself — unless you ignore the git tag. Let me give you an example:
1 | RUN git clone https://github.com/tornadoweb/tornado.git |
It just works when you write the Dockerfile, but what’s wrong with this instruction?
This instruction doesn’t specify the tornado version. It means once you change the build machine, Docker will always use the latest tornado commit — it’s a disaster for the production environment.
Here is the right instruction. And you should also use version tag or something when you want to use wget or curl in the Dockerfile.
1 | RUN git clone -b 'v6.0.3' https://github.com/tornadoweb/tornado.git |
Simplest version for Compiled languages
Multi-stage builds make docker suitable for compiled languages, such as C++, Golang, Java.
Please refer to Use multi-stage builds🔗.
1 | FROM golang:1.7.3 |
Because an image is built during the final stage of the build process, you can minimize image layers by leveraging build cache.
Conclusion
- Different languages have their own building strategies to minimize the images.
- A good Dockerfile will ensure we get almost the same images even if we change the build machine.