适用于带有 Maven 的 SpringBoot 应用程序的通用多阶段 Dockerfile
- 我使用多阶段构建而不是维护多个 dockerfile https://docs.docker.com/develop/develop-images/multistage-build 为 Springboot 应用程序开发了新版本的通用 Dockerfile
- 这使用
Maven。 Gradle 也可以采用类似的方法。
- 这会运行测试用例,然后构建运行时映像
- 支持从运行测试中分离下载依赖项
- 单独构建测试阶段
docker build -t tests --target builder .
- 默认使用代码覆盖率运行单元测试
- 从开关
mvn -s settings.xml -Dtest="!*IT,!*IntegrationTest" -P jacoco test 运行集成测试。
- 支持提供
JAVA_PARAMS 和JAVA_OPTS 用于调试和所需的任何内容
- 如果您在 Docker Swarm 或 Kubernetes Helm 中部署此映像。
- 提供 settings.xml 以指向您的 Maven 存储库服务器(公共或私有)
下面的构建将执行以下操作:
#
# Build stage to for building the Jar
#
FROM maven:3.2.5-jdk-8 as builder
MAINTAINER marcello.desales@gmail.com
# Only copy the necessary to pull only the dependencies from Intuit's registry
ADD ./pom.xml /opt/server/pom.xml
# As some entries in pom.xml refers to the settings, let's keep it same
ADD ./settings.xml /opt/server/settings.xml
WORKDIR /opt/server/
# Prepare by downloading dependencies
RUN mvn -s settings.xml -B -e -C -T 1C org.apache.maven.plugins:maven-dependency-plugin:3.0.2:go-offline
# Run the full packaging after copying the source
ADD ./src /opt/server/src
RUN mvn -s settings.xml install -P embedded -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -B -e -o -T 1C verify
# Building only this stage can be done with the --target builder switch
# 1. Build: docker build -t config-builder --target builder .
# When running this first stage image, just verify the unit tests
# Overriden them by removing the "!" for integration tests
# 2. docker run --rm -ti config-builder mvn -s settings.xml -Dtest="*IT,*IntegrationTest" test
CMD mvn -s settings.xml -Dtest="!*IT,!*IntegrationTest" -P jacoco test
#
# Build stage with the runtime jar and resources
#
FROM openjdk:8-jre-slim
# Copy from the previous stage
COPY --from=builder /opt/server/target/*.jar /tmp/
# Just rename the built version
RUN mkdir /runtime && \
find /tmp -name "*.jar" ! -name "*sources*" -exec cp -t /runtime {} + && \
mv /runtime/*.jar /runtime/server.jar && \
rm -f /tmp/*.jar
# Port used by the server
EXPOSE 8888
# This is to support HTTPS calls to
RUN apt-get update && apt-get install -y curl ca-certificates
RUN update-ca-certificates && \
mkdir -p /usr/share/ssl/certs && \
chmod 755 /usr/share/ssl/certs
# What to execute on docker run
ENTRYPOINT sh -c "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom \
$JAVA_PARAMS -jar /runtime/server.jar --server.port=8888 $SPRING_BOOT_APP_OPTS"
构建和运行测试
- 按照多阶段构建规范,我们现在可以只生成测试映像
- 对于多种类型的测试(单元、集成),您可以拆分执行。
因此,构建测试可以如下完成:
$ docker build -t generic-dockerfile:tests --target builder .
Sending build context to Docker daemon 16.82MB
Step 1/9 : FROM maven:3.2.5-jdk-8 as builder
---> 95dd59c15f5d
Step 2/9 : MAINTAINER marcello.desales@gmail.com
---> Using cache
---> e4edaeb48381
Step 3/9 : ADD ./pom.xml /opt/server/pom.xml
---> Using cache
---> b2d6d834b411
Step 4/9 : ADD ./settings.xml /opt/server/settings.xml
---> Using cache
---> 9b0964db2c9f
Step 5/9 : WORKDIR /opt/server/
---> Using cache
---> 542d0bd9d12f
Step 6/9 : RUN mvn -s settings.xml -B -e -C -T 1C org.apache.maven.plugins:maven-dependency-plugin:3.0.2:go-offline
---> Using cache
---> 3c2d8df6b52e
Step 7/9 : ADD ./src /opt/server/src
---> Using cache
---> 6d48dd3f9f85
Step 8/9 : RUN mvn -s settings.xml install -P embedded -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -B -e -o -T 1C verify
---> Using cache
---> 1c109d2026c4
Step 9/9 : CMD mvn -s settings.xml -Dtest="!*IT,!*IntegrationTest" -P jacoco test
---> Using cache
---> 45eac3094ea4
Successfully built 45eac3094ea4
Successfully tagged generic-dockerfile:tests
然后你就可以执行测试了:
$ docker run -ti generic-dockerfile:tests
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building spring-cloud-config-server 1.1.6-SNAPSHOT
[INFO] ------------------------------------------------------------------------
- 您还可以覆盖 CMD 参数以运行上述 Dockerfile 中记录的集成测试。
构建并运行应用程序
您可以像往常一样构建运行时映像
$ docker build -t generic-dockerfile .
done.
done.
Removing intermediate container e632d7c310f7
---> e9391a0ca21d
Step 16/16 : ENTRYPOINT sh -c "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom $JAVA_PARAMS -jar /runtime/server.jar --server.port=8888 $SPRING_BOOT_APP_OPTS"
---> Running in 849ba7ad3212
Removing intermediate container 849ba7ad3212
---> 909354984264
Successfully built 909354984264
Successfully tagged generic-dockerfile:latest
运行应用程序就这么简单
$ docker run -ti generic-dockerfile
ThisHost: getLocalHost says localHost="c34b2cedbebf/172.17.0.2" isLoopbackAddress=false
2018-04-19T19:15:41,180 3166 | INFO | internal.util.Version.<clinit>#30 ["background-preinit" {}] HV000001: Hibernate Validator 5.2.5.Final
2018-04-19T19:15:41,470 3456 | INFO | factory.annotation.AutowiredAnnotationBeanPostProcessor.<init>#155 ["main" {svr=c34b2cedbebf}] JSR-330 'javax.inject.Inject' annotation found and supported for autowiring