Millet Porridge

English version of https://corvo.myseu.cn

0%

Docker Series 6: Dockerfile advanced

Evaluate every instructions

If we want to optimize the build time. We need to know how much time the very instructions take. This is an example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Copy from: https://stackoverflow.com/a/52191994
docker build . -t test --no-cache | while read line ; do echo "$(date)| $line"; done;

Fri 08 Nov 2019 09:20:54 AM HKT| Sending build context to Docker daemon 8.192kB
Fri 08 Nov 2019 09:20:55 AM HKT| Step 1/5 : FROM node:10.17.0-alpine
Fri 08 Nov 2019 09:20:55 AM HKT| ---> 0aa7bb41deca
Fri 08 Nov 2019 09:20:55 AM HKT| Step 2/5 : COPY main.js main.js
Fri 08 Nov 2019 09:20:55 AM HKT| ---> 05c746d8951a
Fri 08 Nov 2019 09:20:55 AM HKT| Step 3/5 : COPY full-run.sh /run.sh
Fri 08 Nov 2019 09:20:55 AM HKT| ---> 3a44ba811766
Fri 08 Nov 2019 09:20:55 AM HKT| Step 4/5 : RUN chmod +x /run.sh
Fri 08 Nov 2019 09:20:56 AM HKT| ---> Running in 2ceec4735960
Fri 08 Nov 2019 09:20:57 AM HKT| Removing intermediate container 2ceec4735960
Fri 08 Nov 2019 09:20:57 AM HKT| ---> 8baf4c5d9284
Fri 08 Nov 2019 09:20:57 AM HKT| Step 5/5 : ENTRYPOINT ["/run.sh"]
Fri 08 Nov 2019 09:20:57 AM HKT| ---> Running in 1ebf29aa5b85
Fri 08 Nov 2019 09:20:57 AM HKT| Removing intermediate container 1ebf29aa5b85
Fri 08 Nov 2019 09:20:57 AM HKT| ---> 9cb776220122
Fri 08 Nov 2019 09:20:57 AM HKT| Successfully built 9cb776220122
Fri 08 Nov 2019 09:20:57 AM HKT| Successfully tagged test:latest

If you want to make calculate, change $(date) to $(date +%s) will help a lot.

Leverage build cache

Leverage build cache

  1. 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.
  2. 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
2
3
4
5
# do something ...
COPY main.py main.py

COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
1
2
3
4
5
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

# do something ...
COPY main.py main.py

As we know, we rarely change requirements.txt, and it may cost a lot of times during the build. It’s proper to make it as a cached layer.

In addition, package.json(in NodeJS) and go.mod(in Golang) should be copied before the real code is done.

Rules in Dockerfile

These rules are not mentioned in the offical document. But it help a lot to solve the problem.

Please use git tag

Some developers use git clone in their Dockerfile. It should not blame unless you ignore the git tag. Let me give you an example:

1
RUN git clone https://github.com/tornadoweb/tornado.git

It’s just work when you write the Dockerfile, btt 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 lateast tornado commit, it’s a disaster for the prodction 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

The multi-stage builds makes the docker to be suitable for Compiled languages, such as C++, Golang, Java.

Please refer to Use multi-stage builds🔗,

1
2
3
4
5
6
7
8
9
10
11
FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]

Because an image is built during the final stage of the build process, you can minimize image layers by leveraging build cache.

Conclution

  1. Different languages have their own building strategies to minimize the images.
  2. A good Dockerfile will ensure we get the almost same images even if we change the build machine.