打包 OCI 镜像
打包 OCI 镜像
该插件可以使用 Cloud Native Buildpacks (CNB) 从 jar 或 war 文件创建一个 OCI 镜像。镜像可以通过 bootBuildImage
任务来构建。
出于安全考虑,镜像会以非 root 用户身份构建和运行。详情请参阅 CNB 规范。
当应用 java
或 war
插件时,任务会自动创建,并且是 BootBuildImage 的一个实例。
Docker 守护进程
bootBuildImage
任务需要访问 Docker 守护进程。该任务将检查本地 Docker CLI 配置文件 以确定当前的 上下文,并使用上下文的连接信息与 Docker 守护进程进行通信。如果无法确定当前上下文或上下文没有连接信息,则任务将使用默认的本地连接。此功能在所有支持平台上与 Docker Engine 配合使用,无需额外配置。
可以通过设置环境变量来配置 bootBuildImage
任务,以使用替代的本地或远程连接。下表展示了环境变量及其对应的值:
环境变量 | 描述 |
---|---|
DOCKER_CONFIG | Docker CLI 配置文件 的位置,用于确定当前上下文(默认为 $HOME/.docker ) |
DOCKER_CONTEXT | 应从 Docker CLI 配置文件中检索主机信息的 上下文 名称(覆盖 DOCKER_HOST ) |
DOCKER_HOST | 包含 Docker 守护进程的主机和端口的 URL - 例如 tcp://192.168.99.100:2376 |
DOCKER_TLS_VERIFY | 当设置为 1 时启用安全的 HTTPS 协议(可选) |
DOCKER_CERT_PATH | HTTPS 证书和密钥文件的路径(如果 DOCKER_TLS_VERIFY=1 则为必需,否则忽略) |
Docker 守护进程的连接信息也可以通过插件配置中的 docker
属性来提供。下表总结了可用的属性:
有关更多详细信息,请参见 示例。
Docker 镜像仓库
如果 builder
或 runImage
属性指定的 Docker 镜像存储在需要身份验证的私有 Docker 镜像仓库中,可以使用 docker.builderRegistry
属性提供身份验证凭据。
如果生成的 Docker 镜像要发布到 Docker 镜像仓库,可以使用 docker.publishRegistry
属性来提供认证凭据。
提供了用于用户认证或身份令牌认证的属性。有关所支持的认证方法的更多信息,请参阅用于存储镜像的 Docker 仓库的文档。
下表总结了 docker.builderRegistry
和 docker.publishRegistry
的可用属性:
属性 | 描述 |
---|---|
username | Docker 镜像仓库用户的用户名。用户身份验证时必填。 |
password | Docker 镜像仓库用户的密码。用户身份验证时必填。 |
url | Docker 镜像仓库的地址。用户身份验证时可选。 |
email | Docker 镜像仓库用户的电子邮件地址。用户身份验证时可选。 |
token | Docker 镜像仓库用户的身份令牌。令牌身份验证时必填。 |
更多详情,请参见示例。
图片自定义
该插件调用一个 builder 来协调生成镜像的过程。Builder 包含多个 buildpacks,这些 buildpacks 可以检查应用程序以影响生成的镜像。默认情况下,插件会选择一个 builder 镜像。生成的镜像名称是根据项目属性推导出来的。
任务属性可用于配置构建器在项目上的操作方式。下表总结了可用属性及其默认值:
属性 | 命令行选项 | 描述 | 默认值 |
---|---|---|---|
builder | --builder | 要使用的构建器镜像名称。 | paketobuildpacks/builder-jammy-java-tiny:latest |
trustBuilder | --trustBuilder | 是否将构建器视为可信。 | true if the builder is one of paketobuildpacks/builder-jammy-java-tiny , paketobuildpacks/builder-noble-java-tiny , paketobuildpacks/builder-jammy-tiny , paketobuildpacks/builder-jammy-base , paketobuildpacks/builder-jammy-full , paketobuildpacks/builder-jammy-buildpackless-tiny , paketobuildpacks/builder-jammy-buildpackless-base , paketobuildpacks/builder-jammy-buildpackless-full , gcr.io/buildpacks/builder , heroku/builder ; false otherwise. |
imagePlatform | --imagePlatform | 任何拉取的构建器、运行和构建包镜像的平台(操作系统和架构)。必须采用 操作系统[/架构[/变体]] 的形式,例如 linux/amd64 、linux/arm64 或 linux/arm/v5 。请参考所使用的构建器的文档以确定可用的镜像操作系统和架构选项。 | 无默认值,表示应使用主机的平台。 |
runImage | --runImage | 用于运行的镜像名称。 | 没有默认值,表示应使用 Builder 元数据中指定的运行镜像。 |
imageName | --imageName | 生成的镜像的 Image name。 | docker.io/library/${project.name}:${project.version} |
pullPolicy | --pullPolicy | 策略用于确定何时从注册表中拉取构建器和运行镜像。可接受的值为 ALWAYS 、NEVER 和 IF_NOT_PRESENT 。 | ALWAYS |
environment | 应传递给构建器的环境变量。 | 空。 | |
buildpacks | 构建镜像时,构建器应使用的 Buildpacks。仅会使用指定的 Buildpacks,覆盖构建器中默认包含的 Buildpacks。Buildpack 引用必须采用以下形式之一: - 构建器中的 Buildpack - [urn:cnb:builder:]<buildpack ID>[@<version>] - 文件系统目录中的 Buildpack - [file://]<path> - 文件系统中 gzipped tar (.tgz) 文件中的 Buildpack - [file://]<path>/<file name> - OCI 镜像中的 Buildpack - [docker://]<host>/<repo>[:<tag>][@<digest>] | None ,表示构建器应该使用其中包含的构建包。 | |
bindings | 卷绑定挂载 在构建镜像时应挂载到构建器容器的绑定挂载。这些绑定将在创建构建器容器时以未解析和未验证的形式传递给 Docker。绑定必须采用以下形式之一: |
<主机源路径>:<容器目标路径>[:<选项>]
<主机卷名称>:<容器目标路径>[:<选项>]
其中 <选项>
可以包含:
ro
将卷挂载为容器中的只读
rw
将卷挂载为容器中的可读写
volume-opt=key=value
指定由选项名称及其值组成的键值对| |
|network
|--network
| 网络驱动 是构建容器将被配置使用的网络模式。提供的值在创建构建容器时将不经验证直接传递给 Docker。| |
|cleanCache
|--cleanCache
| 是否在构建前清理缓存。|false
|
|verboseLogging
| | 启用构建器操作的详细日志记录。|false
|
|publish
|--publishImage
| 是否将生成的镜像发布到 Docker 镜像仓库。|false
|
|tags
| | 一个或多个要应用于生成镜像的附加标签列表。提供给tags
选项的值应为完整的镜像引用。有关更多详细信息,请参阅 标签部分。| |
|buildWorkspace
| | 一个临时工作区,构建器(builder)和构建包(buildpacks)在镜像构建过程中将使用它来存储文件。其值可以是一个命名卷(named volume)或绑定挂载(bind mount)位置。| Docker 守护进程中的一个命名卷,其名称源自镜像名称。 |
|buildCache
| | 一个包含由 buildpacks 创建并在镜像构建过程中使用的层的缓存。该值可以是一个命名卷或绑定挂载位置。| Docker 守护进程中的一个命名卷,其名称来源于镜像名称。 |
|launchCache
| | 一个缓存,包含由构建包创建的层,并用于镜像启动过程。该值可以是一个命名卷或绑定挂载位置。| Docker 守护进程中的一个命名卷,其名称派生自镜像名称。 |
|createdDate
|--createdDate
| 用于设置生成图像元数据中Created
字段的日期。该值必须为 ISO 8601 即时格式的字符串,或使用now
表示当前日期和时间。| 一个固定的日期,用于实现构建可重现性。 |
|applicationDirectory
|--applicationDirectory
| 构建器镜像中应用程序内容将上传到的目录路径。生成的镜像中应用程序内容也将位于此位置。|/workspace
|
|securityOptions
|--securityOptions
| 将应用于构建容器的安全选项,以字符串数组的形式提供。|["label=disable"]
on Linux and macOS,[]
on Windows |
该插件通过 JavaPlugin 的 targetCompatibility
属性检测项目的目标 Java 兼容性。当使用默认的 Paketo 构建器和构建包时,插件会指示构建包安装相同的 Java 版本。你可以按照 builder 配置 示例中的说明覆盖此行为。
默认的构建器 paketobuildpacks/builder-jammy-java-tiny:latest
包含了一组精简的系统库,并且不包含 shell。如果应用程序需要一个 shell 来运行启动脚本(例如在应用了 application plugin 来生成分发 zip 存档的情况下),或者依赖于某个不存在的系统库,应该覆盖 builder
配置,使用一个包含 shell 和更广泛系统库的构建器,例如 paketobuildpacks/builder-jammy-base:latest
或 paketobuildpacks/builder-jammy-full:latest
。
标签格式
提供给 tags
选项的值应该是完整的镜像引用。接受的格式为 [domainHost:port/][path/]name[:tag][@digest]
。
如果域名缺失,默认使用 docker.io
。如果路径缺失,默认使用 library
。如果标签缺失,默认使用 latest
。
一些示例:
-
my-image
指向镜像引用docker.io/library/my-image:latest
-
my-repository/my-image
指向docker.io/my-repository/my-image:latest
-
example.com/my-repository/my-image:1.0.0
将直接使用
示例
自定义镜像构建器和运行镜像
如果你需要自定义用于创建镜像的构建器或用于启动构建镜像的运行镜像,请按照以下示例配置任务:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
builder = "mine/java-cnb-builder"
runImage = "mine/java-cnb-run"
}
tasks.named<BootBuildImage>("bootBuildImage") {
builder.set("mine/java-cnb-builder")
runImage.set("mine/java-cnb-run")
}
此配置将使用构建器镜像,其名称为 mine/java-cnb-builder
,标签为 latest
,以及运行时镜像,其名称为 mine/java-cnb-run
,标签为 latest
。
构建镜像和运行镜像也可以在命令行中指定,如下例所示:
$ gradle bootBuildImage --builder=mine/java-cnb-builder --runImage=mine/java-cnb-run
构建器配置
如果构建器暴露了配置选项,可以通过 environment
属性来设置这些选项。
以下是一个在构建时配置 Paketo Java buildpacks 使用的 JVM 版本 的示例:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
environment["BP_JVM_VERSION"] = "17"
}
tasks.named<BootBuildImage>("bootBuildImage") {
environment.put("BP_JVM_VERSION", "17")
}
如果 Docker 守护进程与构建器运行的网络位置之间存在网络代理,而构建包需要从这些位置下载工件,那么你需要配置构建器以使用代理。在使用 Paketo 构建器时,可以通过设置 HTTPS_PROXY
和/或 HTTP_PROXY
环境变量来实现,如下例所示:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
environment["HTTP_PROXY"] = "http://proxy.example.com"
environment["HTTPS_PROXY"] = "https://proxy.example.com"
}
tasks.named<BootBuildImage>("bootBuildImage") {
environment.putAll(mapOf("HTTP_PROXY" to "http://proxy.example.com",
"HTTPS_PROXY" to "https://proxy.example.com"))
}
运行时 JVM 配置
Paketo Java 构建包通过设置 JAVA_TOOL_OPTIONS
环境变量来配置 JVM 运行时环境。在容器中启动应用镜像时,可以通过修改构建包提供的 JAVA_TOOL_OPTIONS
值来自定义 JVM 运行时行为。
应在镜像中存储并应用于每个部署的环境变量修改可以按照 Paketo 文档 中的描述进行设置,如下例所示:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
environment["BPE_DELIM_JAVA_TOOL_OPTIONS"] = " "
environment["BPE_APPEND_JAVA_TOOL_OPTIONS"] = "-XX:+HeapDumpOnOutOfMemoryError"
}
tasks.named<BootBuildImage>("bootBuildImage") {
environment.putAll(mapOf(
"BPE_DELIM_JAVA_TOOL_OPTIONS" to " ",
"BPE_APPEND_JAVA_TOOL_OPTIONS" to "-XX:+HeapDumpOnOutOfMemoryError"
))
}
自定义镜像名称
默认情况下,镜像名称是从项目的 name
和 version
推断出来的,类似于 docker.io/library/${project.name}:${project.version}
。你可以通过设置任务属性来控制名称,如下例所示:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
imageName = "example.com/library/${project.name}"
}
tasks.named<BootBuildImage>("bootBuildImage") {
imageName.set("example.com/library/${project.name}")
}
请注意,此配置未提供明确的标签,因此会使用 latest
标签。您也可以指定一个标签,可以使用 ${project.version}
、构建中可用的任何属性或硬编码的版本。
镜像名称也可以在命令行中指定,如下例所示:
$ gradle bootBuildImage --imageName=example.com/library/my-app:v1
Buildpacks
默认情况下,构建器将使用构建器镜像中包含的构建包,并按照预定义的顺序应用它们。可以提供一组替代的构建包,以应用未包含在构建器中的构建包,或更改包含的构建包的顺序。当提供一个或多个构建包时,仅会应用指定的构建包。
以下示例指示构建器使用打包在 .tgz
文件中的自定义构建包,随后使用构建器中包含的构建包。
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
buildpacks = ["file:///path/to/example-buildpack.tgz", "urn:cnb:builder:paketo-buildpacks/java"]
}
tasks.named<BootBuildImage>("bootBuildImage") {
buildpacks.set(listOf("file:///path/to/example-buildpack.tgz", "urn:cnb:builder:paketo-buildpacks/java"))
}
Buildpacks 可以以以下任何一种形式指定。
位于 CNB Builder 中的一个 buildpack(如果 builder 中只有一个与 buildpack-id
匹配的 buildpack,则可以省略版本):
-
urn:cnb:builder:buildpack-id
-
urn:cnb:builder:buildpack-id@0.0.1
-
buildpack-id
-
buildpack-id@0.0.1
这是一个包含 buildpack 内容的目录路径(Windows 不支持):
-
file:///路径/到/buildpack/
-
/路径/到/buildpack/
一个指向包含构建包内容的 gzip 压缩 tar 文件的路径:
-
file:///path/to/buildpack.tgz
-
/path/to/buildpack.tgz
一个包含打包构建包的 OCI 镜像:
-
docker://example/buildpack
-
docker:///example/buildpack:latest
-
docker:///example/buildpack@sha256:45b23dee08…
-
example/buildpack
-
example/buildpack:latest
-
example/buildpack@sha256:45b23dee08…
镜像发布
生成的镜像可以通过启用 publish
选项发布到 Docker 注册表。
如果 Docker 注册表需要身份验证,可以使用 docker.publishRegistry
属性来配置凭据。如果 Docker 注册表不需要身份验证,则可以省略 docker.publishRegistry
配置。
镜像将发布到的注册表由镜像名称的注册表部分决定(在这些示例中为 docker.example.com
)。如果配置了 docker.publishRegistry
凭据并且包含 url
属性,该值将传递给注册表,但不会用于确定发布注册表的位置。
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
imageName.set("docker.example.com/library/${project.name}")
publish = true
docker {
publishRegistry {
username = "user"
password = "secret"
}
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
imageName.set("docker.example.com/library/${project.name}")
publish.set(true)
docker {
publishRegistry {
username.set("user")
password.set("secret")
}
}
}
发布选项也可以在命令行中指定,如下例所示:
$ gradle bootBuildImage --imageName=docker.example.com/library/my-app:v1 --publishImage
构建器缓存与工作区配置
CNB 构建器会缓存用于构建和启动镜像的层。默认情况下,这些缓存以命名卷的形式存储在 Docker 守护进程中,其名称源自目标镜像的完整名称。如果镜像名称经常变化,例如在镜像名称中使用项目版本作为标签,那么缓存可能会频繁失效。
缓存卷可以配置为使用替代名称,以便更好地控制缓存生命周期,如下例所示:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
buildCache {
volume {
name = "cache-${rootProject.name}.build"
}
}
launchCache {
volume {
name = "cache-${rootProject.name}.launch"
}
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
buildCache {
volume {
name.set("cache-${rootProject.name}.build")
}
}
launchCache {
volume {
name.set("cache-${rootProject.name}.launch")
}
}
}
构建器和构建包需要在镜像构建过程中存储临时文件的位置。默认情况下,这个临时的构建工作区存储在一个命名的卷中。
缓存和构建工作区可以配置为使用绑定挂载而不是命名卷,如下例所示:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
buildWorkspace {
bind {
source = "/tmp/cache-${rootProject.name}.work"
}
}
buildCache {
bind {
source = "/tmp/cache-${rootProject.name}.build"
}
}
launchCache {
bind {
source = "/tmp/cache-${rootProject.name}.launch"
}
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
buildWorkspace {
bind {
source.set("/tmp/cache-${rootProject.name}.work")
}
}
buildCache {
bind {
source.set("/tmp/cache-${rootProject.name}.build")
}
}
launchCache {
bind {
source.set("/tmp/cache-${rootProject.name}.launch")
}
}
}
Docker 配置
为 minikube 配置 Docker
该插件可以与 minikube 提供的 Docker 守护进程 进行通信,而不是默认的本地连接。
在 Linux 和 macOS 上,启动 minikube 后,可以使用命令 eval $(minikube docker-env)
来设置环境变量。
该插件还可以配置为使用 minikube 守护进程,通过提供类似于以下示例中所示的连接详细信息:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
docker {
host = "tcp://192.168.99.100:2376"
tlsVerify = true
certPath = "/home/user/.minikube/certs"
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
docker {
host.set("tcp://192.168.99.100:2376")
tlsVerify.set(true)
certPath.set("/home/user/.minikube/certs")
}
}
适用于 Podman 的 Docker 配置
该插件可以与 Podman 容器引擎 进行通信。
该插件可以通过提供类似于以下示例的连接详细信息来配置为使用 podman
本地连接:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
docker {
host = "unix:///run/user/1000/podman/podman.sock"
bindHostToBuilder = true
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
docker {
host.set("unix:///run/user/1000/podman/podman.sock")
bindHostToBuilder.set(true)
}
}
安装了 podman
CLI 后,可以使用命令 podman info --format='{{.Host.RemoteSocket.Path}}'
来获取此示例中显示的 docker.host
配置属性的值。
Colima 的 Docker 配置
该插件可以与 Colima 提供的 Docker 守护进程进行通信。可以通过以下命令设置 DOCKER_HOST
环境变量:
$ export DOCKER_HOST=$(docker context inspect colima -f '{{.Endpoints.docker.Host}}')
该插件也可以通过提供类似于以下示例中所示的连接详细信息来配置为使用 Colima 守护进程:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
docker {
host = "unix://${System.properties['user.home']}/.colima/docker.sock"
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
docker {
host.set("unix://${System.getProperty("user.home")}/.colima/docker.sock")
}
}
Docker 身份验证配置
如果构建器或运行镜像存储在支持用户身份验证的私有 Docker 注册表中,可以使用 docker.builderRegistry
属性提供身份验证详细信息,如下例所示:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
docker {
builderRegistry {
username = "user"
password = "secret"
url = "https://docker.example.com/v1/"
email = "user@example.com"
}
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
docker {
builderRegistry {
username.set("user")
password.set("secret")
url.set("https://docker.example.com/v1/")
email.set("user@example.com")
}
}
}
如果构建器或运行镜像存储在支持令牌认证的私有 Docker 注册表中,可以使用 docker.builderRegistry
提供令牌值,如下例所示:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
docker {
builderRegistry {
token = "9cbaf023786cd7..."
}
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
docker {
builderRegistry {
token.set("9cbaf023786cd7...")
}
}
}