SpringBoot 2 与 Docker - 多阶段构建

之前的 Dockerfile 假设胖 JAR 已在命令上构建。我们也可以使用多阶段构建在 Docker 中执行该步骤,将结果从一个镜像复制到另一个镜像。使用 Maven 的示例:

Dockerfile

FROM openjdk:8-jdk-alpine as build
WORKDIR /workspace/app

COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src

RUN ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]

第一个图像标记为 “build”,用于运行 Maven 并构建胖 jar,然后解压缩它。拆包也可以由 Maven 或 Gradle 完成(这是《入门指南》中采用的方法)- 确实没有太大区别,只是必须编辑构建配置并添加插件。

请注意,源代码以分为四层。后面的层包含构建配置和应用的源代码,而前面的层包含构建系统本身(Maven 包装器)。这是一个很小的优化,也意味着我们不必将 target 复制到 docker 镜像,即使是用于构建的临时目录也是如此。

因为必须在第一个 RUN 部分中重新创建 Maven 缓存,所以每个更改源代码的构建都会很慢。但是,我们拥有一个完全独立的构建,只要拥有 docker,任何人都可以运行该应用来运行我们的应用。这在某些环境中可能非常有用,例如,我们需要与不懂 Java 的人共享代码的时候。

实验特性

Docker 18.06 带有一些 “实验性” 功能,其中包括一种缓存构建依赖项的方法。要打开它们,我们需要在守护进程(dockerd) 中有一个标志,并且在运行客户端时还需要一个环境变量,然后可以在 Dockerfile 中添加第一行魔术:

Dockerfile

# syntax=docker/dockerfile:experimental

然后 RUN 指令接受一个新的标志 --mount。这是一个完整的示例:

Dockerfile

# syntax=docker/dockerfile:experimental
FROM openjdk:8-jdk-alpine as build
WORKDIR /workspace/app

COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src

RUN --mount=type=cache,target=/root/.m2 ./mvnw install -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]

然后运行它:

$ DOCKER_BUILDKIT=1 docker build -t myorg/myapp .
...
 => /bin/sh -c ./mvnw install -DskipTests              5.7s
 => exporting to image                                 0.0s
 => => exporting layers                                0.0s
 => => writing image sha256:3defa...
 => => naming to docker.io/myorg/myapp

使用实验性功能,我们可以在控制台上获得不同的输出,但是我们可以看到,一旦缓存变暖,Maven 构建现在只需要几秒钟而不是几分钟。

扫描二维码关注公众号,回复: 10711777 查看本文章

Dockerfile 配置的 Gradle 版本非常相似:

Dockerfile

# syntax=docker/dockerfile:experimental
FROM openjdk:8-jdk-alpine AS build
WORKDIR /workspace/app

COPY . /workspace/app
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean build
RUN mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*.jar)

FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/build/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]

这些功能处于试验性阶段时,用于打开和关闭 buildkit 的选项取决于我们所使用的 docker 版本。检查文档以了解我们拥有的版本(上面的示例对于 docker 18.0.6 是正确的)。

发布了231 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/stevenchen1989/article/details/105338221