Packaging OCI Images
The plugin can create an OCI image from a jar or war file using Cloud Native Buildpacks (CNB).
Images can be built using the bootBuildImage
task.
For security reasons, images build and run as non-root users. See the CNB specification for more details. |
The task is automatically created when the java
or war
plugin is applied and is an instance of BootBuildImage
.
Docker Daemon
The bootBuildImage
task requires access to a Docker daemon.
The task will inspect local Docker CLI configuration files to determine the current context and use the context connection information to communicate with a Docker daemon.
If the current context can not be determined or the context does not have connection information, then the task will use a default local connection.
This works with Docker Engine on all supported platforms without configuration.
Environment variables can be set to configure the bootBuildImage
task to use an alternative local or remote connection.
The following table shows the environment variables and their values:
Environment variable | Description |
---|---|
DOCKER_CONFIG |
Location of Docker CLI configuration files used to determine the current context (defaults to |
DOCKER_CONTEXT |
Name of a context that should be used to retrieve host information from Docker CLI configuration files (overrides |
DOCKER_HOST |
URL containing the host and port for the Docker daemon - for example |
DOCKER_TLS_VERIFY |
Enable secure HTTPS protocol when set to |
DOCKER_CERT_PATH |
Path to certificate and key files for HTTPS (required if |
Docker daemon connection information can also be provided using docker
properties in the plugin configuration.
The following table summarizes the available properties:
Property | Description |
---|---|
|
Name of a context that should be used to retrieve host information from Docker CLI configuration files |
|
URL containing the host and port for the Docker daemon - for example |
|
Enable secure HTTPS protocol when set to |
|
Path to certificate and key files for HTTPS (required if |
|
When |
For more details, see also examples.
Docker Registry
If the Docker images specified by the builder
or runImage
properties are stored in a private Docker image registry that requires authentication, the authentication credentials can be provided using docker.builderRegistry
properties.
If the generated Docker image is to be published to a Docker image registry, the authentication credentials can be provided using docker.publishRegistry
properties.
Properties are provided for user authentication or identity token authentication. Consult the documentation for the Docker registry being used to store images for further information on supported authentication methods.
The following table summarizes the available properties for docker.builderRegistry
and docker.publishRegistry
:
Property | Description |
---|---|
|
Username for the Docker image registry user. Required for user authentication. |
|
Password for the Docker image registry user. Required for user authentication. |
|
Address of the Docker image registry. Optional for user authentication. |
|
E-mail address for the Docker image registry user. Optional for user authentication. |
|
Identity token for the Docker image registry user. Required for token authentication. |
For more details, see also examples.
Image Customizations
The plugin invokes a builder to orchestrate the generation of an image. The builder includes multiple buildpacks that can inspect the application to influence the generated image. By default, the plugin chooses a builder image. The name of the generated image is deduced from project properties.
Task properties can be used to configure how the builder should operate on the project. The following table summarizes the available properties and their default values:
Property | Command-line option | Description | Default value |
---|---|---|---|
|
|
Name of the Builder image to use. |
|
|
|
Name of the run image to use. |
No default value, indicating the run image specified in Builder metadata should be used. |
|
|
Image name for the generated image. |
|
|
|
Policy used to determine when to pull the builder and run images from the registry.
Acceptable values are |
|
|
Environment variables that should be passed to the builder. |
Empty or |
|
|
Buildpacks that the builder should use when building the image. Only the specified buildpacks will be used, overriding the default buildpacks included in the builder. Buildpack references must be in one of the following forms:
|
None, indicating the builder should use the buildpacks included in it. |
|
|
Volume bind mounts that should be mounted to the builder container when building the image. The bindings will be passed unparsed and unvalidated to Docker when creating the builder container. Bindings must be in one of the following forms:
Where
|
||
|
|
The network driver the builder container will be configured to use. The value supplied will be passed unvalidated to Docker when creating the builder container. |
|
|
|
Whether to clean the cache before building. |
|
|
Enables verbose logging of builder operations. |
|
|
|
|
Whether to publish the generated image to a Docker registry. |
|
|
A list of one or more additional tags to apply to the generated image.
The values provided to the |
||
|
A temporary workspace that will be used by the builder and buildpacks to store files during image building. The value can be a named volume or a bind mount location. |
A named volume in the Docker daemon, with a name derived from the image name. |
|
|
A cache containing layers created by buildpacks and used by the image building process. The value can be a named volume or a bind mount location. |
A named volume in the Docker daemon, with a name derived from the image name. |
|
|
A cache containing layers created by buildpacks and used by the image launching process. The value can be a named volume or a bind mount location. |
A named volume in the Docker daemon, with a name derived from the image name. |
|
|
|
A date that will be used to set the |
A fixed date that enables build reproducibility. |
|
|
The path to a directory that application contents will be uploaded to in the builder image. Application contents will also be in this location in the generated image. |
|
|
|
Security options that will be applied to the builder container, provided as an array of string values |
|
The plugin detects the target Java compatibility of the project using the JavaPlugin’s targetCompatibility property.
When using the default Paketo builder and buildpacks, the plugin instructs the buildpacks to install the same Java version.
You can override this behaviour as shown in the builder configuration examples.
|
Tags Format
The values provided to the tags
option should be full image references.
The accepted format is [domainHost:port/][path/]name[:tag][@digest]
.
If the domain is missing, it defaults to docker.io
.
If the path is missing, it defaults to library
.
If the tag is missing, it defaults to latest
.
Some examples:
-
my-image
leads to the image referencedocker.io/library/my-image:latest
-
my-repository/my-image
leads todocker.io/my-repository/my-image:latest
-
example.com/my-repository/my-image:1.0.0
will be used as is
Examples
Custom Image Builder and Run Image
If you need to customize the builder used to create the image or the run image used to launch the built image, configure the task as shown in the following example:
-
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")
}
This configuration will use a builder image with the name mine/java-cnb-builder
and the tag latest
, and the run image named mine/java-cnb-run
and the tag latest
.
The builder and run image can be specified on the command line as well, as shown in this example:
$ gradle bootBuildImage --builder=mine/java-cnb-builder --runImage=mine/java-cnb-run
Builder Configuration
If the builder exposes configuration options, those can be set using the environment
property.
The following is an example of configuring the JVM version used by the Paketo Java buildpacks at build time:
-
Groovy
-
Kotlin
tasks.named("bootBuildImage") {
environment["BP_JVM_VERSION"] = "17"
}
tasks.named<BootBuildImage>("bootBuildImage") {
environment.put("BP_JVM_VERSION", "17")
}
If there is a network proxy between the Docker daemon the builder runs in and network locations that buildpacks download artifacts from, you will need to configure the builder to use the proxy.
When using the Paketo builder, this can be accomplished by setting the HTTPS_PROXY
and/or HTTP_PROXY
environment variables as show in the following example:
-
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"))
}
Runtime JVM Configuration
Paketo Java buildpacks configure the JVM runtime environment by setting the JAVA_TOOL_OPTIONS
environment variable.
The buildpack-provided JAVA_TOOL_OPTIONS
value can be modified to customize JVM runtime behavior when the application image is launched in a container.
Environment variable modifications that should be stored in the image and applied to every deployment can be set as described in the Paketo documentation and shown in the following example:
-
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"
))
}
Custom Image Name
By default, the image name is inferred from the name
and the version
of the project, something like docker.io/library/${project.name}:${project.version}
.
You can take control over the name by setting task properties, as shown in the following example:
-
Groovy
-
Kotlin
tasks.named("bootBuildImage") {
imageName = "example.com/library/${project.name}"
}
tasks.named<BootBuildImage>("bootBuildImage") {
imageName.set("example.com/library/${project.name}")
}
Note that this configuration does not provide an explicit tag so latest
is used.
It is possible to specify a tag as well, either using ${project.version}
, any property available in the build or a hardcoded version.
The image name can be specified on the command line as well, as shown in this example:
$ gradle bootBuildImage --imageName=example.com/library/my-app:v1
Buildpacks
By default, the builder will use buildpacks included in the builder image and apply them in a pre-defined order. An alternative set of buildpacks can be provided to apply buildpacks that are not included in the builder, or to change the order of included buildpacks. When one or more buildpacks are provided, only the specified buildpacks will be applied.
The following example instructs the builder to use a custom buildpack packaged in a .tgz
file, followed by a buildpack included in the builder.
-
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 can be specified in any of the forms shown below.
A buildpack located in a CNB Builder (version may be omitted if there is only one buildpack in the builder matching the buildpack-id
):
-
urn:cnb:builder:buildpack-id
-
urn:cnb:builder:[email protected]
-
buildpack-id
A path to a directory containing buildpack content (not supported on Windows):
-
file:///path/to/buildpack/
-
/path/to/buildpack/
A path to a gzipped tar file containing buildpack content:
-
file:///path/to/buildpack.tgz
-
/path/to/buildpack.tgz
An OCI image containing a packaged buildpack:
-
docker://example/buildpack
-
docker:///example/buildpack:latest
-
docker:///example/buildpack@sha256:45b23dee08…
-
example/buildpack
-
example/buildpack:latest
-
example/buildpack@sha256:45b23dee08…
Image Publishing
The generated image can be published to a Docker registry by enabling a publish
option.
If the Docker registry requires authentication, the credentials can be configured using docker.publishRegistry
properties.
If the Docker registry does not require authentication, the docker.publishRegistry
configuration can be omitted.
The registry that the image will be published to is determined by the registry part of the image name (docker.example.com in these examples).
If docker.publishRegistry credentials are configured and include a url property, this value is passed to the registry but is not used to determine the publishing registry location.
|
-
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")
}
}
}
The publish option can be specified on the command line as well, as shown in this example:
$ gradle bootBuildImage --imageName=docker.example.com/library/my-app:v1 --publishImage
Builder Cache and Workspace Configuration
The CNB builder caches layers that are used when building and launching an image. By default, these caches are stored as named volumes in the Docker daemon with names that are derived from the full name of the target image. If the image name changes frequently, for example when the project version is used as a tag in the image name, then the caches can be invalidated frequently.
The cache volumes can be configured to use alternative names to give more control over cache lifecycle as shown in the following example:
-
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 and buildpacks need a location to store temporary files during image building. By default, this temporary build workspace is stored in a named volume.
The caches and the build workspace can be configured to use bind mounts instead of named volumes, as shown in the following example:
-
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 Configuration
Docker Configuration for minikube
The plugin can communicate with the Docker daemon provided by minikube instead of the default local connection.
On Linux and macOS, environment variables can be set using the command eval $(minikube docker-env)
after minikube has been started.
The plugin can also be configured to use the minikube daemon by providing connection details similar to those shown in the following example:
-
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")
}
}
Docker Configuration for podman
The plugin can communicate with a podman container engine.
The plugin can be configured to use podman local connection by providing connection details similar to those shown in the following example:
-
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)
}
}
With the podman CLI installed, the command podman info --format='{{.Host.RemoteSocket.Path}}' can be used to get the value for the docker.host configuration property shown in this example.
|
Docker Configuration for Colima
The plugin can communicate with the Docker daemon provided by Colima.
The DOCKER_HOST
environment variable can be set by using the following command:
$ export DOCKER_HOST=$(docker context inspect colima -f '{{.Endpoints.docker.Host}}')
The plugin can also be configured to use Colima daemon by providing connection details similar to those shown in the following example:
-
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 Configuration for Authentication
If the builder or run image are stored in a private Docker registry that supports user authentication, authentication details can be provided using docker.builderRegistry
properties as shown in the following example:
-
Groovy
-
Kotlin
tasks.named("bootBuildImage") {
docker {
builderRegistry {
username = "user"
password = "secret"
url = "https://docker.example.com/v1/"
email = "[email protected]"
}
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
docker {
builderRegistry {
username.set("user")
password.set("secret")
url.set("https://docker.example.com/v1/")
email.set("[email protected]")
}
}
}
If the builder or run image is stored in a private Docker registry that supports token authentication, the token value can be provided using docker.builderRegistry
as shown in the following example:
-
Groovy
-
Kotlin
tasks.named("bootBuildImage") {
docker {
builderRegistry {
token = "9cbaf023786cd7..."
}
}
}
tasks.named<BootBuildImage>("bootBuildImage") {
docker {
builderRegistry {
token.set("9cbaf023786cd7...")
}
}
}