Dockerfile Best Practices have appeared in the official documentation, address is Best Practices for Writing Dockerfiles. Writing a list of best practices would be a bit of a sword in front of the gate. Therefore, this article is a translation, understanding, extension and sample supplement to the official documentation
- Dockerfile best practices
- Series of articles: Personal server operation and maintenance guide
If this article helps you, please click a star on shfshanyue/op-note for me
Containers should be ephemeral
The container started by an image built from a Dockerfile should be as ephemeral as possible. Ephemeral means it can start and stop quickly
Use.dockerignore to rule out building irrelevant files
The.dockerignore syntax is consistent with the.gitignore syntax. Use it to exclude building irrelevant files and directories, such as node_modules
Use multi-phase builds
Multi-stage builds can effectively reduce image size, especially for compiled languages, and the build process for an application is often as follows
- Installing the Compilation tool
- Install third-party library dependencies
- Build the application
There is a lot of mirror volume redundancy in the first two steps, which can be avoided by using a multi-stage build
This is an example of building a Go application
FROM golang:1.11-alpine AS build
# Install tools required for project
# Run `docker build --no-cache .` to update dependencies
RUN apk add --no-cache git
RUN go get github.com/golang/dep/cmd/dep
# List project dependencies with Gopkg.toml and Gopkg.lock
# These layers are only re-built when Gopkg files are updated
COPY Gopkg.lock Gopkg.toml /go/src/project/
WORKDIR /go/src/project/
# Install library dependencies
RUN dep ensure -vendor-only
# Copy the entire project and build it
# This layer is rebuilt when a file changes in the project directory
COPY . /go/src/project/
RUN go build -o /bin/project
# This results in a single layer image
FROM scratch
COPY --from=build /bin/project /bin/project
ENTRYPOINT ["/bin/project"]
CMD ["--help"]
Copy the code
This is an example of building a front-end application. See how to deploy a front-end application efficiently with Docker
FROM node:10-alpine as builder
ENV PROJECT_ENV production
ENV NODE_ENV production
# http-server can also take advantage of caching without changing
WORKDIR /code
ADD package.json /code
RUN npm install --production
ADD . /code
RUN npm run build
# Select a smaller volume base image
FROM nginx:10-alpine
COPY --from=builder /code/public /usr/share/nginx/html
Copy the code
Avoid installing unnecessary packages
Reduce volume and build time. For example, the front-end application uses NPM install –production to only install packages that the production environment depends on.
A container does one thing
For example, a Web application will contain three parts, Web service, database and cache. Decouple them into multiple containers for horizontal scaling. If you need network communication, you can put them under one network.
For example, IN my personal server, I use Traefik for load balancing and service discovery. All applications and databases are in traefik_default network. For details, see Traefik for load balancing and service discovery
version: '3'
services:
This image will expose its own 'header' information
whoami:
image: containous/whoami
restart: always
labels:
Set Host to whoami.docker. Localhost for domain access
- "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
# Use the existing traefik network
networks:
default:
external:
name: traefik_default
Copy the code
Reduce the number of mirror layers
- only
RUN
.COPY
.ADD
Creates the number of layers. Other instructions do not increase the size of the mirror - Use multi-phase builds whenever possible
Use the following method to install dependencies
RUN yum install -y node python go
Copy the code
Wrong way to install dependencies, which will increase the number of mirror layers
RUN yum install -y node
RUN yum install -y python
RUN yum install -y go
Copy the code
Sort multiple rows of arguments
Easy readability and careful repacking
RUNapt-get update && apt-get install -y \ bzr \ cvs \ git \ mercurial \ subversionCopy the code
Take full advantage of the build cache
During the construction process of the image, Docker will traverse all instructions in the Dockerfile file and execute them in sequence. For each instruction, Docker looks in the cache to see if a reusable image already exists, or creates a new one
We can skip the cache using docker build –no-cache
ADD
和COPY
The file will be computedchecksum
Whether to change to determine whether to take advantage of the cacheRUN
Just see if the command string hits the cache, as inRUN apt-get -y update
There could be problems
For example, a Node application can copy package.json for dependency installation and then add the entire directory to make full use of the cache.
FROM node:10-alpine as builder
WORKDIR /code
ADD package.json /code
# This step will take full advantage of the node_modules cache
RUN npm install --production
ADD . /code
RUN npm run build
Copy the code
I am Shanyue94, you can add my wechat shanyue94 to communicate with me