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

  1. In the Dockerfile directory, unzip the maven-generated jar package

    unzip .jar -d app

  1. 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.

  1. 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

  1. Or, specify heap-related parameters directly. This method is inflexible and can be used when the memory size is exactly known.

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.

results matching ""

    No results matching ""