Docker Image
Official best practice documents
Best practices for writing Dockerfiles
Explicitly specify the docker image version
When building a docker image, it is recommended that you explicitly specify a tag that contains a version or other supplementary information.
If you do not specify a mirror tag, the latest is used by default. This approach is not beneficial to version management and has a certain impact on the application startup speed (each time you launch an application instance, you need to mirror the warehouse to check if the image is updated)
Reduce the size of the mirror
Use alpine version of the base image
alpine is a lightweight Linux distribution that is highly streamlined and contains basic tools, and its docker images are only 4-5M in size. Each development language and framework have a base image based on alpine, and when developing the image of one's own application, selecting these images as the underlying images can greatly reduce the volume of the images.
- Java(Spring Boot): - openjdk:8-jdk-alpine, openjdk:8-jre-alpine etc.
- Java(Tomcat) - tomcat:8.5-alpine etc.
- Nodejs - node:9-alpine, node:8-alpine etc.
- Python - python:3-alpine, python:2-alpine etc.
- PHP - based on php:7-fpm-alpine, php:5-fpm-alpine and other mirrors adding nginx, refer to https://hub.docker.com/r/trafex/alpine-nginx-php7/
- Ruby: ruby:2-alpine etc.
- Go/Executable File - directly based on the alpine mirror, the compiled executable file is mirrored. Because alpine is different from ordinary distributions such as Ubuntu/Centos, you need to compile and link the application code statically. For example, Go needs to close cgo: CGO_ENABLED=0 go build ...
- Static page - nginx:1-alpine etc.
Cleanup commands in Dockerfile
Each instruction of Dockerfile will generate a file layer. The installation and cleanup of components should be placed in a command. If they are separated, the cleanup command cannot play a role in reducing the image volume. For example, in the following statement, if you put the rm command In the second line, it is impossible to reduce the size of the file layer generated by the apk command.
apk --update add php7 && rm -rf /var/cache/apk/*
Reduce the image transfer size
When the docker builds a image, if there is no change in the contents of a command, it will use the last cache file layer. When uploading to the mirror warehouse, this layer will not need to be uploaded.
In order to take advantage of this to reduce the transfer size and speed up the pushing and pulling of images, you can add layer by layer when adding applications:
- Invariant or rarely changed large-volume dependent libraries and frequently modified own codes
- Because the cache is on the local machine running the docker build command, it is recommended to use a certain machine for docker build in order to use the cache (for more information, you may refer to https://runnable.com/blog/distributing-docker-cache-across-hosts)
The following is an example of building a Spring Boot application image to illustrate how to layer. Other types of applications, such as the Java WAR package and the Nodejs npm module can take a similar approach.
Building Spring Boot application image
In the Dockerfile directory, unzip the maven-generated jar package
unzip
.jar -d app
Dockerfile We divide the application content into 4 parts and COPY them to the image: the first 3 are basically unchanged, and the fourth is one's often-changing code. The last line is the way to start the spring boot application after decompression.
FROM openjdk:8-jre-alpine
LABEL maintainer "opl-xws@xiaomi.com"
COPY app/BOOT-INF/lib/ /app/BOOT-INF/lib/ COPY app/org /app/org COPY app/META-INF /app/META-INF
COPY app/BOOT-INF/classes /app/BOOT-INF/classes
EXPOSE 8080
CMD ["/usr/bin/java", "-cp", "/app", "org.springframework.boot.loader.JarLauncher"]
In relation to start command
Avoid using process managers
When an instance of an application crashes or exits abnormally, many process management programs do not exit. As a result, the platform cannot detect that the application is unavailable and cannot restart the application. Therefore, avoid using such a process manager to start image.
Java application
Java has some issues with container support. There are two ways to make Java applications aware of the memory constraints of the container and avoid memory overflows.
With the new version of JavaSE 8 (≥ 8u131), the start command plus the following parameters, the adaptive container memory limit (the MaxRAMFraction parameter needs to be adjusted according to the actual situation, 1 is not a universal value)
-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1
- Or, specify heap-related parameters directly. This method is inflexible and can be used when the memory size is exactly known.
Related to application
Avoid using local storage
After the application image is started, the file system is temporary and is destroyed after crash. Persistent data and files, among others, need to be stored in SDS, FDS and other back-end storage services
Logs
Application logs cannot be written to local files and need to be written to standard output or standard errors. The platform is responsible for collecting, summarizing, and subsequent processing.