如果我们不想直接在构建中调用 docker
,那么 Maven 和 Gradle 有很多丰富的插件可以为我们工作。这里仅仅是少数。
Spring Boot 插件
使用 Spring Boot 2.3,我们可以选择直接使用 Spring Boot 从 Maven 或 Gralde 构建镜像。只要我们已经在构建 Spring Boot jar 文件,我们只需要直接调用插件即可。使用 Maven:
$ ./mvnw spring-boot:build-image
及 Gradle:
$ ./gradlew bootBuildImage
它使用本地 docker 守护进程(因此必须安装),但不需要 Dockerfile
。结果是默认情况下名为 docker.io/<group>/<artifact>:latest
的镜像。我们可以使用以下方法在 Maven 中修改镜像名称:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<name>myorg.demo</name>
</image>
</configuration>
</plugin>
</plugins>
</build>
</project>
以及在 Gradle 中使用:
bootBuildImage {
builder = "myorg/demo"
}
该镜像是使用 Cloud Native Buildpacks 构建的,其中默认构建器针对 Spring Boot 应用进行了优化(我们可以对其进行自定义,但是默认设置很有用)。像上面的示例一样,镜像可以有效地分层。它还使用 CF 内存计算器根据运行时的可用容器资源在运行时调整 JVM 的大小,因此在运行镜像时,我们将看到内存计算器报告其结果:
$ docker run -p 8080:8080 myorg/demo
Container memory limit unset. Configuring JVM for 1G container.
Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=86557K -XX:ReservedCodeCacheSize=240M -Xss1M -Xmx450018K (Head Room: 0%, Loaded Class Count: 12868, Thread Count: 250, Total Memory: 1073741824)
...
Spotify Maven 插件
Spotify Maven 插件是一个受欢迎的选择。它要求应用开发人员编写一个 Dockerfile
,然后为我们运行 docker
,就像我们在命令行上操作一样。docker image 标签及其他内容有一些配置选项,但它使我们的应用中的 docker 知识集中在 Dockerfile
中,这是很多人喜欢的。
对于真正的基本用法,它无需额外配置即可直接使用:
$ mvn com.spotify:dockerfile-maven-plugin:build
...
[INFO] Building Docker context /home/dsyer/dev/demo/workspace/myapp
[INFO]
[INFO] Image will be built without a name
[INFO]
...
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.630 s
[INFO] Finished at: 2018-11-06T16:03:16+00:00
[INFO] Final Memory: 26M/595M
[INFO] ------------------------------------------------------------------------
这将构建一个匿名 docker
镜像。我们现在可以在命令行上使用 docker 对其进行标记,或者使用 Maven 配置将其设置为 repository
。示例(而不更改 pom.xml
):
$ mvn com.spotify:dockerfile-maven-plugin:build -Ddockerfile.repository=myorg/myapp
或更改 pom.xml:
pom.xml
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.8</version>
<configuration>
<repository>myorg/${project.artifactId}</repository>
</configuration>
</plugin>
</plugins>
</build>
Palantir Gradle 插件
Palantir Gradle 插件与 Dockerfile
一起使用,并且还能够为我们生成 Dockerfile
,然后像在命令行上一样运行 docker
。
首先,我们需要将插件导入到 build.gradle
中:
build.gradle
buildscript {
...
dependencies {
...
classpath('gradle.plugin.com.palantir.gradle.docker:gradle-docker:0.13.0')
}
}
然后最后应用插件并调用其任务:
build.gradle
apply plugin: 'com.palantir.docker'
group = 'myorg'
bootJar {
baseName = 'myapp'
version = '0.1.0'
}
task unpack(type: Copy) {
dependsOn bootJar
from(zipTree(tasks.bootJar.outputs.files.singleFile))
into("build/dependency")
}
docker {
name "${project.group}/${bootJar.baseName}"
copySpec.from(tasks.unpack.outputs).into("dependency")
buildArgs(['DEPENDENCY': "dependency"])
}
在该示例中,我们选择在 build
目录中的特定位置解压缩 Spring Boot 胖 jar,该目录是 docker 构建的根目录。然后,上面的多层(不是多阶段)Dockerfile
将起作用。
Jib Maven 和 Gradle 插件
Google 有一个名为 Jib 的开源工具,它相对较新,但出于多种原因却很有趣。也是最有趣的事情是我们不需要 docker
来运行它 - 它使用与从 docker build
获得的相同的标准输出来构建镜像,但是除非我们要求,否则不使用 docker - 因此它可以在以下环境中工作 - 没有安装 docker(在构建服务器中并不罕见)。我们也不需要 Dockerfile
(无论如何都会被忽略)或 pom.xml
中的任何内容来获取在 Maven 中构建的镜像(Gradle 要求我们至少在 build.gradle
中安装插件)。
Jib 的另一个有趣的功能是,它对层有所了解,并且以与上面创建的多层 Dockerfile
稍有不同的方式优化了它们。就像在胖 jar 中一样,Jib 将本地应用资源与依赖项分离开来,但他走的更远,而且还将快照依赖项放入一个单独的层中,因为它们很可能会发生变化。有一些配置选项可用于进一步自定义布局。
Maven 示例(不更改 pom.xml
):
$ mvn com.google.cloud.tools:jib-maven-plugin:build -Dimage=myorg/myapp
要运行上述命令,我们将需要具有在 myorg
存储库前缀下推送到 Dockerhub 的权限。如果我们已在命令行上通过 docker
进行了身份验证,则可以从本地 ~/.docker
配置中取得并生效。我们也可以在 ~/.m2/settings.xml
中设置 Maven “服务器” 身份验证(存储库的 id
很重要):
settings.xml
<server>
<id>registry.hub.docker.com</id>
<username>myorg</username>
<password>...</password>
</server>
还有其他选择,例如,我们可以使用 dockerBuild
目标而不是 build
来针对 docker
守护进程本地构建(例如在命令行上运行 docker)。还支持其他容器注册表,对于每个容器注册表,我们还需要通过 docker 或 Maven 设置来搭建本地身份验证。
一旦在 build.gradle
中将 gradle 插件包含类似功能,例如:
build.gradle
plugins {
...
id 'com.google.cloud.tools.jib' version '1.8.0'
}
或使用入门指南中使用的较旧样式:
build.gradle
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
mavenCentral()
}
dependencies {
classpath('org.springframework.boot:spring-boot-gradle-plugin:2.2.1.RELEASE')
classpath('com.google.cloud.tools.jib:com.google.cloud.tools.jib.gradle.plugin:1.8.0')
}
}
然后我们可以用:
$ ./gradlew jib --image=myorg/myapp
与 Maven 构建一样,如果我们已在命令行上通过 docker
进行了身份验证,则镜像推送将从我们的本地 ~/.docker
配置进行身份验证。