Automated build is an indispensable part of the application release process. Commonly used build tools are
walle and so on. These tools often have the following problems when building an app:
- Need to write a shell command for construction, etc., directly or indirectly, difficult to manage, poor compatibility
- The above point may be easier to solve, but the most deadly is: heavily dependent on the software environment such as
jenkinshost or baler, such as
The ideal situation is: Different applications, such as java applications, go applications, php applications, etc., can perform parallel and non-interfering execution operations on a host that is responsible for the build, and the software environment and build process depend on the build. Can be controlled by the developer.
So far, the mission can be done well, it may not be [docker] (https://blog.zhouzhipeng.com/category/docker)!
In the world of docker, the build is delivered with a
mirror, and the one that can be mirrored is
Dockerfile (manual use of
docker ce 17.05, there is a very important feature
Multi-Stage Build (multi-stage build), which will significantly increase your operational productivity!
The following will use the actual case to explain the feature of
Multi-Stage Buildin detail.
Before Multi-Stage Build
The following demo takes the example of
java hello world, the complete code is: [https://github.com/zhouzhipeng/docker-multi-stage-demo](https://github.com/zhouzhipeng/docker-multi-stage -demo)
This is a standard maven project with only one HelloWorld main class. The general construction idea is:
- Compile and package the project in the maven image
- Copy the jar generated in step 1
- Using the jar from step 2, build and run the main class in the jar in the jre image.
Dockerfile.build is used to compile and package jars
FROM maven: 3.5.2-alpine MAINTAINER zhouzhipeng <firstname.lastname@example.org> WORKDIR /app COPY . . #编译包装 RUN mvn package -Dmaven.test.skip=true
Dockerfile.old is used to run the main class in the jar
FROM openjdk: 8-jre-alpine MAINTAINER zhouzhipeng <email@example.com> WORKDIR /app COPY docker-multi-stage-demo-1.0-SNAPSHOT.jar . # Run main class CMD java -cp docker-multi-stage-demo-1.0-SNAPSHOT.jar com.zhouzhipeng.HelloWorld
Note that the docker-multi-stage-demo-1.0-SNAPSHOT.jar file associated with the two dockerfiles requires another build.sh script to string.
#!/usr/bin/env bash # 1. First build a mirror with the product jar Docker build -t zhouzhipeng/dockermultistagedemo-build -f Dockerfile.build . # 2. Temporarily create the dockermultistagedemo-build container Docker create --name build zhouzhipeng/dockermultistagedemo-build # 3. Copy the jar from the above container Docker cp build:/app/target/docker-multi-stage-demo-1.0-SNAPSHOT.jar ./ # 4. Build a mirror of java execution Docker build -t zhouzhipeng/dockermultistagedemo -f Dockerfile.old . # 5. Delete the temporary jar file Rm -rf docker-multi-stage-demo-1.0-SNAPSHOT.jar
Friends who know about Dockerfile and shell believe that they should understand it. Don’t repeat it here.
After Multi-Stage Build
After reading the previous section, you might feel a little trouble? Yes, the trouble is not only to write multiple dockerfiles, but also a build.sh script for extra execution. Undoubtedly increased the complexity of building applications!
Combine the above Dockerfile.build with Dockerfile.old and slightly modify it to get the following new Dockerfile:
FROM maven:3.5.2-alpine as builder MAINTAINER zhouzhipeng <firstname.lastname@example.org> WORKDIR /app COPY src . COPY pom.xml . # Compile and package (jar package generation path: /app/target) RUN mvn package -Dmaven.test.skip=true FROM openjdk: 8-jre-alpine MAINTAINER zhouzhipeng <email@example.com> WORKDIR /app COPY --from=builder /app/target/docker-multi-stage-demo-1.0-SNAPSHOT.jar . # Run main class CMD java -cp docker-multi-stage-demo-1.0-SNAPSHOT.jar com.zhouzhipeng.HelloWorld
Then, still the familiar docker build command
Docker build -t zhouzhipeng/dockermultistagedemo-new .
Careful, you should not find that there are two different places in the Dockerfile above.
FROMstatements have appeared
This is today’s main coffee
Multi-Stage Build, first come through a picture to intuitively feel what is called ‘Multi-Stage Build` (multi-stage build):
Through multi-stage build, you can keep the Dockerfile simple and easy to read, and make the final product image "clean".
Or the Dockerfile in the above example, as shown below:
The parts in the red box can be thought of as separate "stages", and you can roughly imagine that the achievement is a separate Dockerfile content.
Everyone knows that the mirror construction is superimposed layer by layer. According to the command line order of the Dockerfile, the overlay is performed from top to bottom. Therefore, the lower stage can be referenced to the upper stage. In order to facilitate reference to the upper stage, you need to give it a name, using the
The full format of the
FROM command is as follows:
FROM <image>[:<tag>] [AS <name>]
The interaction between the stages is a file, so the
COPY command needs to be extended. Use
--from= to specify which "stage" to copy the file from above. The complete command format is as follows:
COPY --from=<name|index> <src>... <dest> # 注意--from is optional. When the stage of the upper layer has no name, it can be referenced in the order of index (starting from 0), eg. --from=0
It’s worth mentioning that by default, using the
docker build command to build a dockerfile with multiple stages, the final product is the image generated by the bottom stage.
Of course, if for debugging reasons or other requirements, docker also supports building to the specified stage, using
--target builder to build only the builder image.
Docker build -t zhouzhipeng/builder --target builder .
So far, we have a Dockerfile that can be built with one click, and then it’s only allowed to build automatically!
You can use the familiar
jenkins with github’s webhook to implement the code once and execute the docker build command.
Of course, if I recommend a personal experience, use the official docker hub, because the images you build can be shared with others.
The specific use of the Docker hub’s automated build function is not explained in detail. Below is a quick demonstration with a gif diagram. Interested friends can explore it on their own.
to sum up
Multi-Stage Build feature is ideal for building pipeline flows, and is ideal for applications that rely on complex environments and complex processes.
You can try the above source code under clone: https://github.com/zhouzhipeng/docker-multi-stage-demo