【问题标题】:Generic Docker Image and Dockerfile for SpringBoot Apps using Gradle/Maven使用 Gradle/Maven 的 SpringBoot 应用程序的通用 Docker 映像和 Dockerfile
【发布时间】:2016-09-21 21:55:28
【问题描述】:

根据https://spring.io/guides/gs/spring-boot-docker/,我们可以使用应用程序的硬编码名称和版本为 SpringBoot 应用程序创建 Docker 映像。例如:

src/main/docker/Dockerfile

FROM frolvlad/alpine-oraclejdk8:slim
VOLUME /tmp
ADD gs-spring-boot-docker-0.1.0.jar app.jar
RUN sh -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

但是,更改应用程序的名称或版本会破坏您在 build.gradle 任务中放置的 Docker Build 命令。

build.gradle

task buildDocker(type: Docker, dependsOn: build) {
  push = true
  applicationName = jar.baseName
  dockerfile = file('src/main/docker/Dockerfile')
  doFirst {
    copy {
      from jar
      into stageDir
    }
  }
}

命令 gradle buildDocker 通过暂存应用程序中的 Dockerfile 和可执行 Jar 并执行“docker build”来构建映像。

问题

考虑到 Dockerfile 中的名称是静态的,如何更改此设置以在更改版本后不破坏我的构建,甚至在构建 docker 映像时更改我的 SpringBoot 应用程序的名称?

【问题讨论】:

    标签: gradle docker spring-boot dockerfile spring-boot-docker-plugin


    【解决方案1】:

    从 Dockerfile 回溯,我们可以只需要添加“app.jar”。所以,从

    ADD gs-spring-boot-docker-0.1.0.jar app.jar
    

    ADD app.jar app.jar
    

    这导致需要重命名或复制生成的可执行 Jar。此示例将可执行 jar 重命名为“app.jar”,因此可以轻松构建 docker 映像。可以在下面找到可以复制到要在 Gradle 中构建的任何 SpringBoot 应用程序的通用任务。

    build.gradle

    /**
     * Generic support for building docker images for SpringBoot Apps
     */
    task buildDocker(type: Docker, dependsOn: build) {
      push = false
      applicationName = rootProject.name
      dockerfile = file('src/main/docker/Dockerfile')
    
      doFirst {
        // Rename the app jar to "app.jar" so that the Dockerfile does not require renames
        copy {
          from "${project.buildDir}/libs"
          into stageDir
          include "${rootProject.name}-${version}.jar"
          rename("${rootProject.name}-${version}.jar", "app.jar")
        }
      }
    
      doLast {
        println "Run the Docker Container"
        println "docker run -ti -p 8080:8080 $project.group/$applicationName:$version"
      }
    } 
    

    最终生成的Dockerfile如下:

    src/main/docker/Dockerfile

    FROM frolvlad/alpine-oraclejdk8:slim
    MAINTAINER Marcello_deSales@intuit.com
    VOLUME /tmp
    ADD app.jar app.jar
    RUN sh -c 'touch /app.jar'
    ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
    

    命令“gradle buildDocker”将生成 docker 镜像,并且作为奖励,将打印完整的命令以供您执行应用程序(请注意,默认端口号是硬编码的,如果您更改该值,则必须更改)。

    【讨论】:

      【解决方案2】:

      适用于带有 Maven 的 SpringBoot 应用程序的通用多阶段 Dockerfile

      • 我使用多阶段构建而不是维护多个 dockerfile https://docs.docker.com/develop/develop-images/multistage-build 为 Springboot 应用程序开发了新版本的通用 Dockerfile
        • 这使用MavenGradle 也可以采用类似的方法。
      • 这会运行测试用例,然后构建运行时映像
        • 支持从运行测试中分离下载依赖项
        • 单独构建测试阶段docker build -t tests --target builder .
        • 默认使用代码覆盖率运行单元测试
        • 从开关 mvn -s settings.xml -Dtest="!*IT,!*IntegrationTest" -P jacoco test 运行集成测试。
      • 支持提供JAVA_PARAMSJAVA_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
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-29
      • 1970-01-01
      • 2021-10-30
      • 2019-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-08
      相关资源
      最近更新 更多