By zhouzhipeng from blog.zhouzhipeng.com/dockerfile-… This article can be reproduced in full, but the original author and source need to be retained.

preface

Automatic construction is an essential link in the process of application release. The commonly used construction tools include Jenkins, Walle and so on. These tools often have the following problems when building applications:

  1. It is necessary to write shell commands for construction directly or indirectly, which is not easy to manage and has poor compatibility
  2. The above point may be relatively easy to solve, but the most deadly is: heavy dependence on such asjenkinsThe software environment of the host machine or packer, asgit.maven.javaEtc.

Ideally, different applications, such as Java applications, GO applications, PHP applications, and so on, can execute the build operations in parallel and without interference on a host that is responsible for the build, and the software environment, build process, and so on that depend on the build can be controlled by the developer.

So far, docker is probably the only one who can accomplish the above mission well.

In the Docker world, the build delivers the image, and the image is generated by the Dockerfile (unless you use docker Commit manually).

After Docker CE 17.05, there is an important feature called Multi-stage Build that will significantly increase your operational productivity!

This feature of Multi-stage Build will be explained in detail with practical cases as follows

Before multi-stage Build

The following demo uses Java Hello World as an example. The complete code is at: github.com/zhouzhipeng…

This is a standard Maven project with only the HelloWorld main class. The general construction idea is as follows:

  1. Compile and package projects in maven images
  2. Copy the JAR generated in Step 1
  3. Using the JAR obtained in Step 2, build and run the main class in the JAR in the JRE image

Dockerfile.build is used to compile and package jars

Maven :3.5.2-alpine MAINTAINER zhouZHIpeng <[email protected]> WORKDIR /app COPY.. # RUN MVN package -Dmaven.test.skip=trueCopy the code

Dockerfile.old is used to run the main class in the JAR

FROM openjdk:8-jre-alpine MAINTAINER zhouzhipeng <[email protected]> WORKDIR /app COPY Run CMD Java -cp docker-multi-stage-demo-1.0-snapshot.jar in the main class com.zhouzhipeng.HelloWorldCopy the code

Note that the docker-multi-stage-demo-1.0-snapshot. jar file associated with two dockerfiles requires another build.sh script to be connected.

build.sh

#! / usr/bin/env bash # 1. To construct a product with a jar of mirror docker build - t zhouzhipeng/dockermultistagedemo - build - f Dockerfile. Build. # 2. Temporary create dockermultistagedemo - build container docker create -- the name build zhouzhipeng/dockermultistagedemo - build # 3. Docker cp build:/app/target/ docker-multi-stage-demo-1.0-snapshot.jar./ # 4. Building Java implementation of mirror docker build - t zhouzhipeng/dockermultistagedemo - f Dockerfile. Old. # 5. Delete the temporary jar file rm -rf docker-multi-stage-demo-1.0-snapshot.jarCopy the code

Dockerfile and shell also understand the friends believe that should be able to understand, not to do too much verbose here.

After the Multi-state Build

After watching the last episode, you might feel a little bit of trouble? Yes, the trouble is that not only do you have to write multiple dockerfiles, but you also need a build.sh script to execute them in addition. Undoubtedly, it increases the complexity of building applications!

Dockerfile.build = dockerfile. old = dockerfile. build = dockerfile. old = dockerfile. build = dockerfile. old

FROM Maven :3.5.2-alpine as Builder MAINTAINER zhouZHIpeng <[email protected]> WORKDIR /app COPY src.copy pam.xml. Jar package generated path: /app/target) RUN mvn package -Dmaven.test.skip=true FROM openjdk:8-jre-alpine MAINTAINER zhouzhipeng <[email protected]> WORKDIR /app COPY --from=builder /app/target/ docker-multi-stage-Demo-1.0-snapshot.jar. # Run the main classes of CMD Java - cp docker - multi - stage - demo - 1.0 - the SNAPSHOT. Jar com. Zhouzhipeng. The HelloWorldCopy the code

Then, again, the familiar Docker build command

docker build -t zhouzhipeng/dockermultistagedemo-new .
Copy the code

Can.

If you are careful, you will notice that there are two differences in the above Dockerfile.

  1. There are multipleFROMstatements
  2. COPYCommand after many--from=builder

This is today’s main cafe multi-stage Build. First, let’s use a picture to get a sense of what a multi-stage Build is:

With a multi-stage build, you can keep the Dockerfile clean and readable while keeping the resulting image “clean.”

Simple to understand

Take the Dockerfile as an example, as shown below:

The sections in the red box can be seen as separate “stages”, which can be roughly imagined as a separate Dockerfile content.

As you know, image builds are layered on top of each other, from top to bottom, in the command line order of the Dockerfile. Therefore, the lower stage can refer to the upper stage. To facilitate the reference to the upper stage, we need to give it a name and use the AS operator.

The complete format of the FROM command is as follows:

FROM <image>[:<tag>] [AS <name>]
Copy the code

Stages interact with files, so the COPY command needs to be extended to specify which stage to COPY files from above. The complete command format is as follows:

COPY --from=<name|index> <src>... <dest> # Note that --from is optional and can be referenced in index(starting from 0) order when the upper stage has no name, eg. --from=0Copy the code

It is worth mentioning that by default, when a docker build command is used to build a dockerfile containing multiple stages, the final product is the image produced by the bottom stage.

Of course, if docker also supports building to specified stages for debugging reasons or other needs, you can only build Builder images using — Target Builder.

docker build -t zhouzhipeng/builder --target builder . 
Copy the code

The last step

So far, we have a Dockerfile that can be built with one click, now we just need to make it build automatically!

You can use Jenkins with github webhook to execute the docker build command once you submit the code.

Of course, I recommend using the official Docker Hub for personal experiences, because that way you can share your image with others.

The specific use of the Automated Build function of Docker Hub is not detailed, the following uses a GIF diagram to quickly demonstrate, interested friends can explore by themselves.

conclusion

The multi-stage Build feature is ideal for building pipeline flows, especially for applications that rely on complex environments and processes.

Clone the above source code to try oh: github.com/zhouzhipeng…

reference

Docs.docker.com/v17.09/engi…

Blog. Alexellis. IO/mutli – stage…