打包 OCI 镜像
打包 OCI 镜像
- Docker Daemon
- Docker Registry
- Image Customizations
- Tags Format
- Examples
- Custom Image Builder and Run Image
- Builder Configuration
- Runtime JVM Configuration
- Custom Image Name
- Buildpacks
- Image Publishing
- Builder Cache and Workspace Configuration
- Docker Configuration
该插件可以使用 Cloud Native Buildpacks(CNB)从 jar 或 war 文件创建一个 OCI 镜像。可以使用 bootBuildImage 任务来构建镜像。
出于安全原因,镜像以非 root 用户构建和运行。更多详情请参见 CNB 规范。
当应用 java 或 war 插件时,该任务会自动创建,并且是 BootBuildImage 的一个实例。
Docker Daemon
bootBuildImage 任务需要访问 Docker daemon。该任务会检查本地 Docker CLI 的 配置文件,以确定当前的 context,并使用该 context 的连接信息与 Docker daemon 通信。如果无法确定当前 context,或者该 context 没有连接信息,则任务将使用默认的本地连接。这种方式在所有受支持的平台上无需额外配置即可与 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 daemon 的连接信息也可以通过插件配置中的 docker 属性提供。下表总结了可用的属性:
更多详情,请参见 示例。
Docker Registry
如果 builder 或 runImage 属性指定的 Docker 镜像存储在需要身份验证的私有 Docker 镜像仓库中,则可以使用 docker.builderRegistry 属性提供身份验证凭据。
如果要将生成的 Docker 镜像发布到 Docker 镜像仓库,可以使用 docker.publishRegistry 属性提供身份验证凭据。
提供了用于用户认证或身份令牌(identity token)认证的属性。有关所支持的认证方法的更多信息,请参阅用于存储镜像的 Docker registry 的文档。
下表总结了 docker.builderRegistry 和 docker.publishRegistry 的可用属性:
| Property | Description |
|---|---|
username | Docker 镜像仓库用户的用户名。用户认证时必需。 |
password | Docker 镜像仓库用户的密码。用户认证时必需。 |
url | Docker 镜像仓库的地址。用户认证时可选。 |
email | Docker 镜像仓库用户的电子邮件地址。用户认证时可选。 |
token | Docker 镜像仓库用户的身份令牌。令牌认证时必需。 |
更多详情,请参见 examples。
如果未提供凭证,该插件会读取用户现有的 Docker 配置文件(通常位于 $HOME/. docker/config.json)以确定认证方法。插件将使用这些方法,为所请求的镜像提供认证凭证。
该插件支持以下认证方法:
-
Credential Helpers:在 Docker 配置文件中配置的外部工具,用于为特定的 registry 提供凭证。例如,
osxkeychain或ecr-login等工具可处理某些 registry 的认证。 -
Credential Store:一种默认的备用机制,用于安全地存储和检索凭证(例如,Docker Desktop 使用的
desktop)。 -
Static Credentials:直接存储在 Docker 配置文件
auths部分中的凭证。
镜像定制
该插件调用一个 builder 来协调生成镜像。该 builder 包含多个 buildpacks,可以检查应用程序以影响所生成的镜像。默认情况下,插件会选择一个 builder 镜像。所生成镜像的名称由项目属性推断得出。
任务属性可用于配置构建器在项目上的操作方式。下表总结了可用的属性及其默认值:
| Property | 命令行选项 | 描述 | 默认值 |
|---|---|---|---|
builder | --builder | 要使用的构建器镜像的名称。 | paketobuildpacks/builder-noble-java-tiny:latest |
trustBuilder | --trustBuilder | 是否将该 builder 视为 trusted。 | true if the builder is one of paketobuildpacks/builder-noble-java-tiny, paketobuildpacks/builder-jammy-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 | 所拉取的任何 builder 镜像、运行镜像和 buildpack 镜像的平台(操作系统和架构)。格式必须为 OS[/architecture[/variant]],例如 linux/amd64、linux/arm64 或 linux/arm/v5。请参考所用 builder 的文档,以确定可用的镜像操作系统和架构选项。 | 无默认值,表示应使用主机机器的平台。 |
runImage | --runImage | 要使用的运行镜像的名称。 | 无默认值,表示应使用 Builder 元数据中指定的运行时镜像。 |
imageName | --imageName | 生成的镜像的 Image name。 | docker.io/library/${project.name}:${project.version} |
pullPolicy | --pullPolicy | 用于确定何时从注册表拉取 builder 镜像和 run 镜像的 Policy。可接受的值为 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,表示构建器应使用其中包含的 buildpacks。 | |
bindings | 构建镜像时应挂载到构建器容器的卷绑定挂载(Volume bind mounts)。这些绑定将在创建构建器容器时以未经解析和验证的形式直接传递给 Docker。绑定必须采用以下形式之一: - <host source path>:<container destination path>[:<options>]- <host volume name>:<container destination path>[:<options>]其中 <options> 可包含以下内容:- ro:将卷以只读方式挂载到容器中- rw:将卷以可读写方式挂载到容器中- volume-opt=key=value:指定由选项名称及其值组成的键值对 | ||
network | --network | 构建器容器将配置为使用的 网络驱动。所提供的值在创建构建器容器时将不经验证直接传递给 Docker。 | |
cleanCache | --cleanCache | 是否在构建前清理缓存。 | false |
verboseLogging | 启用构建器操作的详细日志记录。 | false | |
publish | --publishImage | 是否将生成的镜像发布到 Docker registry。 | false |
tags | 一个或多个要应用于生成镜像的附加标签列表。提供给 tags 选项的值应为完整的镜像引用。更多详情请参见 标签部分。 | ||
buildWorkspace | 一个临时工作区,将由 builder 和 buildpacks 在镜像构建过程中用于存储文件。该值可以是一个命名卷(named volume)或绑定挂载(bind mount)位置。 | Docker 守护进程中一个命名卷,其名称源自镜像名称。 | |
buildCache | 一个包含由 buildpacks 创建的层并被镜像构建过程使用的缓存。该值可以是一个命名卷或一个绑定挂载位置。 | Docker 守护进程中一个命名卷,其名称源自镜像名称。 | |
launchCache | 一个包含由 buildpacks 创建的层并被镜像启动过程使用的缓存。该值可以是一个命名卷或绑定挂载位置。 | Docker 守护进程中一个命名卷,其名称源自镜像名称。 | |
createdDate | --createdDate | 一个用于设置生成镜像元数据中 Created 字段的日期。该值必须是 ISO 8601 瞬时格式的字符串,或者使用 now 表示当前日期和时间。 | 一个固定日期,用于实现 构建可重现性。 |
applicationDirectory | --applicationDirectory | 应用程序内容将被上传到构建器镜像中的目录路径。在生成的镜像中,应用程序内容也将位于此位置。 | /workspace |
securityOptions | --securityOptions | 将应用于构建器容器的安全选项,以字符串值数组的形式提供 | ["label=disable"] on Linux and macOS, [] on Windows |
该插件使用 JavaPlugin 的 targetCompatibility 属性来检测项目的 Java 目标兼容性。当使用默认的 Paketo builder 和 buildpacks 时,该插件会指示 buildpacks 安装相同版本的 Java。你可以按照 builder 配置 示例中所示的方式覆盖此行为。
默认的构建器 paketobuildpacks/builder-noble-java-tiny:latest 包含一组精简的系统库,且不包含 shell。如果应用程序需要 shell 来运行启动脚本(例如,当应用了 application plugin 以生成分发 zip 归档文件时),或者依赖于某些未包含在该构建器中的系统库,则应覆盖 runImage 配置,改用包含 shell 和更完整系统库的镜像,例如 paketobuildpacks/ubuntu-noble-run: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将按原样使用
示例
自定义 Image Builder 和 Run Image
如果你需要自定义用于创建镜像的 builder,或用于启动构建后镜像的 run 镜像,可按照以下示例配置该任务:
- 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
Builder 配置
如果构建器暴露了配置选项,可以使用 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 daemon(builder 在其中运行)与 buildpacks 下载制品的网络位置之间存在网络代理,则需要配置 builder 以使用该代理。当使用 Paketo builder 时,可以通过设置 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 buildpack 通过设置 JAVA_TOOL_OPTIONS 环境变量来配置 JVM 运行时环境。当应用程序镜像在容器中启动时,可以修改 buildpack 提供的 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
默认情况下,builder 将使用 builder 镜像中包含的 buildpack,并按照预定义的顺序应用它们。也可以提供一组替代的 buildpack,以应用未包含在 builder 中的 buildpack,或更改已包含 buildpack 的顺序。当提供一个或多个 buildpack 时,将仅应用所指定的 buildpack。
以下示例指示 builder 使用一个打包在 .tgz 文件中的自定义 buildpack,然后使用 builder 中包含的 buildpack。
- 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 与 buildpack-id 匹配,则版本号可以省略):
-
urn:cnb:builder:buildpack-id -
urn:cnb:builder:buildpack-id@0.0.1 -
buildpack-id -
buildpack-id@0.0.1
指向包含 buildpack 内容的目录的路径(在 Windows 上不受支持):
-
file:///path/to/buildpack/ -
/path/to/buildpack/
一个指向包含 buildpack 内容的 gzip 压缩 tar 文件的路径:
-
file:///path/to/buildpack.tgz -
/path/to/buildpack.tgz
一个包含 打包的 buildpack 的 OCI 镜像:
-
docker://example/buildpack -
docker:///example/buildpack:latest -
docker:///example/buildpack@sha256:45b23dee08… -
example/buildpack -
example/buildpack:latest -
example/buildpack@sha256:45b23dee08…
镜像发布
通过启用 publish 选项,可以将生成的镜像发布到 Docker registry。
如果 Docker registry 需要身份验证,可以使用 docker.publishRegistry 属性配置凭据。如果 Docker registry 不需要身份验证,则可以省略 docker.publishRegistry 配置。
镜像将被发布到的 registry 由镜像名称中的 registry 部分决定(在这些示例中为 docker.example.com)。如果配置了 docker.publishRegistry 凭据并且其中包含 url 属性,则该值会传递给 registry,但不会用于确定发布 registry 的位置。
- 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
Builder 缓存和工作区配置
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")
}
}
}
构建器(Builders)和 buildpacks 在构建镜像时需要一个位置来存储临时文件。默认情况下,这个临时构建工作区存储在一个命名卷(named volume)中。
缓存和构建工作区可以配置为使用绑定挂载(bind mounts)而非命名卷(named volumes),如下例所示:
- 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 daemon 通信,而不是使用默认的本地连接。
在 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 daemon 进行通信。可以通过以下命令设置 DOCKER_HOST 环境变量:
$ export DOCKER_HOST=$(docker context inspect colima -f '{{.Endpoints.docker.Host}}')
该插件也可以通过提供类似以下示例所示的连接详细信息,配置为使用 Colima daemon:
- 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 配置
如果 builder 镜像或 run 镜像存储在支持用户认证的私有 Docker registry 中,可以使用 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")
}
}
}
如果 builder 镜像或 run 镜像存储在支持令牌认证的私有 Docker registry 中,则可以使用 docker.builderRegistry 提供令牌值,如下例所示:
- Groovy
- Kotlin
tasks.named("bootBuildImage") {
docker {
builderRegistry {
token = "9cbaf023786cd7..."
}
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
docker {
builderRegistry {
token.set("9cbaf023786cd7...")
}
}
}