This page looks best with JavaScript enabled

Docker Tips You Didn't Know

 ·  ☕ 3 min read

1. Multi-Stage Builds

Compiling a project requires a set of specific tools, but those tools are not needed at runtime. To reduce the image size, you can build in stages. Build in the first stage, then carry the compiled output into the next stage to produce a smaller image.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
FROM golang:1.12 as builder

COPY / /go/src/github.com/shaowenchen/goproject

WORKDIR /go/src/github.com/shaowenchen/goproject
RUN CGO_ENABLED=0 GO111MODULE=on GOOS=linux GOARCH=amd64 GOFLAGS=-mod=vendor go build -i -ldflags '-w -s' -o myserver cmd/myserver/apiserver.go

FROM alpine:3.9
RUN apk add --update ca-certificates && update-ca-certificates
COPY --from=builder /go/src/github.com/shaowenchen/goproject/myserver /usr/local/bin/
CMD ["sh"]

The above is a Dockerfile that compiles an image for a Go project. Many projects choose alpine as the base image. However, if the project uses certain system libraries, the base image cannot be chosen arbitrarily.

2. Building with the Cache

Docker images have a layered structure, with a maximum of 127 layers. Except for the FROM instruction, every other instruction in a Dockerfile produces a new image layer. During a build, if Docker finds that an instruction will produce a layer identical to one from before, it reuses the cached layer.

To use the cache to speed up the build, put static setup and configuration instructions early and frequently changing content late.

1
2
3
4
5
6
FROM stackaero/nodejs-pm2-slim:1.1.5
WORKDIR /app
COPY package.json /app/
RUN npm install
COPY . /app/
CMD pm2 start ./index.js --no-daemon >> /dev/null

Because the project’s source code always changes on every build, it should go as close to the bottom as possible; dependency packages do not change often, so putting them at the top makes full use of the cache.

Use the following build command to disable the cache:

1
docker build --no-cache

3. Packaging Applications with S2I

Compared with using the cache to optimize build speed, a simpler approach is to package the application with S2I, adding just one image layer.

Reference link: Building Cloud Native Applications with S2I

It does not matter if a language or framework is not supported by S2I — we can package the base environment the application needs into a base image, then build on top of it.

4. The .dockerignore File

Docker works on a C/S model: when you run a build, it sends the required files to the Docker Daemon. Some files are very large and unused by the build, and they consume transfer time. We can define a .dockerignore to ignore these files, just like .gitignore.

The .dockerignore file

.git

The Dockerfile

1
2
3
FROM golang:1.12 as builder

COPY / /go/src/github.com/shaowenchen/goproject

In the example above, the COPY ignores the .git directory.

5. Saving a Container as an Image

When learning Docker, you are often taught not to make any changes inside a container. That is correct — it follows immutable infrastructure.

Besides packaging images, we also go straight into containers to debug. Sometimes, for historical reasons, the image or Dockerfile cannot be found, and the container needs to be saved as an image.

Running the docker commit command saves ContainerID as the shaowenchen/myimage:latest image.

1
docker commit ContainerID  shaowenchen/myimage:latest

WeChat Official Account
WRITTEN BY
WeChat Official Account