打包OCI镜像

该插件可以使用 Cloud Native Buildpacks (CNB) 从jar或war文件创建 OCI image。 可以通过 bootBuildImage 任务构建镜像。

出于安全考虑,镜像的构建和运行均以非root用户身份进行。 详见 CNB规范

当应用了 javawar 插件时,该任务会被自动创建,并且是 BootBuildImage 的一个实例。

Docker Daemon

bootBuildImage 任务需要访问Docker守护进程。 该任务会检查本地Docker CLI的 配置文件,以确定当前的 context,并使用该context的连接信息与Docker守护进程通信。 如果无法确定当前context,或context没有连接信息,则该任务会使用默认的本地连接。 这在所有受支持平台上的 Docker Engine下无需配置即可工作。

可以通过设置环境变量来配置 bootBuildImage 任务使用本地或远程连接。 下表展示了可用的环境变量及其含义:

Environment variable Description

DOCKER_CONFIG

用于确定当前context的Docker CLI 配置文件位置(默认为 $HOME/.docker

DOCKER_CONTEXT

应用于从Docker CLI配置文件获取主机信息的 context名称(会覆盖 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守护进程连接信息。 下表总结了可用的属性:

Property Description

context

用于从Docker CLI 配置文件获取主机信息的 context名称

host

Docker守护进程的主机和端口URL,例如 tcp://192.168.99.100:2376

tlsVerify

设置为 true 时启用安全HTTPS协议(可选)

certPath

HTTPS所需的证书和密钥文件路径(若 tlsVerifytrue 时必需,否则忽略)

bindHostToBuilder

若为 true ,则 host 属性的值会传递给为CNB builder创建的容器(可选)

更多详情参见 示例

Docker Registry

如果 builderrunImage 属性指定的Docker镜像存储在需要认证的私有Docker镜像仓库中,则可通过 docker.builderRegistry 属性提供认证凭据。

如果生成的Docker镜像需要发布到Docker镜像仓库,则可通过 docker.publishRegistry 属性提供认证凭据。

属性支持用户认证或身份令牌认证。 请查阅所用Docker仓库的文档,了解支持的认证方式。

下表总结了 docker.builderRegistrydocker.publishRegistry 可用的属性:

Property Description

username

Docker镜像仓库用户的用户名。用户认证时必需。

password

Docker镜像仓库用户的密码。用户认证时必需。

url

Docker镜像仓库地址。用户认证时可选。

email

Docker镜像仓库用户的电子邮件地址。用户认证时可选。

token

Docker镜像仓库用户的身份令牌。令牌认证时必需。

更多详情参见 示例

如果未提供凭据,插件会读取用户现有的Docker配置文件(通常位于 $HOME/.docker/config.json ),以确定认证方式。 通过这些方式,插件会尝试为请求的镜像提供认证凭据。

插件支持以下认证方式:

  • Credential Helpers:在Docker配置文件中配置的外部工具,为特定仓库提供凭据。例如,osxkeychainecr-login 等工具可处理某些仓库的认证。

  • Credential Store:默认的回退机制,用于安全存储和检索凭据(如Docker Desktop的 desktop )。

  • Static Credentials:直接存储在Docker配置文件`auths`部分下的静态凭据。

镜像自定义

插件会调用 builder来编排镜像的生成。 builder包含多个 buildpacks,可检查应用以影响生成的镜像。 默认情况下,插件会选择一个builder镜像。 生成镜像的名称由项目属性推断得出。

可通过任务属性配置builder在项目上的操作方式。 下表总结了可用属性及其默认值:

Property Command-line option Description Default value

builder

--builder

要使用的builder镜像名称。

paketobuildpacks/builder-noble-java-tiny:latest

trustBuilder

--trustBuilder

是否将builder视为 受信任

若builder为 paketobuildpacks/builder-noble-java-tinypaketobuildpacks/builder-jammy-java-tinypaketobuildpacks/builder-jammy-tinypaketobuildpacks/builder-jammy-basepaketobuildpacks/builder-jammy-fullpaketobuildpacks/builder-jammy-buildpackless-tinypaketobuildpacks/builder-jammy-buildpackless-basepaketobuildpacks/builder-jammy-buildpackless-fullgcr.io/buildpacks/builderheroku/builder 之一则为 true ,否则为 false

imagePlatform

--imagePlatform

拉取的builder、run和buildpack镜像的平台(操作系统和架构)。 格式为 OS[/architecture[/variant]] ,如 linux/amd64linux/arm64linux/arm/v5 。 请参考所用builder的文档以确定可用的镜像OS和架构选项。

无默认值,表示使用主机平台。

runImage

--runImage

要使用的run镜像名称。

无默认值,表示使用Builder元数据中指定的run镜像。

imageName

--imageName

生成镜像的名称

docker.io/library/${project.name}:${project.version}

pullPolicy

--pullPolicy

用于决定何时从仓库拉取builder和run镜像的策略。 可选值为 ALWAYSNEVERIF_NOT_PRESENT

ALWAYS

environment

传递给builder的环境变量。

空。

buildpacks

构建镜像时builder应使用的buildpacks。 仅会使用指定的buildpacks,覆盖builder中包含的默认buildpacks。 buildpack引用必须为以下形式之一:

  • builder中的buildpack - [urn:cnb:builder:]<buildpack ID>[@<version>]

  • 文件系统目录中的buildpack - [file://]<path>

  • 文件系统中.gz压缩包(.tgz)形式的buildpack - [file://]<path>/<file name>

  • OCI镜像中的buildpack - [docker://]<host>/<repo>[:<tag>][@<digest>]

无,表示使用builder自带的buildpacks。

bindings

卷绑定挂载,在构建镜像时应挂载到builder容器。 绑定信息会在创建builder容器时原样传递给Docker,不做解析和校验。 绑定必须为以下形式之一:

  • <主机源路径>:<容器目标路径>[:<选项>]

  • <主机卷名>:<容器目标路径>[:<选项>]

其中`<选项>`可包含:

  • ro 将卷以只读方式挂载到容器

  • rw 将卷以读写方式挂载到容器

  • volume-opt=key=value 指定选项名及其值的键值对

network

--network

builder容器将配置使用的 网络驱动。 提供的值会在创建builder容器时原样传递给Docker,不做校验。

cleanCache

--cleanCache

构建前是否清理缓存。

false

verboseLogging

启用builder操作的详细日志。

false

publish

--publishImage

是否将生成的镜像发布到Docker仓库。

false

tags

要为生成镜像附加的一个或多个额外标签。 tags 选项的值应为*完整*镜像引用。 详见 标签部分

buildWorkspace

builder和buildpacks在构建镜像时用于存储文件的临时工作区。 该值可以是命名卷或绑定挂载位置。

Docker守护进程中的命名卷,名称由镜像名派生。

buildCache

构建过程中buildpacks创建的层缓存。 该值可以是命名卷或绑定挂载位置。

Docker守护进程中的命名卷,名称由镜像名派生。

launchCache

镜像启动过程中buildpacks创建的层缓存。 该值可以是命名卷或绑定挂载位置。

Docker守护进程中的命名卷,名称由镜像名派生。

createdDate

--createdDate

用于设置生成镜像元数据中 Created 字段的日期。 该值必须为ISO 8601 instant格式的字符串,或`now`表示当前日期时间。

固定日期以实现 构建可重现性

applicationDirectory

--applicationDirectory

应用内容将上传到builder镜像中的目录路径。 生成的镜像中应用内容也位于该位置。

/workspace

securityOptions

--securityOptions

将应用于builder容器的 安全选项,以字符串数组形式提供

Linux和macOS下为 ["label=disable"] ,Windows下为 []

插件会通过JavaPlugin的 targetCompatibility 属性检测项目的目标Java兼容性。 使用默认Paketo builder和buildpacks时,插件会指示buildpacks安装相同的Java版本。 你可以按 builder配置示例所示覆盖此行为。
默认builder paketobuildpacks/builder-noble-java-tiny:latest 包含的系统库较少且不包含shell。 需要shell来运行启动脚本的应用(如应用了 application`插件 生成分发zip包的情况),或依赖于未包含的系统库的应用,应通过 `runImage 配置项指定包含shell和更丰富系统库的镜像,如 paketobuildpacks/ubuntu-noble-run-base: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 会直接按原样使用

示例

自定义镜像构建器与运行镜像

如果你需要自定义用于创建镜像的 builder 或用于启动已构建镜像的 run image,可按如下示例配置任务:

  • 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 的 builder 镜像,以及名为 mine/java-cnb-run 且标签为 latest 的 run image。

builder 和 run image 也可以通过命令行指定,如下所示:

$ gradle bootBuildImage --builder=mine/java-cnb-builder --runImage=mine/java-cnb-run

Builder 配置

如果 builder 暴露了配置选项,可以通过 environment 属性进行设置。

  • 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 buildpacks 通过设置 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"
	))
}

自定义镜像名称

默认情况下,镜像名称由项目的 nameversion 推断而来,形如 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 镜像中包含的 buildpacks,并按预定义顺序应用。 也可以提供一组自定义 buildpacks,用于应用 builder 未包含的 buildpacks,或更改已包含 buildpacks 的顺序。 当指定了一个或多个 buildpacks 时,仅会应用这些指定的 buildpacks。

以下示例指示 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-id 匹配的 buildpack,则版本可省略):

  • urn:cnb:builder:buildpack-id

  • urn:cnb:builder:buildpack-id@0.0.1

  • buildpack-id

  • buildpack-id@0.0.1

指向包含 buildpack 内容的目录路径(Windows 不支持):

指向包含 buildpack 内容的 gzip 压缩 tar 文件路径:

包含 打包 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 仓库。

如果 Docker 仓库需要认证,可通过 docker.publishRegistry 属性配置凭据。 如果 Docker 仓库不需要认证,则可以省略 docker.publishRegistry 配置。

镜像将被发布到的仓库由镜像名称中的 registry 部分决定(如这些示例中的 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

Builder 缓存与工作区配置

CNB builder 会缓存构建和启动镜像时使用的层。 默认情况下,这些缓存作为命名卷存储在 Docker daemon 中,卷名由目标镜像的完整名称派生。 如果镜像名称经常变化(例如项目版本作为镜像标签),则缓存也可能会频繁失效。

可以通过如下示例配置缓存卷使用自定义名称,以便更好地控制缓存生命周期:

  • 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")
		}
	}
}

builder 和 buildpacks 需要一个位置在构建镜像期间存储临时文件。 默认情况下,该临时构建工作区存储在命名卷中。

缓存和构建工作区也可以配置为使用绑定挂载(bind mount)而非命名卷,如下例所示:

  • 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 daemon:

  • 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 image 存储在支持用户认证的私有 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")
		}
	}
}

如果 builder 或 run image 存储在支持 token 认证的私有 Docker 仓库中,可通过如下示例所示的 docker.builderRegistry 提供 token 值:

  • Groovy

  • Kotlin

tasks.named("bootBuildImage") {
	docker {
		builderRegistry {
			token = "9cbaf023786cd7..."
		}
	}
}
tasks.named<BootBuildImage>("bootBuildImage") {
	docker {
		builderRegistry {
			token.set("9cbaf023786cd7...")
		}
	}
}