Technical Documentation: GoogleContainerTools/jib
ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference
Overview (`README.md`)
Jib
| ☑️ Jib User Survey |
|---|
| What do you like best about Jib? What needs to be improved? Please tell us by taking a one-minute survey. Your responses will help us understand Jib usage and allow us to serve our customers (you!) better. |
What is Jib?
Jib builds optimized Docker and OCI images for your Java applications without a Docker daemon - and without deep mastery of Docker best-practices. It is available as plugins for Maven and Gradle and as a Java library.
- Maven: See documentation for jib-maven-plugin.
- Gradle: See documentation for jib-gradle-plugin.
- Jib Core: A general-purpose container-building library for Java.
- Jib CLI: A command-line interface for building images that uses Jib Core.
Jib works well with Google Cloud Build. For details, see how to use Jib on Google Cloud Build.
For more information, check out the official blog post or watch this talk (slides).
Goals
Fast - Deploy your changes fast. Jib separates your application into multiple layers, splitting dependencies from classes. Now you don’t have to wait for Docker to rebuild your entire Java application - just deploy the layers that changed.
Reproducible - Rebuilding your container image with the same contents always generates the same image. Never trigger an unnecessary update again.
Daemonless - Reduce your CLI dependencies. Build your Docker image from within Maven or Gradle and push to any registry of your choice. No more writing Dockerfiles and calling docker build/push.
Quickstart
Maven - See the jib-maven-plugin Quickstart.
Gradle - See the jib-gradle-plugin Quickstart.
Jib Core - See the Jib Core Quickstart.
Jib CLI - See the Jib CLI doc.
Examples
The examples directory includes the following examples (and more).
How Jib Works
Whereas traditionally a Java application is built as a single image layer with the application JAR, Jib's build strategy separates the Java application into multiple layers for more granular incremental builds. When you change your code, only your changes are rebuilt, not your entire application. These layers, by default, are layered on top of an OpenJDK base image, but you can also configure a custom base image. For more information, check out the official blog post or watch this talk (slides).
See also rules_docker for a similar existing container image build tool for the Bazel build system.
Need Help?
A lot of questions are already answered!
For usage questions, please ask them on Stack Overflow.
Privacy
See the Privacy page.
Get involved with the community
We welcome contributions! Here's how you can contribute:
- Browse issues or file an issue
- Chat with us on gitter
- Join the jib-users mailing list
- Contribute:
- Read the contributing guide before starting work on an issue
- Try to fix good first issues
- Help out on issues that need help
- Join in on discussion issues
Make sure to follow the Code of Conduct when contributing so we can foster an open and welcoming community.
Disclaimer
This is not an officially supported Google product.
Overview (`examples/README.md`)
Example projects containerizing with Jib
Please file an issue if you find any problems with the examples or would like to request other examples.
For examples on using Jib Core, see jib-core/examples.
Simple example
See helloworld for containerizing a simple Hello World application.
Multi-module example (DRAFT)
See multi-module for containerizing projects with multiple modules.
Vert.x
See vertx for containerizing Eclipse Vert.x applications.
Spring Boot example
See spring-boot for containerizing a Spring Boot application and running it on Kubernetes.
Ktor example
See ktor for containerizing a Ktor Kotlin Application using the Kotlin Gradle DSL.
Dropwizard example
See dropwizard for containerizing Dropwizard applications.
Micronaut example
See micronaut for containerizing a Micronaut framework Groovy/Java application.
Java agents example
See java-agent for launching with the Stackdriver Debugger Java agent.
Kafka Connect+Streams example
See the following projects for using Jib-packaged applications in coordination with Apache Kafka.
- Kafka Streams -
OneCricketeer/kafka-streams-jib-example - Kafka Connect -
OneCricketeer/apache-kafka-connect-docker
Overview (`jib-cli/README.md`)
Jib CLI
jib is a general-purpose command-line utility for building Docker or OCI container images from file system content as well as JAR files. Jib CLI builds containers fast and reproducibly without Docker like other Jib tools.
# docker not required
$ docker
-bash: docker: command not found
# build and upload an image
$ jib build --target=my-registry.example.com/built-by-jibAdditionally, Jib CLI can directly build an optimized image for JAR files (including Spring Boot fat JAR).
$ jib jar --target=my-registry.example.com/jar-app myapp.jarThe CLI tool is powered by Jib Core, a Java library for building containers without Docker.
Table of Contents
- Get the Jib CLI
- Jib CLI JVM options
- Supported Commands
- Build Command
- Jar Command
- War Command
- Options Shared Between Jar and War Commands
- Common Jib CLI Options
- Global Jib Configuration
- References
- Privacy
Get the Jib CLI
Most users should download a ZIP archive (Java application). We are working on releasing a native executable binary using GraalVM. (Help wanted!)
Download a Java Application
A JRE is required to run this Jib CLI distribution.
Find the latest jib-cli 0.13.0 release on the Releases page and download jib-jre-<version>.zip.
Unzip the zip file. The zip file contains the jib (jib.bat for Windows) script at jib/bin/. Optionally, add the binary directory to your $PATH so that you can call jib from anywhere.
We generate SLSA3 signatures using the OpenSSF's slsa-framework/slsa-github-generator during the release process. To verify a release binary:
- Install the verification tool from slsa-framework/slsa-verifier#installation.
- Download the signature file
jib-jre-<version>.zip.intoto.jsonlfrom the GitHub releases page. - Run the verifier:
slsa-verifier -artifact-path jib-jre-<version>.zip -provenance jib-jre-<version>.zip.intoto.jsonl -source github.com/GoogleContainerTools/jib -branch master -workflow-input release_version=<version>Windows: Install with `choco`
On Windows, you can use the choco command. To install, upgrade, or uninstall Jib CLI, run the following commands from the command-line or PowerShell:
choco install jib
choco upgrade jib
choco uninstall jibBuild Yourself from Source (for Advanced Users)
Use the application plugin's installDist task to create a runnable installation inbuild/install/jib. A zip and tar file are also created in build/distributions.
# build
$ ./gradlew jib-cli:installDist
# run
$ ./jib-cli/build/install/jib/bin/jibJib CLI JVM options
Jib CLI is a Java application built with the Gradle application plugin.
To configure JVM options for the Jib CLI process itself, you can use the JIB_OPTS or JAVA_OPTS environment variables.
This is commonly used to configure settings like a proxy by passing standard Java networking properties, as described in the proxy configuration FAQ.
Supported Commands
The Jib CLI supports two commands:
build- containerizes using a build file.jar- containerizes JAR files.war- containerizes WAR files.
Build Command
This command follows the following pattern:
jib build --target <image name> [options]Quickstart
- Create a hello world script (
script.sh) containing:sh#!/bin/sh echo "Hello World" - Create a build file. The default is a file named
jib.yamlin the project root.yamlapiVersion: jib/v1alpha1 kind: BuildFile from: image: ubuntu entrypoint: ["/script.sh"] layers: entries: - name: scripts files: - properties: filePermissions: 755 src: script.sh dest: /script.sh - Build to docker daemontext
$ jib build --target=docker://jib-cli-quickstart - Run the containertext
$ docker run jib-cli-quickstart Hello World
Options
Optional flags for the build command:
| Option | Description |
|---|---|
-b, --build-file |
The path to the build file (ex: path/to/other-jib.yaml) |
-c, --context |
The context root directory of the build (ex: path/to/my/build/things) |
-p, --parameter |
Templating parameter to inject into build file, replace ${ |
Jar Command
This command follows the following pattern:
jib jar --target <image name> path/to/myapp.jar [options]Quickstart
- Have your JAR (thin or fat) ready. We will be using the Spring Petclinic JAR in this Quickstart.text
$ git clone https://github.com/spring-projects/spring-petclinic.git $ cd spring-petclinic $ ./mvnw package - Containerize your JAR using the
jarcommand. In the default mode (exploded), the entrypoint will be set tojava -cp /app/dependencies/:/app/explodedJar/ HelloWorldtext$ jib jar --target=docker://cli-jar-quickstart target/spring-petclinic-*.jar - Run the image and open your browser at http://localhost:8080text
$ docker run -p 8080:8080 cli-jar-quickstart
Options
Optional flags for the jar command:
| Option | Description |
|---|---|
--jvm-flags |
JVM arguments, example: --jvm-flags=-Dmy.property=value,-Xshare:off |
--mode |
The jar processing mode, candidates: exploded, packaged, default: exploded |
War Command
This command follows the following pattern:
$ jib war --target <image-name> path/to/myapp.warQuickstart
- Have your sample WAR ready and use the
warcommand to containerize your WAR. By default, the WAR command usesjettyas the base image so the entrypoint is set tojava -jar /usr/local/jetty/start.jar --module=ee10-deploy:text$ jib war --target=docker://cli-war-quickstart <your-sample>.war - Run the image and open your browser at http://localhost:8080text
$ docker run -p 8080:8080 cli-war-quickstart
Options
Flags for the war command:
| Option | Description |
|---|---|
--app-root |
The app root on the container. Customizing the app-root is helpful if you are using a different Servlet engine base image (for example, Tomcat) |
Options Shared Between the Jar and War Commands
Here are a few container configurations that can be customized when using the jar and war commands.
| Option | Description |
|---|---|
--creation-time |
The creation time of the container in milliseconds since epoch or iso8601 format. Overrides the default (1970-01-01T00:00:00Z) |
--entrypoint |
Entrypoint for container. Overrides the default entrypoint, example: --entrypoint='custom entrypoint' |
--environment-variables |
Environment variables to write into container, example: --environment-variables env1=env_value1, env2=env_value2. |
--expose |
Ports to expose on container, example: --expose=5000,7/udp. |
--from |
The base image to use. |
--image-format |
Format of container, candidates: Docker, OCI, default: Docker. |
--labels |
Labels to write into container metadata, example: --labels=label1=value1,label2=value2. |
--program-args |
Program arguments for container entrypoint. |
-u, --user |
The user to run the container as, example: --user=myuser:mygroup. |
--volumes |
Directories on container to hold extra volumes, example: --volumes=/var/log,/var/log2. |
Common Jib CLI Options
The options can either be specified in the command line or defined in a configuration file:
[@<filename>...] One or more argument files containing options.Auth/Security
--allow-insecure-registries Allow jib to send credentials over http (insecure)
--send-credentials-over-http Allow jib to send credentials over http (very insecure)Registry Credentials
Credentials can be specified using credential helpers or username + password. The following options are available:
--credential-helper <credHelper> credential helper for communicating with both target and base image registries, either a path to the helper, or a suffix for an executable named `docker-credential-<suffix>`
--to-credential-helper <credHelper> credential helper for communicating with target registry, either a path to the helper, or a suffix for an executable named `docker-credential-<suffix>
--from-credential-helper <credHelper> credential helper for communicating with base image registry, either a path to the helper, or a suffix for an executable named `docker-credential-<suffix>`
--username <username> username for communicating with both target and base image registries
--password <password> password for communicating with both target and base image registries
--to-username <username> username for communicating with target image registry
--to-password <password> password for communicating with target image registry
--from-username <username> username for communicating with base image registry
--from-password <password> password for communicating with base image registryNote - Combinations of credential-helper, username and password flags come with restrictions and can be use only in the following ways:
Only Credential Helper
--credential-helper--to-credential-helper--from-credential-helper--to-credential-helper,--from-credential-helper
Only Username and Password
--username,--password--to-username,--to-password--from-username,--from-password--to-username,--to-password,--from-username,--from-password
Mixed Mode
--to-credential-helper,--from-username,--from-password--from-credential-helper,--to-username,--to-password
Info Params
--help print usage and exit
--console <type> set console output type, candidates: auto, rich, plain, default: auto
--verbosity <level> set logging verbosity, candidates: quiet, error, warn, lifecycle, info, debug, default: lifecycle
-v, --version Jib CLI version informationDebugging Params
--stacktrace print stacktrace on error (for debugging issues in the jib-cli)
--http-trace enable http tracing at level=config, output=console
--serialize run jib in serialized modeGlobal Jib Configuration
Some options can be set in the global Jib configuration file. The file is at the following locations on each platform:
- Linux:
[config root]/google-cloud-tools-java/jib/config.json, where[config root]is$XDG_CONFIG_HOME($HOME/.config/if not set) - Mac:
[config root]/Google/Jib/config.json, where[config root]is$XDG_CONFIG_HOME($HOME/Library/Preferences/Config/if not set) - Windows:
[config root]\Google\Jib\Config\config.json, where[config root]is$XDG_CONFIG_HOME(%LOCALAPPDATA%if not set)
Properties
disableUpdateCheck: when set to true, disables the periodic up-to-date version check.registryMirrors: a list of mirror settings for each base image registry. In the following example, if the base image configured in Jib is for a Docker Hub image, thenmirror.gcr.io,localhost:5000, and the Docker Hub (registry-1.docker.io) are tried in order until Jib can successfully pull a base image.
{
"disableUpdateCheck": false,
"registryMirrors": [
{
"registry": "registry-1.docker.io",
"mirrors": ["mirror.gcr.io", "localhost:5000"]
},
{
"registry": "quay.io",
"mirrors": ["private-mirror.test.com"]
}
]
}Note about mirror.gcr.io: it is not a Docker Hub mirror but a cache. It caches frequently-accessed public Docker Hub images, and it's often possible that your base image does not exist in mirror.gcr.io. In that case, Jib will have to fall back to use Docker Hub.
References
Fully Annotated Build File (`jib.yaml`)
/* Detailed source-code truncated for AI context efficiency. */Layers Behavior
- Copy directives are bound by the following rules
src: filetype determined by type on local disk- if
srcis directory,destis always considered a directory, directory and contents will be copied over and renamed todest - if
srcis file- if
destends with/then it is considered a target directory, file will be copied into directory - if
destdoesn't end with/then is is the target file location,srcfile will be copied and renamed todest
- if
- if
- Permissions for a file or directory that appear in multiple layers will prioritize the last layer and copy directive the file appears in. In the following example,
file.txtas seen on the running container will have filePermissions234.text- name: layer1 properties: filePermissions: "123" - src: file.txt dest: /file.txt - name: layer2 properties: filePermissions: "234" - src: file.txt dest: /file.txt - Parent directories that are not explicitly defined in a layer will the default properties in jib-core (permissions: 755, modification-time: epoch+1). In the following example,
/somewhereon the container will have the directory permissions755, not777as some might expect.text- name: layer properties: directoryPermissions: "777" - src: file.txt dest: /somewhere/file.txt excludeson a directory can lead to unintended inclusion of files in the directory, to exclude a directory and all its filestextexcludes: - "**/exclude-dir" - "**/exclude-dir/**
Base Image Parameter Inheritance
Some values defined in the base image may be preserved and propagated into the new container.
Parameters will append to base image value:
volumesexposedPorts
Parameters that will append any new keys, and overwrite existing keys:
labelsenvironment
Parameters that will be overwritten:
userworkingDirectoryentrypointcmd
Privacy
See the Privacy page.
Disclaimer
This is not an officially supported Google product.
Overview (`jib-core/README.md`)
Jib Core - Java library for building containers
Jib Core is a Java library for building Docker and OCI container images. It implements a general-purpose container builder that can be used to build containers without a Docker daemon, for any application. The implementation is pure Java.
The API is currently in beta and may change substantially.
Jib Core powers the popular Jib plugins for Maven and Gradle. The plugins build containers specifically for JVM languages and separate the application into multiple layers to optimize for fast rebuilds.
For the Maven plugin, see the jib-maven-plugin project.
For the Gradle plugin, see the jib-gradle-plugin project.
For information about the Jib project, see the Jib project README.
Adding Jib Core to your build
Add Jib Core as a dependency using Maven:
<dependency>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-core</artifactId>
<version>0.28.2</version>
</dependency>Add Jib Core as a dependency using Gradle:
dependencies {
compile 'com.google.cloud.tools:jib-core:0.28.2'
}Examples
Jib.from("busybox")
.addLayer(Arrays.asList(Paths.get("helloworld.sh")), AbsoluteUnixPath.get("/"))
.setEntrypoint("sh", "/helloworld.sh")
.containerize(
Containerizer.to(RegistryImage.named("gcr.io/my-project/hello-from-jib")
.addCredential("myusername", "mypassword")));Jib.from("busybox")creates a newJibContainerBuilderconfigured withbusyboxas the base image..addLayer(...)configures theJibContainerBuilderwith a new layer withhelloworld.sh(local file) to be placed into the container at/helloworld.sh..setEntrypoint("sh", "/helloworld.sh")sets the entrypoint of the container to run/helloworld.sh.RegistryImage.named("gcr.io/my-project/hello-from-jib")creates a newRegistryImageconfigured withgcr.io/my-project/hello-from-jibas the target image to push to..addCredentialadds the username/password credentials to authenticate the push togcr.io/my-project/hello-from-jib. SeeCredentialRetrieverFactoryfor common credential retrievers (to retrieve credentials from Docker config or credential helpers, for example). These credential retrievers can be used with.addCredentialRetriever.Containerizer.tocreates a newContainerizerconfigured to push to theRegistryImage..containerizeexecutes the containerization. If successful, the container image will be available atgcr.io/my-project/hello-from-jib.
See examples for links to more jib-core samples. We welcome contributions for additional examples and tutorials!
API overview
Jib - the main entrypoint for using Jib Core
JibContainerBuilder - configures the container to build
Containerizer - configures how and where to containerize to
JibContainer - information about the built container
Three types define what Jib can accept as either the base image or as the build target:
RegistryImage- an image on a container registryDockerDaemonImage- an image in the Docker daemonTarImage- an image saved as a tarball archive on the filesystem
Other useful classes:
ImageReference- represents an image reference and has useful methods for parsing and manipulating image referencesLayerConfiguration- configures a container layer to buildCredentialRetriever- implement with custom credential retrieval methods for authenticating against a container registryCredentialRetrieverFactory- provides usefulCredentialRetrievers to retrieve credentials from Docker config and credential helpers
Java-specific API:
JavaContainerBuilder- configures aJibContainerBuilderfor Java-specific applicationsMainClassFinder- find the main Java class in a given list of class files
API reference
How Jib Core works
The Jib Core system consists 3 main parts:
- an execution orchestrator that executes an asynchronous pipeline of containerization steps,
- an image manipulator capable of handling Docker and OCI image formats, and
- a registry client that implements the Docker Registry V2 API.
Some other parts of Jib Core internals include:
- a caching mechanism to speed up builds (configurable with
Containerizer.setApplicationLayersCacheandContainerizer.setBaseImageLayersCache) - an eventing system to react to events from Jib Core during its execution (add handlers with
Containerizer.addEventHandler) - support for fully-concurrent multi-threaded executions
Events
Throughout the build process, Jib Core dispatches events that provide useful information. These events implement the type JibEvent, and can be handled by registering event handlers with the containerizer.
Jib.from(...)
...
.containerize(
Containerizer.to(...)
...
.addEventHandler(LogEvent.class, logEvent -> System.out.println(logEvent.getLevel() + ": " + logEvent.getMessage())
.addEventHandler(TimerEvent.class, timeEvent -> ...));When Jib dispatches events, the event handlers you defined for that event type will be called. The following are the types of events you can listen for in Jib core (see API reference for more information):
LogEvent- Log message events. The message and verbosity can be retrieved usinggetMessage()andgetLevel(), respectively.TimerEvent(Incubating) - Events used for measuring how long different build steps take. You can retrieve the duration since the timer's creation and the duration since the same timer's previous event usinggetElapsed()andgetDuration(), respectively.ProgressEvent(Incubating) - Indicates the amount of progress build steps have made. Each progress event consists of an allocation (containing a fraction representing how much of the root allocation this allocation accounts for) and a number of progress units that indicates the amount of work completed since the previous progress event. In other words, the amount of work a single progress event has completed (out of 1.0) can be calculated usinggetAllocation().getFractionOfRoot() * getUnits().
Frequently Asked Questions (FAQ)
See the Jib project FAQ.
Upcoming features
- Extensions to make building Java and other language-specific containers easier
See Milestones for planned features. Get involved with the community for the latest updates.
Community
See the Jib project README.
Overview (`jib-gradle-plugin/README.md`)
Jib - Containerize your Gradle Java project
Jib is a Gradle plugin for building Docker and OCI images for your Java applications.
For the Maven plugin, see the jib-maven-plugin project.
For information about the project, see the Jib project README.
| ☑️ Jib User Survey |
|---|
| What do you like best about Jib? What needs to be improved? Please tell us by taking a one-minute survey. Your responses will help us understand Jib usage and allow us to serve our customers (you!) better. |
Table of Contents
- Upcoming Features
- Quickstart
- Multi Module Projects
- Extended Usage
- Need Help?
- Community
Quickstart
Setup
Make sure you are using Gradle version 5.1 or later.
In your Gradle Java project, add the plugin to your build.gradle:
plugins {
id 'com.google.cloud.tools.jib' version '3.5.4'
}See the Gradle Plugin Portal for more details.
You can containerize your application easily with one command:
gradle jib --image=<MY IMAGE>This builds and pushes a container image for your application to a container registry. If you encounter authentication issues, see Authentication Methods.
To build to a Docker daemon, use:
gradle jibDockerBuildIf you would like to set up Jib as part of your Gradle build, follow the guide below.
Configuration
Configure the plugin by setting the image to push to:
Using [Google Container Registry (GCR)](https://cloud.google.com/container-registry/)...
Make sure you have the docker-credential-gcr command line tool. Jib automatically uses docker-credential-gcr for obtaining credentials. See Authentication Methods for other ways of authenticating.
For example, to build the image gcr.io/my-gcp-project/my-app, the configuration would be:
jib.to.image = 'gcr.io/my-gcp-project/my-app'Using [Amazon Elastic Container Registry (ECR)](https://aws.amazon.com/ecr/)...
Make sure you have the docker-credential-ecr-login command line tool. Jib automatically uses docker-credential-ecr-login for obtaining credentials. See Authentication Methods for other ways of authenticating.
For example, to build the image aws_account_id.dkr.ecr.region.amazonaws.com/my-app, the configuration would be:
jib.to.image = 'aws_account_id.dkr.ecr.region.amazonaws.com/my-app'Using [Docker Hub Registry](https://hub.docker.com/)...
Make sure you have a docker-credential-helper set up. For example, on macOS, the credential helper would be docker-credential-osxkeychain. See Authentication Methods for other ways of authenticating.
For example, to build the image my-docker-id/my-app, the configuration would be:
jib.to.image = 'my-docker-id/my-app'Using [JFrog Container Registry (JCR)](https://jfrog.com/container-registry) or [JFrog Artifactory](https://jfrog.com/help/r/jfrog-artifactory-documentation/getting-started-with-artifactory-as-a-docker-registry)...
Make sure you have a docker-credential-helper set up. For example, on macOS, the credential helper would be docker-credential-osxkeychain. See Authentication Methods for other ways of authenticating.
For example, to build the image my-company-docker-local.jfrog.io/my-app, the configuration would be:
jib.to.image = 'my-company-docker-local.jfrog.io/my-app'Using [Azure Container Registry (ACR)](https://azure.microsoft.com/en-us/services/container-registry/)...
Make sure you have a ACR Docker Credential Helper installed and set up. For example, on Windows, the credential helper would be docker-credential-acr-windows. See Authentication Methods for other ways of authenticating.
For example, to build the image my_acr_name.azurecr.io/my-app, the configuration would be:
jib.to.image = 'my_acr_name.azurecr.io/my-app'Build Your Image
Build your container image with:
gradle jibSubsequent builds are much faster than the initial build.
Having trouble? Let us know by submitting an issue, contacting us on Gitter, or posting to the Jib users forum.
Build to Docker daemon
Jib can also build your image directly to a Docker daemon. This uses the docker command line tool and requires that you have docker available on your PATH.
gradle jibDockerBuildIf you are using minikube's remote Docker daemon, make sure you set up the correct environment variables to point to the remote daemon:
eval $(minikube docker-env)
gradle jibDockerBuildAlternatively, you can set environment variables in the Jib configuration. See dockerClient for more configuration options.
Build an image tarball
You can build and save your image to disk as a tarball with:
gradle jibBuildTarThis builds and saves your image to build/jib-image.tar, which you can load into docker with:
docker load --input build/jib-image.tarRun `jib` with each build
You can also have jib run with each build by attaching it to the build task:
tasks.build.dependsOn tasks.jibThen, gradle build will build and containerize your application.
Additional Build Artifacts
As part of an image build, Jib also writes out the image digest and the image ID. By default, these are written out to build/jib-image.digest and build/jib-image.id respectively, but the locations can be configured using the jib.outputPaths.digest and jib.outputPaths.imageId configuration properties. See Extended Usage for more details.
Multi Module Projects
Special handling of project dependencies is recommended when building complex
multi module projects. See Multi Module Example for detailed information.
Extended Usage
The plugin provides the jib extension for configuration with the following options for customizing the image build:
| Field | Type | Default | Description |
|---|---|---|---|
to |
to |
Required | Configures the target image to build your application to. |
from |
from |
See from |
Configures the base image to build your application on top of. |
container |
container |
See container |
Configures the container that is run from your built image. |
extraDirectories |
extraDirectories |
See extraDirectories |
Configures the directories used to add arbitrary files to the image. |
outputPaths |
outputPaths |
See outputPaths |
Configures the locations of additional build artifacts generated by Jib. |
dockerClient |
dockerClient |
See dockerClient |
Configures Docker for building to/from the Docker daemon. |
skaffold |
skaffold |
See skaffold |
Configures the internal skaffold tasks. This configuration should only be used when integrating with skaffold. |
containerizingMode |
String |
exploded |
If set to packaged, puts the JAR artifact built by the Gradle Java plugin into the final image. If set to exploded (default), containerizes individual .class files and resources files. |
allowInsecureRegistries |
boolean |
false |
If set to true, Jib ignores HTTPS certificate errors and may fall back to HTTP as a last resort. Leaving this parameter set to false is strongly recommended, since HTTP communication is unencrypted and visible to others on the network, and insecure HTTPS is no better than plain HTTP. If accessing a registry with a self-signed certificate, adding the certificate to your Java runtime's trusted keys may be an alternative to enabling this option. |
configurationName |
String |
runtimeClasspath |
Specify the name of the Gradle Configuration to use. |
from is a closure with the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
image |
String |
eclipse-temurin:{8,11,17,21,25}-jre (or jetty for WAR) |
The image reference for the base image. The source type can be specified using a special type prefix. |
auth |
auth |
None | Specifies credentials directly (alternative to credHelper). |
credHelper |
String |
None | Specifies a credential helper that can authenticate pulling the base image. This parameter can either be configured as an absolute path to the credential helper executable or as a credential helper suffix (following docker-credential-). |
platforms |
platforms |
See platforms |
Configures platforms of base images to select from a manifest list. |
to is a closure with the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
image |
String |
Required | The image reference for the target image. This can also be specified via the --image command line option. If the tag is not present here :latest is implied. |
auth |
auth |
None | Specifies credentials directly (alternative to credHelper). |
credHelper |
String |
None | Specifies a credential helper that can authenticate pushing the target image. This parameter can either be configured as an absolute path to the credential helper executable or as a credential helper suffix (following docker-credential-). |
tags |
List<String> |
None | Additional tags to push to. |
auth is a closure with the following properties (see Using Specific Credentials):
| Property | Type |
|---|---|
username |
String |
password |
String |
platforms can configure multiple platform closures. Each individual platform has the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
architecture |
String |
amd64 |
The architecture of a base image to select from a manifest list. |
os |
String |
linux |
The OS of a base image to select from a manifest list. |
See How do I specify a platform in the manifest list (or OCI index) of a base image? for examples.
container is a closure with the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
appRoot |
String |
/app |
The root directory on the container where the app's contents are placed. Particularly useful for WAR-packaging projects to work with different Servlet engine base images by designating where to put exploded WAR contents; see WAR usage as an example. |
args |
List<String> |
None | Additional program arguments appended to the command to start the container (similar to Docker's CMD instruction in relation with ENTRYPOINT). In the default case where you do not set a custom entrypoint, this parameter is effectively the arguments to the main method of your Java application. |
creationTime |
String |
EPOCH |
Sets the container creation time. (Note that this property does not affect the file modification times, which are configured using jib.container.filesModificationTime.) The value can be EPOCH to set the timestamps to Epoch (default behavior), USE_CURRENT_TIMESTAMP to forgo reproducibility and use the real creation time, or an ISO 8601 date-time parsable with DateTimeFormatter.ISO_DATE_TIME such as 2019-07-15T10:15:30+09:00 or 2011-12-03T22:42:05Z. The value can also be initialized lazily with a provider. |
entrypoint |
List<String> |
None | The command to start the container with (similar to Docker's ENTRYPOINT instruction). If set, then jvmFlags, mainClass, extraClasspath, and expandClasspathDependencies are ignored. You may also set jib.container.entrypoint = 'INHERIT' to indicate that the entrypoint and args should be inherited from the base image.* The value can also be initialized lazily with a provider. |
environment |
Map<String, String> |
None | Key-value pairs for setting environment variables on the container (similar to Docker's ENV instruction). |
extraClasspath |
List<String> |
None | Additional paths in the container to prepend to the computed Java classpath. |
expandClasspathDependencies |
boolean |
false |
/app/lib/*) for dependency JARs in the default Java runtime classpath but instead enumerates the JARs. Has the effect of preserving the classpath loading order as defined by the Gradle project.--class-path JVM argument. |
filesModificationTime |
String |
EPOCH_PLUS_SECOND |
Sets the modification time (last modified time) of files in the image put by Jib. (Note that this does not set the image creation time, which can be set using jib.container.creationTime.) The value should either be EPOCH_PLUS_SECOND to set the timestamps to Epoch + 1 second (default behavior), or an ISO 8601 date-time parsable with DateTimeFormatter.ISO_DATE_TIME such as 2019-07-15T10:15:30+09:00 or 2011-12-03T22:42:05Z. The value can also be initialized lazily with a provider. |
format |
String |
Docker |
Use OCI to build an OCI container image. |
jvmFlags |
List<String> |
None | Additional flags to pass into the JVM when running your application. The value can also be initialized lazily with a provider. |
labels |
Map<String, String> |
None | Key-value pairs for applying image metadata (similar to Docker's LABEL instruction). |
mainClass |
String |
Inferred** | The main class to launch your application from. The value can also be initialized lazily with a provider. |
ports |
List<String> |
None | Ports that the container exposes at runtime (similar to Docker's EXPOSE instruction). |
user |
String |
None | The user and group to run the container as. The value can be a username or UID along with an optional groupname or GID. The following are all valid: user, uid, user:group, uid:gid, uid:group, user:gid. |
volumes |
List<String> |
None | Specifies a list of mount points on the container. |
workingDirectory |
String |
None | The working directory in the container. |
extraDirectories is a closure with the following properties (see Adding Arbitrary Files to the Image):
| Property | Type | Default | Description |
|---|---|---|---|
paths |
paths closure, or Object |
(project-dir)/src/main/jib |
May be configured as a closure configuring path elements, or as source directory values recognized by Project.files(), such as String, File, Path, List<String|File|Path>, etc. |
permissions |
Map<String, String> |
None | Maps file paths (glob patterns) on container to Unix permissions. (Effective only for files added from extra directories.) If not configured, permissions default to "755" for directories and "644" for files. See Adding Arbitrary Files to the Image for an example. |
paths can configure multiple path closures (see Adding Arbitrary Files to the Image). Each individual path has the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
from |
Object |
(project-dir)/src/main/jib |
Accepts source directories that are recognized by Project.files(), such as String, File, Path, List<String|File|Path>, etc. |
into |
String |
/ |
The absolute unix path on the container to copy the extra directory contents into. |
includes |
List<String> |
None | Glob patterns for including files. See Adding Arbitrary Files to the Image for an example. |
excludes |
List<String> |
None | Glob patterns for excluding files. See Adding Arbitrary Files to the Image for an example. |
outputPaths is a closure with the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
tar |
File |
(project-dir)/build/jib-image.tar |
The path of the tarball generated by jibBuildTar. Relative paths are resolved relative to the project root. |
digest |
File |
(project-dir)/build/jib-image.digest |
The path of the image digest written out during the build. Relative paths are resolved relative to the project root. |
imageId |
File |
(project-dir)/build/jib-image.id |
The path of the image ID written out during the build. Relative paths are resolved relative to the project root. |
dockerClient is an object used to configure Docker when building to/from the Docker daemon. It has the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
executable |
File |
docker |
Sets the path to the Docker executable that is called to load the image into the Docker daemon. Please note: Users are responsible for ensuring that the Docker path passed in is valid and has the right permissions to be executed. |
environment |
Map<String, String> |
None | Sets environment variables used by the Docker executable. |
System Properties
Each of these parameters is configurable via commandline using system properties. Jib's system properties follow the same naming convention as the configuration parameters, with each level separated by dots (i.e. -Djib.parameterName[.nestedParameter.[...]]=value). Some examples are below:
gradle jib \
-Djib.to.image=myregistry/myimage:latest \
-Djib.to.auth.username=$USERNAME \
-Djib.to.auth.password=$PASSWORD
gradle jibDockerBuild \
-Djib.dockerClient.executable=/path/to/docker \
-Djib.container.environment=key1="value1",key2="value2" \
-Djib.container.args=arg1,arg2,arg3The following table contains additional system properties that are not available as build configuration parameters:
| Property | Type | Default | Description |
|---|---|---|---|
jib.httpTimeout |
int |
20000 |
HTTP connection/read timeout for registry interactions, in milliseconds. Use a value of 0 for an infinite timeout. |
jib.useOnlyProjectCache |
boolean |
false |
If set to true, Jib does not share a cache between different Gradle projects. |
jib.baseImageCache |
File |
Platform-dependent*** | Sets the directory to use for caching base image layers. This cache can (and should) be shared between multiple images. |
jib.applicationCache |
File |
[project dir]/build/jib-cache |
Sets the directory to use for caching application layers. This cache can be shared between multiple images. |
jib.console |
String |
None | If set to plain, Jib will print plaintext log messages rather than display a progress bar during the build. |
* If you configure args while entrypoint is set to 'INHERIT', the configured args value will take precedence over the CMD propagated from the base image.
** Uses the main class defined in the jar task or tries to find a valid main class.
*** The default base image cache is in the following locations on each platform:
- Linux:
[cache root]/google-cloud-tools-java/jib/, where[cache root]is$XDG_CACHE_HOME($HOME/.cache/if not set) - Mac:
[cache root]/Google/Jib/, where[cache root]is$XDG_CACHE_HOME($HOME/Library/Caches/if not set) - Windows:
[cache root]\Google\Jib\Cache, where[cache root]is%XDG_CACHE_HOME%(%LOCALAPPDATA%if not set)
Global Jib Configuration
Some options can be set in the global Jib configuration file. The file is at the following locations on each platform:
- Linux:
[config root]/google-cloud-tools-java/jib/config.json, where[config root]is$XDG_CONFIG_HOME($HOME/.config/if not set) - Mac:
[config root]/Google/Jib/config.json, where[config root]is$XDG_CONFIG_HOME($HOME/Library/Preferences/Config/if not set) - Windows:
[config root]\Google\Jib\Config\config.json, where[config root]is%XDG_CONFIG_HOME%(%LOCALAPPDATA%if not set)
Properties
disableUpdateCheck: when set to true, disables the periodic up-to-date version check.registryMirrors: a list of mirror settings for each base image registry. In the following example, if the base image configured in Jib is for a Docker Hub image, thenmirror.gcr.io,localhost:5000, and the Docker Hub (registry-1.docker.io) are tried in order until Jib can successfully pull a base image.
{
"disableUpdateCheck": false,
"registryMirrors": [
{
"registry": "registry-1.docker.io",
"mirrors": ["mirror.gcr.io", "localhost:5000"]
},
{
"registry": "quay.io",
"mirrors": ["private-mirror.test.com"]
}
]
}Note about mirror.gcr.io: it is not a Docker Hub mirror but a cache. It caches frequently-accessed public Docker Hub images, and it's often possible that your base image does not exist in mirror.gcr.io. In that case, Jib will have to fall back to use Docker Hub.
Example
In this configuration, the image:
- Is built from a base of
openjdk:alpine(pulled from Docker Hub) - Is pushed to
localhost:5000/my-image:built-with-jib,localhost:5000/my-image:tag2, andlocalhost:5000/my-image:latest - Runs by calling
java -Dmy.property=example.value -Xms512m -Xdebug -cp app/libs/*:app/resources:app/classes mypackage.MyApp some args - Exposes port 1000 for tcp (default), and ports 2000, 2001, 2002, and 2003 for udp
- Has two labels (key1:value1 and key2:value2)
- Is built as OCI format
jib {
from {
image = 'openjdk:alpine'
}
to {
image = 'localhost:5000/my-image/built-with-jib'
credHelper = 'osxkeychain'
tags = ['tag2', 'latest']
}
container {
jvmFlags = ['-Dmy.property=example.value', '-Xms512m', '-Xdebug']
mainClass = 'mypackage.MyApp'
args = ['some', 'args']
ports = ['1000', '2000-2003/udp']
labels = [key1:'value1', key2:'value2']
format = 'OCI'
}
}Setting the Base Image
There are three different types of base images that Jib accepts: an image from a container registry, an image stored in the Docker daemon, or an image tarball on the local filesystem. You can specify which you would like to use by prepending the jib.from.image configuration with a special prefix, listed below:
| Prefix | Example | Type |
|---|---|---|
| None | openjdk:11-jre |
Pulls the base image from a registry. |
registry:// |
registry://eclipse-temurin:11-jre |
Pulls the base image from a registry. |
docker:// |
docker://busybox |
Retrieves the base image from the Docker daemon. |
tar:// |
tar:///path/to/file.tar |
Uses an image tarball stored at the specified path as the base image. Also accepts relative paths (e.g. tar://build/jib-image.tar). |
Adding Arbitrary Files to the Image
You can add arbitrary, non-classpath files to the image without extra configuration by placing them in a src/main/jib directory. This will copy all files within the jib folder to the target directory (/ by default) in the image, maintaining the same structure (e.g. if you have a text file at src/main/jib/dir/hello.txt, then your image will contain /dir/hello.txt after being built with Jib).
Note that Jib does not follow symbolic links in the container image. If a symbolic link is present, it will be removed prior to placing the files and directories.
You can configure different directories by using the jib.extraDirectories.paths parameter in your build.gradle:
jib {
// Copies files from 'src/main/custom-extra-dir' and '/home/user/jib-extras' instead of 'src/main/jib'
extraDirectories.paths = ['src/main/custom-extra-dir', '/home/user/jib-extras']
}Alternatively, the jib.extraDirectories parameter can be used as a closure to set custom extra directories, as well as the extra files' permissions on the container:
jib {
extraDirectories {
paths = 'src/main/custom-extra-dir' // Copies files from 'src/main/custom-extra-dir'
permissions = [
'/path/on/container/to/fileA': '755', // Read/write/execute for owner, read/execute for group/other
'/path/to/another/file': '644', // Read/write for owner, read-only for group/other
'/glob/pattern/**/*.sh': 755
]
}
}Using paths as a closure, you may also specify the target of the copy and include or exclude files:
extraDirectories {
paths {
path {
// copies the contents of 'src/main/extra-dir' into '/' on the container
from = file('src/main/extra-dir')
}
path {
// copies the contents of 'src/main/another/dir' into '/extras' on the container
from = file('src/main/another/dir')
into = '/extras'
}
path {
// copies a single-file.xml
from = 'src/main/resources/xml-files'
into = '/dest-in-container'
includes = ['single-file.xml']
}
path {
// copies only .txt files except for 'hidden.txt' at the source root
from = 'build/some-output'
into = '/txt-files'
includes = ['*.txt', '**/*.txt']
excludes = ['hidden.txt']
}
}
}You can also configure paths and permissions through lazy configuration in Gradle, using providers in build.gradle:
extraDirectories {
paths = project.provider { 'src/main/custom-extra-dir' }
permissions = project.provider { ['/path/on/container/to/fileA': '755'] }
}extraDirectories {
paths {
path {
from = project.provider { 'src/main/custom-extra-dir' }
into = project.provider { '/dest-in-container' }
includes = project.provider { ['*.txt', '**/*.txt'] }
excludes = project.provider { ['hidden.txt'] }
}
}
}Authentication Methods
Pushing/pulling from private registries require authorization credentials.
Using Docker configuration files
- Jib looks from credentials from
$XDG_RUNTIME_DIR/containers/auth.json,$XDG_CONFIG_HOME/containers/auth.json,$HOME/.config/containers/auth.json,$DOCKER_CONFIG/config.json, and$HOME/.docker/config.json.
See this issue and man containers-auth.json for more information about the files.
Using Docker Credential Helpers
Docker credential helpers are CLI tools that handle authentication with various registries.
Some common credential helpers include:
- Google Container Registry:
docker-credential-gcr - AWS Elastic Container Registry:
docker-credential-ecr-login - Docker Hub Registry:
docker-credential-* - Azure Container Registry:
docker-credential-acr-*
Configure credential helpers to use by specifying them as a credHelper for their respective image in the jib extension.
Example configuration:
jib {
from {
image = 'aws_account_id.dkr.ecr.region.amazonaws.com/my-base-image'
credHelper = 'ecr-login'
}
to {
image = 'gcr.io/my-gcp-project/my-app'
credHelper = 'gcr'
}
}Using Specific Credentials
You can specify credentials directly in the extension for the from and/or to images.
jib {
from {
image = 'aws_account_id.dkr.ecr.region.amazonaws.com/my-base-image'
auth {
username = USERNAME // Defined in 'gradle.properties'.
password = PASSWORD
}
}
to {
image = 'gcr.io/my-gcp-project/my-app'
auth {
username = 'oauth2accesstoken'
password = 'gcloud auth print-access-token'.execute().text.trim()
}
}
}These credentials can be stored in gradle.properties, retrieved from a command (like gcloud auth print-access-token), or read in from a file.
For example, you can use a key file for authentication (for GCR, see Using a JSON key file):
jib {
to {
image = 'gcr.io/my-gcp-project/my-app'
auth {
username = '_json_key'
password = file('keyfile.json').text
}
}
}Custom Container Entrypoint
If you don't set jib.container.entrypoint, the default container entrypoint to launch your app will be basically java -cp <runtime classpath> <app main class>. (The final java command can be further configured by setting jib.container.{jvmFlags|args|extraClasspath|mainClass|expandClasspathDependencies}.)
Sometimes, you'll want to set a custom entrypoint to use a shell to wrap the java command. For example, to let sh or bash expand environment variables, or to have more sophisticated logic to construct a launch command. (Note, however, that running a command with a shell forks a new child process unless you run it with exec like sh -c "exec java ...". Whether to run the JVM process as PID 1 or a child process of a PID-1 shell is a decision you should make carefully.) In this scenario, you will want to have a way inside a shell script to reliably know the default runtime classpath and the main class that Jib would use by default. To help this, Jib >= 3.1 creates two JVM argument files under /app (the default app root) inside the built image.
/app/jib-classpath-file: runtime classpath that Jib would use for default app launch/app/jib-main-class-file: main class
Therefore, for example, the following commands will be able to launch your app:
- (Java 9+)
java -cp @/app/jib-classpath-file @/app/jib-main-class-file - (with shell)
java -cp $( cat /app/jib-classpath-file ) $( cat /app/jib-main-class-file )
Reproducible Build Timestamps
To ensure that a Jib build is reproducible, Jib sets the image creation time to the Unix epoch (00:00:00, January 1st, 1970 in UTC) and all file modification times to one second past the epoch by default. See the Jib FAQ for more details on reproducible builds.
Another, more complex way to achieve reproducible builds with stable creation times is to leverage commit timestamps from the project's SCM. For example, the gradle-git-properties plugin can be used to inject Git commit information into the current build. These can then be used to configure jib.container.creationTime. Since the actual Git information is not yet available at the time the build is configured, it needs to be set through lazy configuration in Gradle, using a provider in build.gradle:
jib {
container {
creationTime = project.provider { project.ext.git['git.commit.time'] }
}
}This would build an image with the creation time set to the time of the latest commit from project.ext.git['git.commit.time'].
Jib Extensions
The Jib build plugins have an extension framework that enables anyone to easily extend Jib's behavior to their needs. We maintain select first-party plugins for popular use cases like fine-grained layer control and Quarkus support, but anyone can write and publish an extension. Check out the jib-extensions repository for more information.
WAR Projects
Jib also containerizes WAR projects. If the Gradle project uses the WAR Plugin, Jib will by default use jetty as a base image to deploy the project WAR. No extra configuration is necessary other than using the WAR Plugin to make Jib build WAR images.
Note that Jib will work slightly differently for WAR projects from JAR projects:
container.mainClassandcontainer.jvmFlagsare ignored.- The WAR will be exploded into
/var/lib/jetty/webapps/ROOT, which is the expected WAR location for the Jetty base image.
To use a different Servlet engine base image, you can customize container.appRoot, container.entrypoint, and container.args. If you do not set entrypoint or args, Jib will inherit the ENTRYPOINT and CMD of the base image, so in many cases, you may not need to configure them. However, you will most likely have to set container.appRoot to a proper location depending on the base image. Here is an example of using a Tomcat image:
jib {
from.image = 'tomcat:8.5-jre8-alpine'
// For demonstration only: this directory in the base image contains a Tomcat default
// app (welcome page), so you may first want to delete this directory in the base image.
container.appRoot = '/usr/local/tomcat/webapps/ROOT'
}When specifying a jetty image yourself with from.image, you may run into an issue (#3204) and need to override the entrypoint.
jib {
from.image = 'jetty:11.0.2-jre11'
container.entrypoint = ['java', '-jar', '/usr/local/jetty/start.jar']
}Skaffold Integration
Jib is an included builder in Skaffold. Jib passes build information to skaffold through special internal tasks so that skaffold understands when it should rebuild or synchronize files. For complex builds, the defaults may not be sufficient, so the jib extension provides a skaffold configuration closure which exposes:
| Field | Type | Default | Description |
|---|---|---|---|
watch |
watch |
None | Additional configuration for file watching |
sync |
sync |
None | Additional configuration for file synchronization |
watch is a closure with the following properties:
| Field | Type | Default | Description |
|---|---|---|---|
buildIncludes |
List<String> |
None | Additional build files that skaffold should watch |
includes |
List<String> |
None | Additional project files or directories that skaffold should watch |
excludes |
List<String> |
None | Files and directories that skaffold should not watch |
sync is a closure with the following properties:
| Field | Type | Default | Description |
|---|---|---|---|
excludes |
List<String> |
None | Files and directories that skaffold should not sync |
Need Help?
A lot of questions are already answered!
For usage questions, please ask them on Stack Overflow.
Privacy
See the Privacy page.
Upcoming Features
See Milestones for planned features. Get involved with the community for the latest updates.
Community
See the Jib project README.
Disclaimer
This is not an officially supported Google product.
Overview (`jib-maven-plugin/README.md`)
Jib - Containerize your Maven project
Jib is a Maven plugin for building Docker and OCI images for your Java applications.
For the Gradle plugin, see the jib-gradle-plugin project.
For information about the project, see the Jib project README.
| ☑️ Jib User Survey |
|---|
| What do you like best about Jib? What needs to be improved? Please tell us by taking a one-minute survey. Your responses will help us understand Jib usage and allow us to serve our customers (you!) better. |
Table of Contents
- Upcoming Features
- Quickstart
- Multi Module Projects
- Extended Usage
- Need Help?
- Community
Quickstart
You can containerize your application easily with one command:
mvn compile com.google.cloud.tools:jib-maven-plugin:3.5.2:build -Dimage=<MY IMAGE>This builds and pushes a container image for your application to a container registry. If you encounter authentication issues, see Authentication Methods.
To build to a Docker daemon, use:
mvn compile com.google.cloud.tools:jib-maven-plugin:3.5.2:dockerBuildIf you would like to set up Jib as part of your Maven build, follow the guide below.
Setup
In your Maven Java project, add the plugin to your pom.xml:
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.5.2</version>
<configuration>
<to>
<image>myimage</image>
</to>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>Configuration
Configure the plugin by setting the image to push to:
Using [Google Container Registry (GCR)](https://cloud.google.com/container-registry/)...
Make sure you have the docker-credential-gcr command line tool. Jib automatically uses docker-credential-gcr for obtaining credentials. See Authentication Methods for other ways of authenticating.
For example, to build the image gcr.io/my-gcp-project/my-app, the configuration would be:
<configuration>
<to>
<image>gcr.io/my-gcp-project/my-app</image>
</to>
</configuration>Using [Amazon Elastic Container Registry (ECR)](https://aws.amazon.com/ecr/)...
Make sure you have the docker-credential-ecr-login command line tool. Jib automatically uses docker-credential-ecr-login for obtaining credentials. See Authentication Methods for other ways of authenticating.
For example, to build the image aws_account_id.dkr.ecr.region.amazonaws.com/my-app, the configuration would be:
<configuration>
<to>
<image>aws_account_id.dkr.ecr.region.amazonaws.com/my-app</image>
</to>
</configuration>Using [Docker Hub Registry](https://hub.docker.com/)...
Make sure you have a docker-credential-helper set up. For example, on macOS, the credential helper would be docker-credential-osxkeychain. See Authentication Methods for other ways of authenticating.
For example, to build the image my-docker-id/my-app, the configuration would be:
<configuration>
<to>
<image>docker.io/my-docker-id/my-app</image>
</to>
</configuration>Using [JFrog Container Registry (JCR)](https://jfrog.com/container-registry) or [JFrog Artifactory](https://jfrog.com/help/r/jfrog-artifactory-documentation/getting-started-with-artifactory-as-a-docker-registry)...
Make sure you have a docker-credential-helper set up. For example, on macOS, the credential helper would be docker-credential-osxkeychain. See Authentication Methods for other ways of authenticating.
For example, to build the image my-company-docker-local.jfrog.io/my-app, the configuration would be:
<configuration>
<to>
<image>my-company-docker-local.jfrog.io/my-app</image>
</to>
</configuration>Using [Azure Container Registry (ACR)](https://azure.microsoft.com/en-us/services/container-registry/)...
Make sure you have a ACR Docker Credential Helper installed and set up. For example, on Windows, the credential helper would be docker-credential-acr-windows. See Authentication Methods for other ways of authenticating.
For example, to build the image my_acr_name.azurecr.io/my-app, the configuration would be:
<configuration>
<to>
<image>my_acr_name.azurecr.io/my-app</image>
</to>
</configuration>Build your image
Build your container image with:
mvn compile jib:buildSubsequent builds are much faster than the initial build.
Having trouble? Let us know by submitting an issue, contacting us on Gitter, or posting to the Jib users forum.
Build to Docker daemon
Jib can also build your image directly to a Docker daemon. This uses the docker command line tool and requires that you have docker available on your PATH.
mvn compile jib:dockerBuildIf you are using minikube's remote Docker daemon, make sure you set up the correct environment variables to point to the remote daemon:
eval $(minikube docker-env)
mvn compile jib:dockerBuildAlternatively, you can set environment variables in the Jib configuration. See dockerClient for more configuration options.
Build an image tarball
You can build and save your image to disk as a tarball with:
mvn compile jib:buildTarThis builds and saves your image to target/jib-image.tar, which you can load into docker with:
docker load --input target/jib-image.tarBind to a lifecycle
You can also bind jib:build to a Maven lifecycle, such as package, by adding the following execution to your jib-maven-plugin definition:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
...
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>Then, you can build your container image by running:
mvn packageAdditional Build Artifacts
As part of an image build, Jib also writes out the image digest and the image ID. By default, these are written out to target/jib-image.digest and target/jib-image.id respectively, but the locations can be configured using the <outputPaths><digest> and <outputPaths> configuration properties. See Extended Usage for more details.
Multi Module Projects
Special handling of project dependencies is recommended when building complex
multi module projects. See Multi Module Example for detailed information.
Extended Usage
Extended configuration options provide additional options for customizing the image build.
| Field | Type | Default | Description |
|---|---|---|---|
to |
to |
Required | Configures the target image to build your application to. |
from |
from |
See from |
Configures the base image to build your application on top of. |
container |
container |
See container |
Configures the container that is run from your image. |
extraDirectories |
extraDirectories |
See extraDirectories |
Configures the directories used to add arbitrary files to the image. |
outputPaths |
outputPaths |
See outputPaths |
Configures the locations of additional build artifacts generated by Jib. |
dockerClient |
dockerClient |
See dockerClient |
Configures Docker for building to/from the Docker daemon. |
skaffold |
skaffold |
See skaffold |
Configures the internal skaffold goals. This configuration should only be used when integrating with skaffold. |
containerizingMode |
string | exploded |
If set to packaged, puts the JAR artifact built at ${project.build.directory}/${project.build.finalName}.jar (the default location where many JAR-building plugins put a JAR registered as a main artifact, such as the Maven JAR Plugin) into the final image. If set to exploded (default), containerizes individual .class files and resources files. |
allowInsecureRegistries |
boolean | false |
If set to true, Jib ignores HTTPS certificate errors and may fall back to HTTP as a last resort. Leaving this parameter set to false is strongly recommended, since HTTP communication is unencrypted and visible to others on the network, and insecure HTTPS is no better than plain HTTP. If accessing a registry with a self-signed certificate, adding the certificate to your Java runtime's trusted keys may be an alternative to enabling this option. |
skip |
boolean | false |
If set to true, Jib execution is skipped (useful for multi-module projects). This can also be specified via the -Djib.skip command line option. |
from is an object with the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
image |
string | eclipse-temurin:{8,11,17,21,25}-jre (or jetty for WAR) |
The image reference for the base image. The source type can be specified using a special type prefix. |
auth |
auth |
None | Specifies credentials directly (alternative to credHelper). |
credHelper |
string | None | Specifies a credential helper that can authenticate pulling the base image. This parameter can either be configured as an absolute path to the credential helper executable or as a credential helper suffix (following docker-credential-). |
platforms |
list | See platform |
Configures platforms of base images to select from a manifest list. |
to is an object with the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
image |
string | Required | The image reference for the target image. This can also be specified via the -Dimage command line option. If the tag is not present here :latest is implied. |
auth |
auth |
None | Specifies credentials directly (alternative to credHelper). |
credHelper |
string | None | Specifies a credential helper that can authenticate pushing the target image. This parameter can either be configured as an absolute path to the credential helper executable or as a credential helper suffix (following docker-credential-). |
tags |
list | None | Additional tags to push to. |
auth is an object with the following properties (see Using Specific Credentials):
| Property | Type |
|---|---|
username |
string |
password |
string |
platform is an object with the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
architecture |
string | amd64 |
The architecture of a base image to select from a manifest list. |
os |
string | linux |
The OS of a base image to select from a manifest list. |
See How do I specify a platform in the manifest list (or OCI index) of a base image? for examples.
container is an object with the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
appRoot |
string | /app |
The root directory on the container where the app's contents are placed. Particularly useful for WAR-packaging projects to work with different Servlet engine base images by designating where to put exploded WAR contents; see WAR usage as an example. |
args |
list | None | Additional program arguments appended to the command to start the container (similar to Docker's CMD instruction in relation with ENTRYPOINT). In the default case where you do not set a custom entrypoint, this parameter is effectively the arguments to the main method of your Java application. |
creationTime |
string | EPOCH |
Sets the container creation time. (Note that this property does not affect the file modification times, which are configured using <filesModificationTime>.) The value can be EPOCH to set the timestamps to Epoch (default behavior), USE_CURRENT_TIMESTAMP to forgo reproducibility and use the real creation time, or an ISO 8601 date-time parsable with DateTimeFormatter.ISO_DATE_TIME such as 2019-07-15T10:15:30+09:00 or 2011-12-03T22:42:05Z. |
entrypoint |
list | None | The command to start the container with (similar to Docker's ENTRYPOINT instruction). If set, then jvmFlags, mainClass, extraClasspath, and expandClasspathDependencies are ignored. You may also set <entrypoint>INHERIT</entrypoint> (<entrypoint><entry>INHERIT</entry></entrypoint> in old Maven versions) to indicate that the entrypoint and args should be inherited from the base image.* |
environment |
map | None | Key-value pairs for setting environment variables on the container (similar to Docker's ENV instruction). |
extraClasspath |
list | None | Additional paths in the container to prepend to the computed Java classpath. |
expandClasspathDependencies |
boolean | false |
/app/lib/*) for dependency JARs in the default Java runtime classpath but instead enumerates the JARs. Has the effect of preserving the classpath loading order as defined by the Maven project.--class-path JVM argument. |
filesModificationTime |
string | EPOCH_PLUS_SECOND |
Sets the modification time (last modified time) of files in the image put by Jib. (Note that this does not set the image creation time, which can be set using <creationTime>.) The value should either be EPOCH_PLUS_SECOND to set the timestamps to Epoch + 1 second (default behavior), or an ISO 8601 date-time parsable with DateTimeFormatter.ISO_DATE_TIME such as 2019-07-15T10:15:30+09:00 or 2011-12-03T22:42:05Z. |
format |
string | Docker |
Use OCI to build an OCI container image. |
jvmFlags |
list | None | Additional flags to pass into the JVM when running your application. |
labels |
map | None | Key-value pairs for applying image metadata (similar to Docker's LABEL instruction). |
mainClass |
string | Inferred** | The main class to launch the application from. |
ports |
list | None | Ports that the container exposes at runtime (similar to Docker's EXPOSE instruction). |
user |
string | None | The user and group to run the container as. The value can be a username or UID along with an optional groupname or GID. The following are all valid: user, uid, user:group, uid:gid, uid:group, user:gid. |
volumes |
list | None | Specifies a list of mount points on the container. |
workingDirectory |
string | None | The working directory in the container. |
extraDirectories is an object with the following properties (see Adding Arbitrary Files to the Image):
| Property | Type | Default | Description |
|---|---|---|---|
paths |
list | [(project-dir)/src/main/jib] |
List of path objects and/or extra directory paths. Can be absolute or relative to the project root. |
permissions |
list | None | Maps file paths (glob patterns) on container to Unix permissions. (Effective only for files added from extra directories.) If not configured, permissions default to "755" for directories and "644" for files. See Adding Arbitrary Files to the Image for an example. |
path is an object with the following properties (see Adding Arbitrary Files to the Image):
| Property | Type | Default | Description |
|---|---|---|---|
from |
file | [(project-dir)/src/main/jib] |
The source directory. Can be absolute or relative to the project root. |
into |
string | / |
The absolute unix path on the container to copy the extra directory contents into. |
includes |
list | None | Glob patterns for including files. See Adding Arbitrary Files to the Image for an example. |
excludes |
list | None | Glob patterns for excluding files. See Adding Arbitrary Files to the Image for an example. |
outputPaths is an object with the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
tar |
string | (project-dir)/target/jib-image.tar |
The path of the tarball generated by jib:buildTar. Relative paths are resolved relative to the project root. |
digest |
string | (project-dir)/target/jib-image.digest |
The path of the image digest written out during the build. Relative paths are resolved relative to the project root. |
imageId |
string | (project-dir)/target/jib-image.id |
The path of the image ID written out during the build. Relative paths are resolved relative to the project root. |
imageJson |
string | (project-dir)/target/jib-image.json |
The path of the image metadata json file written out during the build. Relative paths are resolved relative to the project root. |
dockerClient is an object used to configure Docker when building to/from the Docker daemon. It has the following properties:
| Property | Type | Default | Description |
|---|---|---|---|
executable |
string | docker |
Sets the path to the Docker executable that is called to load the image into the Docker daemon. Please note: Users are responsible for ensuring that the Docker path passed in is valid and has the right permissions to be executed. |
environment |
map | None | Sets environment variables used by the Docker executable. |
Configuration Properties
Each of these parameters is configurable via commandline using properties. Jib's properties follow the same naming convention as the configuration parameters, with each level separated by dots (i.e. -Djib.parameterName[.nestedParameter.[...]]=value). Some examples are below:
mvn compile jib:build \
-Djib.to.image=myregistry/myimage:latest \
-Djib.to.auth.username=$USERNAME \
-Djib.to.auth.password=$PASSWORD
mvn compile jib:dockerBuild \
-Djib.dockerClient.executable=/path/to/docker \
-Djib.container.environment=key1="value1",key2="value2" \
-Djib.container.args=arg1,arg2,arg3The following table contains additional properties that are not available as build configuration parameters:
| Property | Type | Default | Description |
|---|---|---|---|
jib.httpTimeout |
int | 20000 |
HTTP connection/read timeout for registry interactions, in milliseconds. Use a value of 0 for an infinite timeout. |
jib.useOnlyProjectCache |
boolean | false |
If set to true, Jib does not share a cache between different Maven projects (i.e. jib.baseImageCache defaults to [project dir]/target/jib-cache instead of [user cache home]/google-cloud-tools-java/jib). |
jib.baseImageCache |
string | Platform-dependent*** | Sets the directory to use for caching base image layers. This cache can (and should) be shared between multiple images. |
jib.applicationCache |
string | [project dir]/target/jib-cache |
Sets the directory to use for caching application layers. This cache can be shared between multiple images. |
jib.console |
string | None | If set to plain, Jib will print plaintext log messages rather than display a progress bar during the build. |
* If you configure args while entrypoint is set to 'INHERIT', the configured args value will take precedence over the CMD propagated from the base image.
** Uses the main class defined in the jar task or tries to find a valid main class.
*** The default base image cache is in the following locations on each platform:
- Linux:
[cache root]/google-cloud-tools-java/jib/, where[cache root]is$XDG_CACHE_HOME($HOME/.cache/if not set) - Mac:
[cache root]/Google/Jib/, where[cache root]is$XDG_CACHE_HOME($HOME/Library/Caches/if not set) - Windows:
[cache root]\Google\Jib\Cache, where[cache root]is%XDG_CACHE_HOME%(%LOCALAPPDATA%if not set)
Global Jib Configuration
Some options can be set in the global Jib configuration file. The file is at the following locations on each platform:
- Linux:
[config root]/google-cloud-tools-java/jib/config.json, where[config root]is$XDG_CONFIG_HOME($HOME/.config/if not set) - Mac:
[config root]/Google/Jib/config.json, where[config root]is$XDG_CONFIG_HOME($HOME/Library/Preferences/if not set) - Windows:
[config root]\Google\Jib\Config\config.json, where[config root]is%XDG_CONFIG_HOME%(%LOCALAPPDATA%if not set)
Properties
disableUpdateCheck: when set to true, disables the periodic up-to-date version check.registryMirrors: a list of mirror settings for each base image registry. In the following example, if the base image configured in Jib is for a Docker Hub image, thenmirror.gcr.io,localhost:5000, and the Docker Hub (registry-1.docker.io) are tried in order until Jib can successfully pull a base image.
{
"disableUpdateCheck": false,
"registryMirrors": [
{
"registry": "registry-1.docker.io",
"mirrors": ["mirror.gcr.io", "localhost:5000"]
},
{
"registry": "quay.io",
"mirrors": ["private-mirror.test.com"]
}
]
}Note about mirror.gcr.io: it is not a Docker Hub mirror but a cache. It caches frequently-accessed public Docker Hub images, and it's often possible that your base image does not exist in mirror.gcr.io. In that case, Jib will have to fall back to use Docker Hub.
Example
In this configuration, the image:
- Is built from a base of
openjdk:alpine(pulled from Docker Hub) - Is pushed to
localhost:5000/my-image:built-with-jib,localhost:5000/my-image:tag2, andlocalhost:5000/my-image:latest - Runs by calling
java -Dmy.property=example.value -Xms512m -Xdebug -cp app/libs/*:app/resources:app/classes mypackage.MyApp some args - Exposes port 1000 for tcp (default), and ports 2000, 2001, 2002, and 2003 for udp
- Has two labels (key1:value1 and key2:value2)
- Is built as OCI format
<configuration>
<from>
<image>openjdk:alpine</image>
</from>
<to>
<image>localhost:5000/my-image:built-with-jib</image>
<credHelper>osxkeychain</credHelper>
<tags>
<tag>tag2</tag>
<tag>latest</tag>
</tags>
</to>
<container>
<jvmFlags>
<jvmFlag>-Dmy.property=example.value</jvmFlag>
<jvmFlag>-Xms512m</jvmFlag>
<jvmFlag>-Xdebug</jvmFlag>
</jvmFlags>
<mainClass>mypackage.MyApp</mainClass>
<args>
<arg>some</arg>
<arg>args</arg>
</args>
<ports>
<port>1000</port>
<port>2000-2003/udp</port>
</ports>
<labels>
<key1>value1</key1>
<key2>value2</key2>
</labels>
<format>OCI</format>
</container>
</configuration>Setting the Base Image
There are three different types of base images that Jib accepts: an image from a container registry, an image stored in the Docker daemon, or an image tarball on the local filesystem. You can specify which you would like to use by prepending the <from> configuration with a special prefix, listed below:
| Prefix | Example | Type |
|---|---|---|
| None | openjdk:11-jre |
Pulls the base image from a registry. |
registry:// |
registry://eclipse-temurin:11-jre |
Pulls the base image from a registry. |
docker:// |
docker://busybox |
Retrieves the base image from the Docker daemon. |
tar:// |
tar:///path/to/file.tar |
Uses an image tarball stored at the specified path as the base image. Also accepts relative paths (e.g. tar://target/jib-image.tar). |
Adding Arbitrary Files to the Image
You can add arbitrary, non-classpath files to the image by placing them in a src/main/jib directory. This will copy all files within the jib folder to the target directory (/ by default) in the image, maintaining the same structure (e.g. if you have a text file at src/main/jib/dir/hello.txt, then your image will contain /dir/hello.txt after being built with Jib).
Note that Jib does not follow symbolic links in the container image. If a symbolic link is present, it will be removed prior to placing the files and directories.
You can configure different directories by using the <extraDirectories> parameter in your pom.xml:
<configuration>
<extraDirectories>
<paths>
<path>src/main/custom-extra-dir</path>
<path>
<from>/home/user/jib-extras</from>
<into>/extras</into>
</path>
</paths>
</extraDirectories>
</configuration>Alternatively, the <extraDirectories> parameter can be used as an object to set custom extra directories, as well as the extra files' permissions on the container:
<extraDirectories>
<paths>src/main/custom-extra-dir</paths>
<permissions>
<permission>
<file>/path/on/container/to/fileA</file>
<mode>755</mode>
</permission>
<permission>
<file>/path/to/another/file</file>
<mode>644</mode>
</permission>
<permission>
<file>/glob/pattern/**/*.sh</file>
<mode>755</mode>
</permission>
</permissions>
</extraDirectories>You may also specify the target of the copy and include or exclude files:
<extraDirectories>
<paths>
<path>
// copies the contents of 'src/main/extra-dir' into '/' on the container
<from>src/main/extra-dir</from>
</path>
<path>
// copies the contents of 'src/main/another/dir' into '/extras' on the container
<from>src/main/another/dir</from>
<into>/extras</into>
</path>
<path>
// copies a single-file.xml
<from>src/main/resources/xml-files</from>
<into>/dest-in-container</into>
<includes>single-file.xml</includes>
</path>
<path>
// copies only .txt files except for 'hidden.txt' at the source root
<from>build/some-output</from>
<into>/txt-files</into>
<includes>*.txt,**/*.txt</includes>
<excludes>
<exclude>hidden.txt</exclude>
</excludes>
</path>
</paths>
</extraDirectories>Authentication Methods
Pushing/pulling from private registries require authorization credentials.
Using Docker configuration files
- Jib looks from credentials from
$XDG_RUNTIME_DIR/containers/auth.json,$XDG_CONFIG_HOME/containers/auth.json,$HOME/.config/containers/auth.json,$DOCKER_CONFIG/config.json, and$HOME/.docker/config.json.
See this issue and man containers-auth.json for more information about the files.
Using Docker Credential Helpers
Docker credential helpers are CLI tools that handle authentication with various registries.
Some common credential helpers include:
- Google Container Registry:
docker-credential-gcr - AWS Elastic Container Registry:
docker-credential-ecr-login - Docker Hub Registry:
docker-credential-* - Azure Container Registry:
docker-credential-acr-*
Configure credential helpers to use by specifying them as a credHelper for their respective image.
Example configuration:
<configuration>
...
<from>
<image>aws_account_id.dkr.ecr.region.amazonaws.com/my-base-image</image>
<credHelper>ecr-login</credHelper>
</from>
<to>
<image>gcr.io/my-gcp-project/my-app</image>
<credHelper>gcr</credHelper>
</to>
...
</configuration>Using Specific Credentials
You can specify credentials directly in the <auth> parameter for the from and/or to images. In the example below, to credentials are retrieved from the REGISTRY_USERNAME and REGISTRY_PASSWORD environment variables.
<configuration>
...
<from>
<image>aws_account_id.dkr.ecr.region.amazonaws.com/my-base-image</image>
<auth>
<username>my_username</username>
<password>my_password</password>
</auth>
</from>
<to>
<image>gcr.io/my-gcp-project/my-app</image>
<auth>
<username>${env.REGISTRY_USERNAME}</username>
<password>${env.REGISTRY_PASSWORD}</password>
</auth>
</to>
...
</configuration>Alternatively, you can specify credentials via commandline using the following system properties.
| Property | Description |
|---|---|
-Djib.from.auth.username |
Username for base image registry. |
-Djib.from.auth.password |
Password for base image registry. |
-Djib.to.auth.username |
Username for target image registry. |
-Djib.to.auth.password |
Password for target image registry. |
e.g. mvn compile jib:build -Djib.to.auth.username=user -Djib.to.auth.password=pass
Note: This method of authentication should be used only as a last resort, as it is insecure to make your password visible in plain text. Note that often cloud registries (for example, Google GCR, Amazon ECR, and Azure ACR) do not accept "user credentials" (such as Gmail account name and password) but require different forms of credentials. For example, you may use oauth2accesstoken or _json_key as the username for GCR, and AWS for ECR. For ACR, you may use a service principle.
Using Maven Settings
Registry credentials can be added to your Maven settings. These credentials will be used if credentials could not be found in any specified Docker credential helpers.
If you're considering putting credentials in Maven, we highly recommend using maven password encryption.
Example settings.xml:
<settings>
...
<servers>
...
<server>
<id>MY_REGISTRY</id>
<username>MY_USERNAME</username>
<password>{MY_SECRET}</password>
</server>
</servers>
</settings>- The
idfield should be the registry server these credentials are for. - We do not recommend putting your raw password in
settings.xml.
Custom Container Entrypoint
If you don't set <container><entrypoint>, the default container entrypoint to launch your app will be basically java -cp <runtime classpath> <app main class>. (The final java command can be further configured by setting <container>{<jvmFlags>|<args>|<extraClasspath>|<mainClass>|<expandClasspathDependencies>}.)
Sometimes, you'll want to set a custom entrypoint to use a shell to wrap the java command. For example, to let sh or bash expand environment variables, or to have more sophisticated logic to construct a launch command. (Note, however, that running a command with a shell forks a new child process unless you run it with exec like sh -c "exec java ...". Whether to run the JVM process as PID 1 or a child process of a PID-1 shell is a decision you should make carefully.) In this scenario, you will want to have a way inside a shell script to reliably know the default runtime classpath and the main class that Jib would use by default. To help this, Jib >= 3.1 creates two JVM argument files under /app (the default app root) inside the built image.
/app/jib-classpath-file: runtime classpath that Jib would use for default app launch/app/jib-main-class-file: main class
Therefore, for example, the following commands will be able to launch your app:
- (Java 9+)
java -cp @/app/jib-classpath-file @/app/jib-main-class-file - (with shell)
java -cp $( cat /app/jib-classpath-file ) $( cat /app/jib-main-class-file )
Jib Extensions
The Jib build plugins have an extension framework that enables anyone to easily extend Jib's behavior to their needs. We maintain select first-party plugins for popular use cases like fine-grained layer control, builds a GraalVM native image, and Quarkus support, but anyone can write and publish an extension. Check out the jib-extensions repository for more information.
WAR Projects
Jib also containerizes WAR projects. If the Maven project uses the war-packaging type, Jib will by default use jetty as a base image to deploy the project WAR. No extra configuration is necessary other than having the packaging type to war.
Note that Jib will work slightly differently for WAR projects from JAR projects:
<container><mainClass>and<container><jvmFlags>are ignored.- The WAR will be exploded into
/var/lib/jetty/webapps/ROOT, which is the expected WAR location for the Jetty base image.
To use a different Servlet engine base image, you can customize <container><appRoot>, <container><entrypoint>, and <container><args>. If you do not set entrypoint or args, Jib will inherit the ENTRYPOINT and CMD of the base image, so in many cases, you may not need to configure them. However, you will most likely have to set <container><appRoot> to a proper location depending on the base image. Here is an example of using a Tomcat image:
<configuration>
<from>
<image>tomcat:8.5-jre8-alpine</image>
</from>
<container>
<appRoot>/usr/local/tomcat/webapps/ROOT</appRoot>
</container>
</configuration>When specifying a jetty image yourself with <from>, you may run into an issue (#3204) and need to override the entrypoint.
<configuration>
<from>
<image>jetty:11.0.2-jre11</image>
</from>
<container>
<entrypoint>java,-jar,/usr/local/jetty/start.jar</entrypoint>
</container>
</configuration>Skaffold Integration
Jib is an included builder in Skaffold. Jib passes build information to skaffold through special internal goals so that skaffold understands when it should rebuild or synchronize files. For complex builds, the defaults may not be sufficient, so the jib plugin provides a skaffold configuration object which exposes:
| Field | Type | Default | Description |
|---|---|---|---|
watch |
watch |
None | Additional configuration for file watching |
sync |
sync |
None | Additional configuration for file synchronization |
watch is an object with the following properties:
| Field | Type | Default | Description |
|---|---|---|---|
buildIncludes |
List<String> |
None | Additional build files that skaffold should watch |
includes |
List<String> |
None | Additional project files or directories that skaffold should watch |
excludes |
List<String> |
None | Files and directories that skaffold should not watch |
sync is an object with the following properties:
| Field | Type | Default | Description |
|---|---|---|---|
excludes |
List<String> |
None | Files and directories that skaffold should not sync |
Need Help?
A lot of questions are already answered!
For usage questions, please ask them on Stack Overflow.
Privacy
See the Privacy page.
Upcoming Features
See Milestones for planned features. Get involved with the community for the latest updates.
Community
See the Jib project README.
Disclaimer
This is not an officially supported Google product.
Overview (`jib-plugins-common/README.md`)
Common code for Jib plugins. NOT intended for use outside of jib-maven-plugin or jib-gradle-plugin in its current state.
Overview (`proposals/README.md`)
Design Documents and Proposals
This directory holds the approved design documents and proposals for changes and new features to Jib.
Contribute
Submit a Proposal
Submit a proposal by filing a pull request that adds a .md file to this directory.
Follow the general layout of existing proposals. In general, make sure to include:
- Description of the problem
- Goals to achieve
- Proposed solution to the problem
Proposals are approved upon merge.
Review a Proposal
Review pending proposals by commenting on their pull requests. Proposals in review are labelled with proposal.
For approved proposals, you may open revision pull requests with your suggestions for revision, or provide your comments in a new issue or messaging the community.
Overview (`examples/dropwizard/README.md`)
Containerize a [Dropwizard](https://dropwizard.io) application with Jib
How to start the Dropwizard application
- Run
./mvnw clean packageto build your container - Start the application
- With Docker:
docker run --rm -p 8080:8080 dropwizard-jib-example:1 - Without Docker:
./mvnw exec:java
- With Docker:
- Check that your application is running at http://localhost:8080
Health Check
See your application's health at http://localhost:8080/admin/healthcheck
Extras
FreeMaker templating is setup for dropwizard.yml through tkrille/dropwizard-template-config; this allows one to heavily customize the properties file via the container environment with FTL conditional checks and for loops, for example.
How this example was generated
Starter Maven template generated with dropwizard-archetypes
mvn archetype:generate \
-DarchetypeGroupId=io.dropwizard.archetypes \
-DarchetypeArtifactId=example \
-DarchetypeVersion=[REPLACE ME WITH A VALID DROPWIZARD VERSION]Ref. Dropwizard - Getting Started, Setting up With Maven
The remainder of the archetype code was filled-in following the above guide.
More information
Learn more about Jib.
Learn more about Dropwizard.
Build and run on Google Cloud
Overview (`examples/helloworld/README.md`)
Builds a container image that outputs Hello World when run.
To build the image:
In
pom.xmlorbuild.gradle, replaceREPLACE-WITH-YOUR-GCP-PROJECTwith your GCP project.Run
mvn compile jib:buildor./gradlew jib.
Overview (`examples/java-agent/README.md`)
This SparkJava-based example builds a container image that includes the Stackdriver Debugger Java Agent.
This project assumes the resulting image will be run inside Google Cloud Platform.
To build the image:
Replace
REPLACE-WITH-YOUR-GCP-PROJECTwith your GCP project inpom.xmlorbuild.gradle.Run
mvn packageor./gradlewto build the image.
SparkJava listens on port 4567 by default.
Build and run on Google Cloud
Overview (`examples/ktor/README.md`)
Containerize a [Ktor] application with Jib
This is an example of how to easily build a Docker image for a Ktor application with Jib.
./gradlew jibDockerBuild
docker run --rm -p 8080:8080 ktor-jib-example:1The application can also be ran outside of Jib's build process via ./gradlew run
Defined environment variables
A few variables have been added in the code-base to show case some of the unique features of Ktor.
KTOR_APP_ID- The name of the application in the logs- Type: String
KTOR_METRICS_ENABLED- Exposes JMX Metrics through the application port (8080)- Type: Boolean (default:
false)
- Type: Boolean (default:
KTOR_ROUTE_TRACING- Enables verbose logging of route matches for debugging complex/nested routing tables- Type: Boolean
More information
Learn more about Jib.
Learn Ktor.
Overview (`examples/micronaut/README.md`)
Containerize a [Micronaut](http://micronaut.io/) app with Jib
This is an example of how to easily build a Docker image for a Micronaut framework Groovy/Java application with Jib.
Quickstart
With Docker
./gradlew jibDockerBuild
docker run -d -p 8080:8080 micronaut-jib:0.1curl localhost:8080/hello
> Hello WorldWith Kubernetes
IMAGE=<your image, eg. gcr.io/my-project/micronaut-jib>
./gradlew jib --image=$IMAGE
kubectl run micronaut-jib --image=$IMAGE --port=8080 --restart=Never
# Wait until pod is running
kubectl port-forward micronaut-jib 8080 > /dev/null 2>&1 &curl localhost:8080/hello
> Hello WorldMore information
Learn more about Jib.
Learn more about Micronaut.
Overview (`examples/multi-module/README.md`)
Multi-module example
This example shows how to build multiple containers for a multi-module project in both Maven and Gradle.
How the example is set up
The project consists of two microservices and a library:
name-service- responds with a nameshared-library- a project dependency used byname-servicehello-service- callsname-serviceand responds with a greeting
The Maven project is set up with a parent POM (pom.xml) that defines most of the common build configuration. The module POMs (name-service/pom.xml and hello-service/pom.xml) just define inheritance on the parent POM. However, if needed, the module POMs can define custom configuration on jib-maven-plugin specific to that module.
The Gradle project is set up with a parent build.gradle that sets some common configuration up for all projects, with each sub-project containing its own build.gradle with some custom configuration. settings.gradle defines which modules to include in the overall build.
Reproducibility of dependency module `shared-library`
Since dependency module builds happen with the underlying build system
(maven/gradle), we must add some extra configuration to ensure that the
resulting jar that is built conforms to our reproducibility expectations.
The module shared-library uses the Reproducible Build Maven Plugin
for maven, and some special Jar properties (preserveFileTimestamps,reproducibleFileOrder)
in gradle to achieve this. This configuration can be seen in theshared-library's pom.xml and build.gradle.
Care must be taken when adding custom attributes to a MANIFEST.MF.
Attributes whose values change on every build can affect reproducibility even
with the modifications outlined above.
How to run
Set the PROJECT_ID environment variable to your own Google Cloud Platform project:
export PROJECT_ID=$(gcloud config list --format 'value(core.project)')Run the Maven build:
# build everything
./mvnw package jib:build
# build just hello-service
./mvnw compile jib:build -pl hello-service
# build name-service (with dependency on shared-library)
# you must use "package" for jib to correctly package "shared-library" with the
# "name-service" container
./mvnw package jib:build -pl name-service -amRun the Gradle build:
# build everything
./gradlew jib
# build just hello-service
./gradlew :hello-service:jib
# build name-service (with dependency on shared-library)
./gradlew :name-service:jibYou can also run ./maven-build.sh or ./gradle-build.sh as a shorthand.
Where are the containers
The output of the build should have the container image references highlighted in cyan. You can expect them to be at:
name-service:gcr.io/PROJECT_ID/name-service:0.1.0hello-service:gcr.io/PROJECT_ID/hello-service:0.1.0
How to run on Kubernetes
kubernetes.yaml defines the manifests for running the two microservices on Kubernetes. Make sure to open the file and change PROJECT_ID to your own Google Cloud Platform project.
Create a Kubernetes cluster:
gcloud container clusters create jibApply to your Kubernetes cluster:
kubectl apply -f kubernetes.yamlFind the EXTERNAL-IP of the hello-service.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
svc/hello-service LoadBalancer 10.19.243.223 35.237.89.148 80:30196/TCP 1mVisit the IP in your web browser and you should see:
Hello Jib Multimodule: A string from 'shared-library'Overview (`examples/spring-boot/README.md`)
Dockerize a Spring Boot application using Jib
This is an example of how to easily build a Docker image for a Spring Boot application with Jib.
Try it yourself
You can containerize the application with one of the following commands.
Maven:
./mvnw compile jib:build -Dimage=<your image, eg. gcr.io/my-project/spring-boot-jib>Gradle:
./gradlew jib --image=<your image, eg. gcr.io/my-project/spring-boot-jib>Deploying to Kubernetes using `kubectl`
Make sure you have kubectl installed and configured with a cluster.
IMAGE=<your image, eg. gcr.io/my-project/spring-boot-jib>
./mvnw compile jib:build -Dimage=$IMAGE
kubectl run spring-boot-jib --image=$IMAGE --port=8080 --restart=Never
# Wait until pod is running
kubectl port-forward spring-boot-jib 8080curl localhost:8080
> Greetings from Spring Boot and Jib!* If you are using Gradle, use ./gradlew jib --image=$IMAGE instead of the ./mvnw command
More information
Learn more about Jib.
Build and run on Google Cloud
Overview (`examples/vertx/README.md`)
Containerize a [Eclipse Vert.x](https://vertx.io/) application with Jib
This is an example of how to easily build a Docker image for a Eclipse Vert.x application with Jib.
./gradlew jibDockerBuild
docker run -d --rm -p 8080:8080 vertx-jib-exampleMore information
Learn more about Jib.
Learn more about Eclipse Vert.x.
Overview (`jib-core/examples/README.md`)
Jib Core examples
Please file an issue if you find any problems with the examples or would like to request other examples.
For examples on using Jib plugins, see examples.
[sbt](https://index.scala-lang.org/schmitch/sbt-jib) plugin
Jib Core is used in a third-party project, sbt-jib, that brings the benefits of Jib to sbt users.
Cram
See Cram for a simple example of a command-line utility that uses Jib Core to build Docker containers from file system contents.
Using Jib Core in Gradle builds
See build.gradle for examples using Jib Core to build and manipulate container images within a build.gradle script.
AutoJib - make your application self-containerize
See AutoJib for an example of a library that, when added as a dependency to a Java application, can make your application containerize itself.
Overview (`proposals/archives/README.md`)
Proposal Archives
This directory contains proposals that have already been implemented.
Overview (`jib-core/examples/build.gradle/README.md`)
Examples using Jib Core in Gradle builds
Jib Core is a containerization library for JVM languages, so it works well in Groovy as well. You can use Jib Core directly within a Gradle build.gradle to make tasks that build and manipulate container images.
For example, the following snippet is a simple example that creates a Gradle task that adds an environment variable to an existing image:
build.gradle:
/* Detailed source-code truncated for AI context efficiency. */Configure Gcp Credentials (`docs/configure-gcp-credentials.md`)
Configuring Credentials for [Google Container Registry (GCR)](https://cloud.google.com/container-registry/)
There are a few ways of supplying Jib with the credentials to push and pull images from your private GCR registry.
Using the Docker credential helper
The easiest way is to install the docker-credential-gcr.
Installation
If you have gcloud (Cloud SDK) installed, you can run:
gcloud components install docker-credential-gcrAlternatively, if you have go get installed, you can run:
go get -u github.com/GoogleCloudPlatform/docker-credential-gcrAlternatively, you can download docker-credential-gcr from its Github Releases.
Enable the Container Registry API
If you have not already done so, make sure you enable the Container Registry API for the Google Cloud Platform account you wish to use.
Log in
Log in to the account you with to use with:
docker-credential-gcr gcr-loginThis stores the credentials in docker-credential-gcr's private credential store.
Now, you can use Jib to pull and push from images in the form gcr.io/your-gcp-project/your-image-name.
Default Base Image (`docs/default_base_image.md`)
Default Base Images in Jib
Jib Build Plugins 3+
Starting from version 3.2, the default base image is the official eclipse-temurin image on Docker Hub. Note that Eclipse Temurin by Adoptium is the successor of AdoptOpenJDK. (For versions 3.0 and 3.1, the default is the official adoptopenjdk image.)
For WAR projects, the default is the official jetty image on Docker Hub.
Note that Jib's default choice for Temurin, AdoptOpenJDK, and Jetty does not imply any endorsement to them. In fact, for strong reproducibility (which also results in better performance and efficiency), we always recommend configuring jib.from.image (Gradle) or <from> (Maven) to pin to a specific base image using a digest (or at least a tag). And while doing so, you should do your due diligence to figure out which base image will work best for you.
Docker Hub Download Rate Limit
Docker Hub enforces download rate limit. Because Jib pulls base images from Docker Hub, you can occasionally lead to the following error:
> com.google.cloud.tools.jib.plugins.common.BuildStepsExecutionException: 429 Too Many Requests
GET https://registry-1.docker.io/v2/library/adoptopenjdk/manifests/sha256:9db4a57b38b6d928761ec9c5a250677d306095df0f6a6bdd8936628e033b9f1a
{
"errors": [
{
"code": "TOOMANYREQUESTS",
"message": "You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit"
}
]
}Note that, even after Jib fully cached a base image, Jib still connects to Docker Hub to check the image every time it runs (unless you pin to a specific base image using a SHA digest). This is to check if the cached base image is up-to-date.
Some options:
- Configure a registry mirror.
- Prevent Jib from accessing Docker Hub (after Jib cached a base image locally).
- Pin to a specific base image using a SHA digest (for example,
jib.from.image='eclipse-temurin:11-jre@sha256:...'). - Do offline building.
- Read a base from a local Docker daemon.
- Set up a local registry, store a base image, and read it from the local registry.
- Pin to a specific base image using a SHA digest (for example,
- Retry with increasing backoffs.
See this FAQ for more details about the options.
Migration from Pre-3.0
Prior to 3.0, Jib Maven and Gradle plugins built images based on Distroless Java when the user didn't make an explicit choice. The Jib team carefully assessed all the surrounding factors and ultimately decided to switch from Distroless for the best interest of the Jib users. That is, to meet one of the core missions of Jib to build a secure and optimized image.
If you are already setting a specific base image, there will be absolutely no difference when you upgrade to 3.0. It will continue to use the base image you specified. Even if you are not specifying a base image, most likely upgrading to 3.0 will keep working fine, because it's just about getting a JRE from a different image. (But if you are not setting a base image, as we explained in the previous section, we highly recommend configuring it.)
For some reason if you have to keep the exact same behavior when using 3.0, you can always specify the Distroless Java as a base image.
non-WAR projects
groovyjib { from.image = 'gcr.io/distroless/java:11' // or ":8" ... }xml<configuration> <from><image>gcr.io/distroless/java:11</image></from> </configuration>However, even when you decide to keep using Distroless, at least we strongly recommend
gcr.io/distroless/java-debian10:11, because, as of Apr 2021,gcr.io/distroless/java:{8,11}is based on Debian 9 that reached end-of-life. (Notegcr.io/distroless/java-debian10doesn't have:8.)WAR projects
gradlejib { from.image = 'gcr.io/distroless/java/jetty:java11' // or ":java8" container { entrypoint = 'INHERIT' appRoot = '/jetty/webapps/ROOT' } ... }xml<configuration> <from><image>gcr.io/distroless/java/jetty:java11</image></from> <container> <entrypoint>INHERIT</entrypoint> <appRoot>/jetty/webapps/ROOT</appRoot> </container> </configuration>
Jib CLI
For the JAR mode, Jib CLI versions prior to 0.8 have always used AdoptOpenJDK. Starting with 0.8, the tool uses eclipse-temurin. The WAR mode uses jetty.
Faq (`docs/faq.md`)
Frequently Asked Questions (FAQ)
If a question you have is not answered below, please submit an issue.
| ☑️ Jib User Survey |
|---|
| What do you like best about Jib? What needs to be improved? Please tell us by taking a one-minute survey. Your responses will help us understand Jib usage and allow us to serve our customers (you!) better. |
But, I'm not a Java developer.
My build process doesn't let me integrate with the Jib Maven or Gradle plugin
How do I run the image I built?
Where is bash?
What image format does Jib use?
Why is my image created 48+ years ago?
Where is the application in the container filesystem?
How are Jib applications layered?
Can I learn more about container images?
Which base image (JDK) does Jib use?
How-Tos
How do I set parameters for my image at runtime?
Can I define a custom entrypoint?
I want to containerize a JAR.
I need to RUN commands like apt-get.
Can I ADD a custom directory to the image?
I need to add files generated during the build process to a custom directory on the image.
Can I build to a local Docker daemon?
How do I enable debugging?
What would a Dockerfile for a Jib-built image look like?
How can I inspect the image Jib built?
I would like to run my application with a javaagent.
How can I tag my image with a timestamp?
How do I specify a platform in the manifest list (or OCI index) of a base image?
I want to exclude files from layers, have more fine-grained control over layers, change file ownership, etc.
Jib build plugins don't have the feature that I need.
I am hitting Docker Hub rate limits. How can I configure registry mirrors?
Where is the global Jib configuration file and how I can configure it?
Build Problems
How can I diagnose problems pulling or pushing from remote registries?
What should I do when the registry responds with Forbidden or DENIED?
What should I do when the registry responds with UNAUTHORIZED?
How do I configure a proxy?
How can I examine network traffic?
How do I view debug logs for Jib?
I am seeing Method Not Found or Class Not Found errors when building.
I am seeing Unsupported class file major version when building.
I am seeing NoClassDefFoundError: com/github/luben/zstd/ZstdOutputStream when building.
Launch Problems
I am seeing ImagePullBackoff on my pods.
Why won't my container start?
Jib CLI
How does the jar command support Standard JARs?
How does the jar command support Spring Boot JARs?
How does the war command work?
But, I'm not a Java developer.
Check out Jib CLI, a general-purpose command-line tool for building containers images from filesystem content.
Also see rules_docker for a similar existing container image build tool for the Bazel build system. The tool can build images for languages such as Python, NodeJS, Java, Scala, Groovy, C, Go, Rust, and D.
My build process doesn't let me integrate with the Jib Maven or Gradle plugin
The Jib CLI can be useful for users with complex build workflows that make it hard to integrate the Jib Maven or Gradle plugin. It is a standalone application that is powered by Jib Core and offers two commands:
Build: Builds images from the filesystem content.
Jar: Examines your JAR and builds an image with optimized layers or containerizes the JAR as-is.
Check out the Jib CLI section of the FAQ for more information.
How do I run the image I built?
If you built your image directly to the Docker daemon using jib:dockerBuild (Maven) or jibDockerBuild (Gradle), you simply need to use docker run .
If you built your image to a registry using jib:build (Maven) or jib (Gradle), you will need to pull the image using docker pull before using docker run.
To run your image on Kubernetes, you can use kubectl:
kubectl run jib-deployment --image=<image name>For more information, see steps 4-6 of the Kubernetes Engine deployment tutorial.
Where is bash?
By default, Jib Maven and Gradle plugin versions prior to 3.0 used distroless/java as the base image, which did not have a shell program (such as sh, bash, or dash). However, recent Jib tools use default base images that come with shell programs: Adoptium Eclipse Temurin (formerly AdoptOpenJDK) and Jetty for WAR projects.
Note that you can always set a different base image. Jib's default choice for Temurin or AdoptOpenJDK does not imply any endorsement to it; you should do your due diligence to choose the right image that works best for you. Also note that the default base image is unpinned (the tag can point to different images over time), so we recommend configuring a base image with a SHA digest for strong reproducibility.
Configuring a base image in Maven
xml<configuration> <from> <image>openjdk:11-jre-slim@sha256:...</image> </from> </configuration>Configuring a base image in Gradle
groovyjib.from.image = 'openjdk:11-jre-slim@sha256:...'Configuring a base image in Jib CLI
text$ jib jar --from openjdk:11-jre-slim@sha256:... --target ... app.jar
What image format does Jib use?
Jib currently builds into the Docker V2.2 image format or OCI image format.
Maven
See Extended Usage for the <container><format> configuration.
Gradle
See Extended Usage for the container.format configuration.
Why is my image created 48+ years ago?
For reproducibility purposes, Jib sets the creation time of the container images to the Unix epoch (00:00:00, January 1st, 1970 in UTC). If you would like to use a different timestamp, set the jib.container.creationTime / <container><creationTime> parameter to an ISO 8601 date-time. You may also use the value USE_CURRENT_TIMESTAMP to set the creation time to the actual build time, but this sacrifices reproducibility since the timestamp will change with every build.
Setting creationTime parameter (click to expand)
Maven
<configuration>
<container>
<creationTime>2019-07-15T10:15:30+09:00</creationTime>
</container>
</configuration>Gradle
jib.container.creationTime = '2019-07-15T10:15:30+09:00'Note that the modification time of the files in the built image put by Jib will still be 1 second past the epoch. The file modification time can be configured using <container><filesModificationTime> (Maven) or jib.container.filesModificationTime (Gradle).
Please tell me more about reproducibility!
Reproducible means that given the same inputs, a build should produce the same outputs. Container images are uniquely identified by a digest (or a hash) of the image contents and image metadata. Tools and infrastructure such the Docker daemon, Docker Hub, registries, Kubernetes, etc) treat images with different digests as being different.
To ensure that a Jib build is reproducible — that the rebuilt container image has the same digest — Jib adds files and directories in a consistent order, and sets consistent creation- and modification-times and permissions for all files and directories. Jib also ensures that the image metadata is recorded in a consistent order, and that the container image has a consistent creation time. To ensure consistent times, files and directories are recorded as having a creation and modification time of 1 second past the Unix Epoch (1970-01-01 00:00:01.000 UTC), and the container image is recorded as being created on the Unix Epoch. Setting container.creationTime to USE_CURRENT_TIMESTAMP and then rebuilding an image will produce a different timestamp for the image creation time, and so the container images will have different digests and appear to be different.
For more details see reproducible-builds.org.
Where is the application in the container filesystem?
Jib packages your Java application into the following paths on the image:
/app/libs/contains all the dependency artifacts/app/resources/contains all the resource files/app/classes/contains all the classes files- the contents of the extra directory (default
src/main/jib) are placed relative to the container's root directory (/)
How are Jib applications layered?
Jib makes use of layering to allow for fast rebuilds - it will only rebuild the layers containing files that changed since the previous build and will reuse cached layers containing files that didn't change. Jib organizes files in a way that groups frequently changing files separately from large, rarely changing files. For example, SNAPSHOT dependencies are placed in a separate layer from other dependencies, so that a frequently changing SNAPSHOT will not force the entire dependency layer to rebuild itself.
Jib applications are split into the following layers:
- All other dependencies
- Snapshot dependencies
- Project dependencies
- Resources
- Classes
- Each extra directory (
jib.extraDirectoriesin Gradle,<extraDirectories>in Maven) builds to its own layer
Which base image (JDK) does Jib use?
eclipse-temurin by Adoptium (formerly adoptopenjdk) and jetty (for WAR). See Default Base Images in Jib for details.
Can I learn more about container images?
If you'd like to learn more about container images, @coollog has a guide: Build Containers the Hard Way, which takes a deep dive into everything involved in getting your code into a container and onto a container registry.
Configuring Jib
How do I set parameters for my image at runtime?
JVM Flags
For the default base image, you can use the JAVA_TOOL_OPTIONS environment variable (note that other JRE images may require using other environment variables):
Using Docker: docker run -e "JAVA_TOOL_OPTIONS=<JVM flags>"
Using Kubernetes:
apiVersion: v1
kind: Pod
spec:
containers:
- name: <name>
image: <image name>
env:
- name: JAVA_TOOL_OPTIONS
value: <JVM flags>Note that many JVMs may only support a max length of 1024 characters for the JAVA_TOOL_OPTIONS environment variable, and anything longer than this may be cut off by the JVM.
For Java 9+, often you may want to use JDK_JAVA_OPTIONS instead of JAVA_TOOL_OPTIONS.
Other Environment Variables
Using Docker: docker run -e "NAME=VALUE"
Using Kubernetes:
apiVersion: v1
kind: Pod
spec:
containers:
- name: <name>
image: <image name>
env:
- name: NAME
value: VALUEArguments to Main
Using Docker: docker run <arg1> <arg2> <arg3>
Using Kubernetes:
apiVersion: v1
kind: Pod
spec:
containers:
- name: <name>
image: <image name>
args:
- <arg1>
- <arg2>
- <arg3>For more information, see the JAVA_TOOL_OPTIONS environment variable, the docker run -e reference, and defining environment variables for a container in Kubernetes.
Can I define a custom entrypoint at runtime?
Normally, the plugin sets a default entrypoint for java applications, or lets you configure a custom entrypoint using the container.entrypoint configuration parameter. You can also override the default/configured entrypoint by defining a custom entrypoint when running the container. See docker run --entrypoint reference for running the image with Docker and overriding the entrypoint command, or see Define a Command and Arguments for a Container for running the image in a Kubernetes Pod and overriding the entrypoint command.
I want to containerize a JAR.
The intention of Jib is to add individual class files, resources, and dependency JARs into the container instead of putting a JAR. This lets Jib choose an opinionated, optimal layout for the application on the container image, which also allows it to skip the extra JAR-packaging step.
However, you can set <containerizingMode>packaged (Maven) or jib.containerizingMode = 'packaged' (Gradle) to containerize a JAR, but note that your application will always be run via java -cp ... your.MainClass (even if it is an executable JAR). Some disadvantages of setting containerizingMode='packaged':
- You need to run the JAR-packaging step (
mvn packagein Maven or thejartask in Gradle). - Reduced granularity in building and caching: if any of your Java source files or resource files are updated, not only the JAR has to be rebuilt, but the entire layer containing the JAR in the image has to be recreated and pushed to the destination.
- If it is a fat or shaded JAR embedding all dependency JARs, you are duplicating the dependency JARs in the image. Worse, it results in far more reduced granularity in building and caching, as dependency JARs can be huge and all of them need to be pushed repeatedly even if they do not change.
Note that for runnable JARs/WARs, currently Jib does not natively support creating an image that runs a JAR (or WAR) through java -jar runnable.jar (although it is not impossible to configure Jib to do so at the expense of more complex project setup.)
I need to RUN commands like `apt-get`.
Running commands like apt-get slows down the container build process. We do not recommend or support running commands as part of the build.
However, if you need to run commands, you can build a custom image and configure Jib to use it as the base image.
Base image configuration examples (click to expand)
Maven
In jib-maven-plugin, you can then use this custom base image by adding the following configuration:
<configuration>
<from>
<image>custom-base-image</image>
</from>
</configuration>Gradle
In jib-gradle-plugin, you can then use this custom base image by adding the following configuration:
jib.from.image = 'custom-base-image'Can I ADD a custom directory to the image?
Yes, using the extra directories feature. See the Maven and Gradle docs for examples.
I need to add files generated during the build process to a custom directory on the image.
If the current extra directories design doesn't meet your needs (e.g. you need to set up the extra files directory with files generated during the build process), you can use additional goals/tasks to create the extra directory as part of your build.
File copying examples (click to expand)
Maven
In Maven, you can use the maven-resources-plugin to copy files to your extra directory. For example, if you generate files in target/generated/files and want to add them to /my/files on the container, you can add the following to your pom.xml:
<plugins>
...
<plugin>
<artifact>jib-maven-plugin</artifact>
...
<configuration>
<extraDirectories>
<paths>
<path>${project.basedir}/target/extra-directory/</path>
</paths>
</extraDirectories>
</configuration>
</plugin>
...
<plugin>
<artifact>maven-resources-plugin</artifact>
<version>3.2.0</version>
<configuration>
<outputDirectory>${project.basedir}/target/extra-directory/my/files</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/target/generated/files</directory>
</resource>
</resources>
</configuration>
</plugin>
...
</plugins>The copy-resources goal will run automatically before compile, so if you are copying files from your build output to the extra directory, you will need to either set the life-cycle phase to post-compile or later, or run the goal manually:
mvn compile resources:copy-resources jib:buildGradle
The same can be accomplished in Gradle by using a Copy task. In your build.gradle:
jib.extraDirectories.paths = ['build/extra-directory']
task setupExtraDir(type: Copy) {
from file('build/generated/files')
into file('build/extra-directory/my/files')
}
tasks.jib.dependsOn setupExtraDirThe files will be copied to your extra directory when you run the jib task.
Can I build to a local Docker daemon?
There are several ways of doing this:
- Use
jib:dockerBuildfor Maven orjibDockerBuildfor Gradle to build directly to your local Docker daemon. - Use
jib:buildTarfor Maven orjibBuildTarfor Gradle to build the image to a tarball, then usedocker load --inputto load the image into Docker (the tarball built with these commands will be located intarget/jib-image.tarfor Maven andbuild/jib-image.tarfor Gradle by default). docker pullthe image built with Jib to have it available in your local Docker daemon.- Alternatively, instead of using a Docker daemon, you can run a local container registry, such as Docker registry or other repository managers, and point Jib to push to the local registry.
How do I enable debugging?
Use the JAVA_TOOL_OPTIONS to pass along debugging configuration arguments. For example, to have the remote VM accept local debug connections on port 5005, but not suspend:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=localhost:5005Then connect your debugger to port 5005 on your local host. You can port-forward the container port to a localhost port for easy access.
Using Docker: docker run -p 5005:5005
Using Kubernetes: kubectl port-forward 5005:5005
Beware: in Java 8 and earlier, specifying only a port meant that the JDWP socket was open to all incoming connections which is insecure. It is recommended to limit the debug port to localhost.
I would like to run my application with a javaagent.
You can run your container with a javaagent by placing it somewhere in the src/main/jib/myfolder directory to add it to the container's filesystem, then pointing to it using Jib's container.jvmFlags configuration.
Maven
<configuration>
<container>
<jvmFlags>
<jvmFlag>-javaagent:/myfolder/agent.jar</jvmFlag>
</jvmFlags>
</container>
</configuration>Gradle
jib.container.jvmFlags = ['-javaagent:/myfolder/agent.jar']See also:
- Can I ADD a custom directory to the image?
- Javaagent sample: dynamically downloads a javaagent during build
- (Gradle) javaagent-gradle-plugin: third-party Jib extension
How can I tag my image with a timestamp?
Maven
To tag the image with a simple timestamp, add the following to your pom.xml:
<properties>
<maven.build.timestamp.format>yyyyMMdd-HHmmssSSS</maven.build.timestamp.format>
</properties>Then in the jib-maven-plugin configuration, set the tag to:
<configuration>
<to>
<image>my-image-name:${maven.build.timestamp}</image>
</to>
</configuration>You can then use the same timestamp to reference the image in other plugins.
Gradle
To tag the image with a timestamp, simply set the timestamp as the tag for to.image in your jib configuration. For example:
jib.to.image = 'gcr.io/my-gcp-project/my-app:' + System.nanoTime()What would a Dockerfile for a Jib-built image look like?
A Dockerfile that performs a Jib-like build is shown below:
# Jib uses Adoptium Eclipse Temurin (formerly AdoptOpenJDK).
FROM eclipse-temurin:11-jre
# Multiple copy statements are used to break the app into layers,
# allowing for faster rebuilds after small changes
COPY dependencyJars /app/libs
COPY snapshotDependencyJars /app/libs
COPY projectDependencyJars /app/libs
COPY resources /app/resources
COPY classFiles /app/classes
# Jib's extra directory ("src/main/jib" by default) is used to add extra, non-classpath files
COPY src/main/jib /
# Jib's default entrypoint when container.entrypoint is not set
ENTRYPOINT ["java", jib.container.jvmFlags, "-cp", "/app/resources:/app/classes:/app/libs/*", jib.container.mainClass]
CMD [jib.container.args]When unset, Jib will infer the value for jib.container.mainClass.
Some plugins, such as the Docker Prepare Gradle Plugin, will even automatically generate a Docker context for your project, including a Dockerfile.
How can I inspect the image Jib built?
To inspect the image that is produced from the build using Docker, you can use commands such as docker inspect your/image:tag to view the image configuration, or you can also download the image using docker save to manually inspect the container image. Other tools, such as dive, provide nicer UI to inspect the image.
How do I specify a platform in the manifest list (or OCI index) of a base image?
Newer Jib versions added an incubating feature that provides support for selecting base images with the desired platforms from a manifest list. For example,
<from>
<image>... image reference to a manifest list ...</image>
<platforms>
<platform>
<architecture>amd64</architecture>
<os>linux</os>
</platform>
<platform>
<architecture>arm64</architecture>
<os>linux</os>
</platform>
</platforms>
</from>jib.from {
image = '... image reference to a manifest list ...'
platforms {
platform {
architecture = 'amd64'
os = 'linux'
}
platform {
architecture = 'arm64'
os = 'linux'
}
}
}The default when not specified is a single "amd64/linux" platform, whose behavior is backward-compatible.
When multiple platforms are specified, Jib creates and pushes a manifest list (also known as a fat manifest) after building and pushing all the images for the specified platforms.
As an incubating feature, there are certain limitations:
- OCI image indices are not supported (as opposed to Docker manifest lists).
- Only
architectureandosare supported. If the base image manifest list contains multiple images with the given architecture and os, the first image will be selected. - Does not support using a local Docker daemon or tarball image for a base image.
- Does not support pushing to a Docker daemon (
jib:dockerBuild/jibDockerBuild) or building a local tarball (jib:buildTar/jibBuildTar).
Make sure to specify a manifest list in <from> (whether by a tag name or a digest (@sha256:...)). For troubleshooting, you may want to check what platforms the manifest list contains. To view a manifest list, enable experimental docker CLI features and then run the manifest inspect command.
$ docker manifest inspect openjdk:8
{
...
// This confirms that openjdk:8 points to a manifest list.
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
// This entry in the list points to the manifest for the ARM64/Linux manifest.
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
...
"digest": "sha256:1fbd49e3fc5e53154fa93cad15f211112d899a6b0c5dc1e8661d6eb6c18b30a6",
"platform": {
"architecture": "arm64",
"os": "linux",
"variant": "v8"
}
}
]
}I want to exclude files from layers, have more fine-grained control over layers, change file ownership, etc.
See "Jib build plugins don't have the feature that I need".
Jib build plugins don't have the feature that I need.
The Jib build plugins have an extension framework that enables anyone to easily extend Jib's behavior to their needs. We maintain select first-party plugins for popular use cases like fine-grained layer control and Quarkus support, but anyone can write and publish an extension. Check out the jib-extensions repository for more information.
I am hitting Docker Hub rate limits. How can I configure registry mirrors?
See the Maven, Gradle or Jib CLI docs. Note that the example in the docs uses Google's Docker Hub mirror on mirror.gcr.io.
Starting from Jib build plugins 3.0, Jib by default uses base images on Docker Hub, so you may start to encounter the rate limits if you are not explicitly setting a base image.
Some other alternatives to get around the rate limits:
- Prevent Jib from accessing Docker Hub (after Jib cached a base image locally).
- Pin to a specific base image using a SHA digest. For example,
jib.from.image='eclipse-temurin:11-jre@sha256:...'. If you are not setting a base image with a SHA digest (which is the case if you don't setjib.from.imageat all), then every time Jib runs, it reaches out to the registry to check if the base image is up-to-date. On the other hand, if you pin to a specific image with a digest, then the image is immutable. Therefore, if Jib has cached the image once (by running Jib online once to fully cache the image), Jib will not reach out to the Docker Hub. See this Stack Overflow answer for more details. - (Maven/Gradle plugins only) Do offline building. Pass
--offlineto Maven or Gradle. Before that, you need to run Jib online once to cache the image. However,--offlinemeans you cannot push to a remote registry. See this Stack Overflow answer for more details. - Retrieve a base image from a local Docker daemon. Store an image to your local Docker daemon, and set, say,
jib.from.image='docker://eclipse-temurin:11-jre'. It can be slow for an initial build where Jib has to cache the image in Jib's format. For performance reasons, we usually recommend using an image on a registry. - Set up a local registry, store a base image, and read it from the local registry. Setting up a local registry is as simple as running
docker run -d -p5000:5000 registry:2, but nevertheless, the whole process is a bit involved.
- Pin to a specific base image using a SHA digest. For example,
- Retry with increasing backoffs. For example, using the
retrytool.
Where is the global Jib configuration file and how I can configure it?
See the Maven, Gradle or Jib CLI docs.
Build Problems
How can I diagnose problems pulling or pushing from remote registries?
There are a few reasons why Jib may be unable to connect to a remote registry, including:
- Registry reports FORBIDDEN. See What should I do when the registry responds with Forbidden or DENIED?
- Registry reports UNAUTHORIZED. See What should I do when the registry responds with UNAUTHORIZED?
- Access requires a proxy. See How do I configure a proxy? for details.
- The registry does not support HTTPS. We do not pass authentication details on non-HTTPS connections, though this can be overridden with the
sendCredentialsOverHttpsystem property, but it is not recommend (version 0.9.9). - The registry's SSL certificates have expired or are not trusted. We have a separate document on handling registries that use self-signed certificates, which may also apply if the SSL certificate is signed by an untrusted Certificate Authority. Jib supports an
allowInsecureRegistriesflag to ignore SSL certificate validation, but it is not recommend (version 0.9.9). - The registry does not support the Docker Image Format V2 Schema 2 (sometimes referred to as v2-2). This problem is usually shown by failures wth
INVALID_MANIFESTerrors. Some registries can be configured to support V2-2 such as Artifactory and OpenShift. Other registries, such as Quay.io/Quay Enterprise, are in the process of adding support.
What should I do when the registry responds with Forbidden or DENIED?
If the registry returns 403 Forbidden or "code":"DENIED", it often means Jib successfully authenticated using your credentials but the credentials do not have permissions to pull or push images. Make sure your account/role has the permissions to do the operation.
Depending on registry implementations, it is also possible that the registry actually meant you are not authenticated. See What should I do when the registry responds with UNAUTHORIZED? to ensure you have set up credentials correctly.
What should I do when the registry responds with UNAUTHORIZED?
If the registry returns 401 Unauthorized or "code":"UNAUTHORIZED", it is often due to credential misconfiguration. Examples:
You did not configure auth information in the default places where Jib searches. (See also Authentication Methods).
Docker credential file (as generated by
docker loginorpodman login) at$XDG_RUNTIME_DIR/containers/auth.json,$XDG_CONFIG_HOME/containers/auth.jsonor$HOME/.config/containers/auth.json$DOCKER_CONFIG/config.json$HOME/.docker/config.json
This is one of the configuration files for the
dockerorpodmancommand line tool. See configuration files document, credential store and credential helper sections, and this for how to configure auth. For example, you can dodocker loginto save auth inconfig.json, but it is often recommended to configure a credential helper (also configurable inconfig.json).If Jib was able to retrieve auth information from a Docker credential file, you should see a log message similar to
Using credentials from Docker config (/home/myuser/.docker/config.json)where you can verify which credential file was picked up by Jib.Jib configurations
- Configuring credential helpers:
<from/to><credHelper>(Maven) /from/to.credHelper(Gradle) - Specific credentials (not recommend):
<from/to><auth>/or insettings.xml(Maven) /from/to.auth.username/password(Gradle) - These parameters can also be set through properties: Maven / Gradle
- Configuring credential helpers:
For Google Cloud Registry (GCR), the Container Registry API is not yet enabled for your project.
- You enable the API from Cloud Console or with the following Cloud SDK command:
gcloud services enable containerregistry.googleapis.com
- You enable the API from Cloud Console or with the following Cloud SDK command:
$HOME/.docker/config.jsonmay also contain short-lived authorizations in theauthsblock that may have expired. In the case of Google Container Registry, if you had previously usedgcloud dockerto configure these authorizations, you should remove these stale authorizations by editing yourconfig.jsonand deleting lines fromauthsassociated withgcr.io(for example:"https://asia.gcr.io"). You can then rungcloud auth configure-dockerto correctly configure thecredHelpersblock for more robust interactions with gcr.Different auth configurations exist in multiple places, and Jib is not picking up the auth information you are working on.
You configured a credential helper, but the helper is not on
$PATH. This is especially common when running Jib inside IDE where the IDE binary is launched directly from an OS menu and does not have access to your shell's environment.Configured credentials have access to the base image repository but not to the target image repository (or vice versa).
Typos in username, password, image names, repository names, or registry names. This is a very common error.
Image names do not conform to the structure or policy that a registry requires. For example, Docker Hub returns 401 Unauthorized when trying to use a multi-level repository name.
Incorrect port number in image references (
registry.hostname:/...).You are using a private registry without HTTPS. See How can I diagnose problems pulling or pushing from remote registries?.
Note, if Jib was able to retrieve credentials, you should see a log message like these:
Using credentials from Docker config (/home/user/.docker/config.json) for localhost:5000/javaUsing credential helper docker-credential-gcr for gcr.io/project/repoUsing credentials from Maven settings file for gcr.io/project/repoUsing credentials from <from><auth> for gcr.io/project/repoUsing credentials from to.auth for gcr.io/project/repoIf you encounter issues interacting with a registry other than UNAUTHORIZED, check "How can I diagnose problems pulling or pushing from remote registries?".
How do I configure a proxy?
Jib currently requires configuring your build tool to use the appropriate Java networking properties (https.proxyHost, https.proxyPort, https.proxyUser, https.proxyPassword).
How can I examine network traffic?
It can be useful to examine network traffic to diagnose connectivity issues. Jib uses the Google HTTP client library to interact with registries which logs HTTP requests using the JVM-provided java.util.logging facilities. It is very helpful to serialize Jib's actions using the jib.serialize property.
To see the HTTP traffic, create a logging.properties file with the following:
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=ALL
# CONFIG hides authentication data
# ALL includes authentication data
com.google.api.client.http.level=CONFIGAnd then launch your build tool as follows:
mvn --batch-mode -Djava.util.logging.config.file=path/to/logging.properties -Djib.serialize=true ...or
gradle --no-daemon --console=plain --info -Djava.util.logging.config.file=path/to/logging.properties -Djib.serialize=true ...Note: Jib Gradle plugins prior to version 2.2.0 have an issue generating HTTP logs (#2356).
You may want to enable the debug logs too (-X for Maven, or --debug --stacktrace for Gradle).
When configured correctly, you should see logs like this:
Mar 31, 2020 9:55:52 AM com.google.api.client.http.HttpResponse <init>
CONFIG: -------------- RESPONSE --------------
HTTP/1.1 202 Accepted
Content-Length: 0
Docker-Distribution-Api-Version: registry/2.0
Docker-Upload-Uuid: 6292f0d7-93cb-4a8e-8336-78a1bf7febd2
Location: https://registry-1.docker.io/v2/...
Range: 0-657292
Date: Tue, 31 Mar 2020 13:55:52 GMT
Strict-Transport-Security: max-age=31536000
Mar 31, 2020 9:55:52 AM com.google.api.client.http.HttpRequest execute
CONFIG: -------------- REQUEST --------------
PUT https://registry-1.docker.io/v2/...
Accept:
Accept-Encoding: gzip
Authorization: <Not Logged>
User-Agent: jib 2.1.1-SNAPSHOT jib-maven-plugin Google-HTTP-Java-Client/1.34.0 (gzip)How do I view debug logs for Jib?
Maven: use mvn -X -Djib.serialize=true to enable more detailed logging and serialize Jib's actions.
Gradle: use gradle --debug -Djib.serialize=true to enable more detailed logging and serialize Jib's actions.
I am seeing `Method Not Found` or `Class Not Found` errors when building.
Sometimes when upgrading your Gradle build plugin versions, you may experience errors due to mismatching versions of dependencies pulled in (for example: issues/2183). This can be due to the buildscript classpath loading behavior described on gradle forums.
This commonly appears in multi module Gradle projects. A solution to this problem is to define all of your plugins in the base project and apply them selectively in your subprojects as needed. This should help alleviate the problem of the buildscript classpath using older versions of a library.
build.gradle (root)
plugins {
id 'com.google.cloud.tools.jib' version 'x.y.z' apply false
}build.gradle (sub-project)
plugins {
id 'com.google.cloud.tools.jib'
}I am seeing `Unsupported class file major version` when building.
When you're using latest Java versions to write an app (or using an old version of Jib), you may see the error coming from Jib when building an image (not when compiling your code):
Failed to execute goal com.google.cloud.tools:jib-maven-plugin:3.2.0:dockerBuild (default-cli) on project demo: Execution default-cli of goal com.google.cloud.tools:jib-maven-plugin:3.2.0:dockerBuild failed: Unsupported class file major version 61Jib uses the ASM library to examine compiled Java bytecode to automatically infer a main class (in other words, the class that defines public static void main() to start your app). In this way, if you have only one such class, Jib can automatically infer and use that class to set an image entrypoint (basically, a command to start your app). When new Java versions come out, often the ASM library version used in Jib doesn't support the new bytecode format. If this is the case, check if you are using the latest Jib. If you still get the error with the latest Jib, file a bug to have the Jib team upgrade the ASM library.
Workaround: to prevent Jib from doing auto-inference, you can manually set your desired main class via <container><mainClass> (for example, <container><mainClass>com.example.your.Main</mainClass>). As with other Jib parameters, it can be set through system/Maven properties or on the command-line (for example, -Dcontainer.mainClass=...).
Note that although the ASM library is the common cause of this error coming from Jib, it may be due to other reasons. Always check the full stack (-e or -X for Maven and --stacktrace for Gradle) to see where the error is coming from.
I am seeing `NoClassDefFoundError: com/github/luben/zstd/ZstdOutputStream` when building.
Jib supports base image layers with media-type application/vnd.oci.image.layer.v1.tar+zstd, i.e. compressed with zstd algorithm instead of gzip.
However, the dependency to zstd is optional, so pulling such layers will result in:
java.lang.NoClassDefFoundError: com/github/luben/zstd/ZstdOutputStream
at org.apache.commons.compress.compressors.zstandard.ZstdCompressorOutputStream.<init>This can be solved by adding a dependency to artifact com.github.luben:zstd-jni:1.5.2-3 to the plugin.
Launch problems
I am seeing `ImagePullBackoff` on my pods (in [minikube](https://github.com/kubernetes/minikube)).
When you use your private image built with Jib in a Kubernetes cluster, the cluster needs to be configured with credentials to pull the image. This involves 1) creating a Secret, and 2) using the Secret as imagePullSecrets.
kubectl create secret docker-registry registry-json-key \
--docker-server=<registry> \
--docker-username=<username> \
--docker-password=<password> \
--docker-email=<any valid email address>
kubectl patch serviceaccount default \
-p '{"imagePullSecrets":[{"name":"registry-json-key"}]}'For example, if you are using GCR, the commands would look like (see Advanced Authentication Methods):
kubectl create secret docker-registry gcr-json-key \
--docker-server=https://gcr.io \
--docker-username=_json_key \
--docker-password="$(cat keyfile.json)" \
[email protected]
kubectl patch serviceaccount default \
-p '{"imagePullSecrets":[{"name":"gcr-json-key"}]}'See more at Using Google Container Registry (GCR) with Minikube.
Why won't my container start?
There are some common reasons why containers fail on launch.
My shell script won't run.
Jib Maven and Gradle plugins prior to 3.0 used Distroless Java as the default base image, which does not have a shell. See Where is bash? for more details.
The container fails with `exec` errors.
A Jib user reported an error launching their container:
standard_init_linux.go:211 exec user process caused "no such file or directory"On examining the container structure with Dive, the user discovered that the contents of the /lib directory had disappeared.
The user had used Jib's ability to install extra files into the image (Maven, Gradle) to install a library file by placing it in src/main/jib/lib/libfoo.so. This would normally cause the libfoo.so to be installed in the image as /lib/libfoo.so. But /lib and /lib64 in the user's base image were symbolic links. Jib does not follow such symbolic links when creating the image. And at container initialization time, Docker treats these symlinks as a file, and thus the symbolic link was replaced with /lib as a new directory. As a result, none of the system shared libraries were resolved and dynamically-linked programs failed.
Solution: The user installed the file in a different location.
Jib CLI
How does the `jar` command support Standard JARs?
The Jib CLI supports both thin JARs (where dependencies are specified in the JAR's manifest) and fat JARs.
The current limitation of using a fat JAR is that the embedded dependencies will not be placed into the designated dependencies layers. They will instead be placed into the classes or resources layer. Therefore, for efficiency, we recommend against containerizing fat JARs (Spring Boot fat JARs are an exception) if you can prepare thin JARs. We hope to have better support for fat JARs in the future.
A standard JAR can be containerized by the jar command in two modes, exploded or packaged.
Exploded Mode (Recommended)
Achieved by calling jib jar --target ${TARGET_REGISTRY} ${JAR_NAME}.jar
The default mode for containerizing a JAR. It will open up the JAR and optimally place files into the following layers:
- Other Dependencies Layer
- Snapshot-Dependencies Layer
- Resources Layer
- Classes Layer
Entrypoint : java -cp /app/dependencies/:/app/explodedJar/ ${MAIN_CLASS}
Packaged Mode
Achieved by calling jib jar --target ${TARGET_REGISTRY} ${JAR_NAME}.jar --mode packaged.
It will result in the following layers on the container:
- Dependencies Layer
- Jar Layer
Entrypoint : java -jar ${JAR_NAME}.jar
How does the `jar` command support Spring Boot JARs?
The jar command currently supports containerization of Spring Boot fat JARs.
A Spring-Boot fat JAR can be containerized in two modes, exploded or packaged.
Exploded Mode (Recommended)
Achieved by calling jib jar --target ${TARGET_REGISTRY} ${JAR_NAME}.jar
The default mode for containerizing a JAR. It will respect layers.idx in the JAR (if present) or create optimized layers in the following format:
- Other Dependencies Layer
- Spring-Boot-Loader Layer
- Snapshot-Dependencies Layer
- Resources Layer
- Classes Layer
Entrypoint : java -cp /app org.springframework.boot.loader.JarLauncher
Packaged Mode
Achieved by calling jib jar --target ${TARGET_REGISTRY} ${JAR_NAME}.jar --mode packaged
It will containerize the JAR as is. However, note that we highly recommend against using packaged mode for containerizing Spring Boot fat JARs.
Entrypoint: java -jar ${JAR_NAME}.jar
How does the `war` command work?
The war command currently supports containerization of standard WARs. It uses the official jetty on Docker Hub as the default base image and explodes out the WAR into /var/lib/jetty/webapps/ROOT on the container. It creates the following layers:
- Other Dependencies Layer
- Snapshot-Dependencies Layer
- Resources Layer
- Classes Layer
The default entrypoint when using a jetty base image will be java -jar /usr/local/jetty/start.jar --module=ee10-deploy unless you choose to specify a custom one.
You can use a different Servlet engine base image with the help of the --from option and customize --app-root, --entrypoint and --program-args. If you don't set the entrypoint or program-arguments, Jib will inherit them from the base image. However, setting the --app-root is required if you use a non-jetty base image. Here is how the war command may look if you're using a Tomcat image:
$ jib war --target=<image-reference> myapp.war --from=tomcat:8.5-jre8-alpine --app-root=/usr/local/tomcat/webapps/ROOTGoogle Cloud Build (`docs/google-cloud-build.md`)
Jib on Google Cloud Build
You can use Jib on Google Cloud Build in a simple step:
steps:
- name: 'gcr.io/cloud-builders/javac:8'
entrypoint: './gradlew'
args: ['--console=plain', '--no-daemon', ':server:jib', '-Djib.to.image=gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA']Any Java container can be used for building, not only the gcr.io/cloud-builders/javac:* (from gcr.io/cloud-builders/javac), for example with Temurin's:
steps:
- name: 'docker.io/library/eclipse-temurin:25'
entrypoint: './gradlew'
args: ['--console=plain', '--no-daemon', ':server:jib', '-Djib.to.image=gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA']To use Google "Distroless" Container Images to build with Jib on Google Cloud Build, and avoid running into Step #1: standard_init_linux.go:228: exec user process caused: no such file or directory errors (because Google's distroless containers are based on busybox), you have to do something like this:
steps:
- name: 'gcr.io/distroless/java17-debian11:debug'
entrypoint: '/busybox/sh'
args:
- -c
- |
ln -s /busybox/sh /bin/sh
ln -s /busybox/env /usr/bin/env
/workspace/gradlew --console=plain --no-daemon --gradle-user-home=/home/.gradle :server:jib -Djib.to.image=gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHAPrivacy (`docs/privacy.md`)
The privacy of our users is very important to us.
Your use of this software is subject to the Google Privacy Policy.
Update check
Many Jib users are unaware of new releases. To encourage users to stay up-to-date, the Jib Maven and Jib Gradle plugins (2.0.0 and later) and Jib CLI (0.6.0 and later) will
periodically check to see if there is a new version of Jib is available. This check fetches a simple text
file hosted in Google Cloud Storage. As a side effect this request is logged, which includes the request path,
source IP address, and the user-agent string. The user-agent is set by Jib and includes the Jib tool name
and version.
How to disable update checks
- set the
jib.disableUpdateCheckssystem property totrue - set
disableUpdateChecktotruein Jib's global config. The global config is in the following locations by default:- Linux:
$XDG_CONFIG_HOME/google-cloud-tools-java/jib/config.json(if$XDG_CONFIG_HOMEis defined), else$HOME/.config/google-cloud-tools-java/jib/config.json - Mac:
$XDG_CONFIG_HOME/Google/Jib/config.json(if$XDG_CONFIG_HOMEis defined), else$HOME/Library/Preferences/Google/Jib/config.json - Windows:
$XDG_CONFIG_HOME\Google\Jib\Config\config.json(if$XDG_CONFIG_HOMEis defined), else%LOCALAPPDATA%\Google\Jib\Config\config.json
- Linux:
Self Sign Cert (`docs/self_sign_cert.md`)
Accessing a private docker registry with self-signed certificate
Jib relies on the Java Runtime Environment's list of approved Certification Authority Certificates for validating SSL certificates, and will hence fail when connecting to a docker registry that uses a self-signed https certificate. This document describes two approaches for handling registries with self-signed certificates. Both approaches configure the JRE's list of approved CA Certificates.
These CA Certificates for JRE are managed through a type of a keystore file called truststore. An easy way to manipulate truststores is using the KeyStore Explorer, an open source GUI replacement for the Java command-line keytool and jarsigner utilities. Download and install KeyStore Explorer from the official website.
Step 1. Identify Java runtime used by build tool
We must first identify the location of your build-tool's JRE's list of CA Certificates.
Maven
Run mvn --version and take note of the Java runtime location:
$ mvn --version
Apache Maven 3.5.4 (1edded0938998edf8bf061f1ceb3cfdeccf443fe; 2018-06-18T06:33:14+12:00)
Maven home: /usr/local/Cellar/maven/3.5.4/libexec
Java version: 1.8.0_172, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre
Default locale: en_NZ, platform encoding: UTF-8
OS name: "mac os x", version: "10.13.6", arch: "x86_64", family: "mac"In this example the Java runtime location is /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre.
Gradle
Create an init script with the following:
println org.gradle.internal.jvm.Jvm.current().getJavaHome()And run gradle -I /path/to/script to output the executing JRE location.
$ gradle -I /tmp/printjrelocation
/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home
> Task :help
Welcome to Gradle 4.6.
[...]JRE vs JDK Distributions
The Maven and Gradle examples above report two different directories, where the Maven example reported a .../jre subdirectory. Java Development Kits usually include a standalone Java Runtime Environment inside the jre/ directory. If present, use the jre/ directory as the runtime location.
2. Load JRE CA Certificates
Having identified your Java runtime location:
- Launch
KeyStore Explorer - Select Open an existing KeyStore
- Navigate to the Java runtime location identified previously, and then continue to open the file at
jre/lib/security/cacerts. If there is nojre/directory then this is a JRE distribution and should navigate and instead open the file atlib/security/cacerts.- In the example above, this file would be
/Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/security/cacerts.
- In the example above, this file would be
- You will likely be prompted for a password. The default password for the
cacertsfile ischangeit.
3. Import Self-Signed Certificate
If you have the self-signed certificate in a file then:
- Select Tools > Import Trusted Certificate
- Select the certifcate file on disk
- Give it a name, or use suggested name, and click OK
- Click OK on the success window
Otherwise use Examine > Examine SSL to connect to your service and click the Import button to import its SSL certificate. Then click OK.
4. Save the CA Certificates
Now we save the updated truststore. We can either save to a new truststore and configure our build's JVM to use this new truststore, or modify the JRE's list of CA Certificates.
Option 1: Create a New Truststore
This option creates a new list of CA Certificates and configures your build tool to use this new list as the JRE's list of approved CA certificates.
Within KeyStore Explorer, select File > Save As... and save the new truststore file as a JKS file within your project location. You will be prompted for a password; we use password in the examples below.
Maven
The following snippet shows how to configure Maven to use this new truststore file:
$ ./mvnw -Djavax.net.ssl.trustStore=path/to/truststore.jks \
-Djavax.net.ssl.trustStorePassword=password \
-Dimage=<host>:<port>/<image> jib:buildGradle
The following snippet shows how to configure Gradle to use this new truststore file:
$ ./gradlew jib \
-Djavax.net.ssl.trustStore=path/to/truststore.jks \
-Djavax.net.ssl.trustStorePassword=passwordOption 2: Modify the JRE `cacerts`
The other approach modifies the JRE's list of CA Certificates to include the registry's self-signed certificate. The certificate will be trusted at the JRE level, affecting all Java applications running on it. You must re-import the certificate when you update to a new JRE.
Basically you instruct KeyStore Explorer to save your modified cacerts and replace what was previously configured with the JRE. Depending on your operating system and permissions, you may need to save to a new file and then replace the original lib/security/cacerts file with administrative privileges.
--- METRICS ---
- Files Extracted: 25
- Estimated Token Budget: ~50120 tokens
- Canonical Reference: https://codewiki.google/github.com/GoogleContainerTools/jib