jib Documentation

Build container images for your Java applications.

RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy jib on any server, homelab, or cloud container platform.

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.

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

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:

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.


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.

sh
# docker not required
$ docker
-bash: docker: command not found
# build and upload an image
$ jib build --target=my-registry.example.com/built-by-jib

Additionally, Jib CLI can directly build an optimized image for JAR files (including Spring Boot fat JAR).

sh
$ jib jar --target=my-registry.example.com/jar-app myapp.jar

The CLI tool is powered by Jib Core, a Java library for building containers without Docker.

Table of Contents

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:

  1. Install the verification tool from slsa-framework/slsa-verifier#installation.
  2. Download the signature file jib-jre-<version>.zip.intoto.jsonl from the GitHub releases page.
  3. Run the verifier:
shell
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:

text
choco install jib
choco upgrade jib
choco uninstall jib

Build Yourself from Source (for Advanced Users)

Use the application plugin's installDist task to create a runnable installation in
build/install/jib. A zip and tar file are also created in build/distributions.

sh
# build
$ ./gradlew jib-cli:installDist
# run
$ ./jib-cli/build/install/jib/bin/jib

Jib 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:

  1. build - containerizes using a build file.
  2. jar - containerizes JAR files.
  3. war - containerizes WAR files.

Build Command

This command follows the following pattern:

text
jib build --target <image name> [options]

Quickstart

  1. Create a hello world script (script.sh) containing:
    sh
    #!/bin/sh
    echo "Hello World"
  2. Create a build file. The default is a file named jib.yaml in the project root.
    yaml
    apiVersion: jib/v1alpha1
    kind: BuildFile
    
    from:
      image: ubuntu
    
    entrypoint: ["/script.sh"]
    
    layers:
      entries:
        - name: scripts
          files:
            - properties:
                filePermissions: 755
              src: script.sh
              dest: /script.sh
  3. Build to docker daemon
    text
    $ jib build --target=docker://jib-cli-quickstart
  4. Run the container
    text
    $ 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 ${} with (repeatable)

Jar Command

This command follows the following pattern:

text
jib jar --target <image name> path/to/myapp.jar [options]

Quickstart

  1. 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
  2. Containerize your JAR using the jar command. In the default mode (exploded), the entrypoint will be set to java -cp /app/dependencies/:/app/explodedJar/ HelloWorld
    text
    $ jib jar --target=docker://cli-jar-quickstart target/spring-petclinic-*.jar
  3. Run the image and open your browser at http://localhost:8080
    text
    $ 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:

text
$ jib war --target <image-name> path/to/myapp.war

Quickstart

  1. Have your sample WAR ready and use the war command to containerize your WAR. By default, the WAR command uses jetty as the base image so the entrypoint is set to java -jar /usr/local/jetty/start.jar --module=ee10-deploy:
    text
    $ jib war --target=docker://cli-war-quickstart <your-sample>.war
  2. Run the image and open your browser at http://localhost:8080
    text
    $ 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:

text
[@<filename>...]      One or more argument files containing options.

Auth/Security

text
--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:

text
--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 registry

Note - Combinations of credential-helper, username and password flags come with restrictions and can be use only in the following ways:

Only Credential Helper

  1. --credential-helper
  2. --to-credential-helper
  3. --from-credential-helper
  4. --to-credential-helper, --from-credential-helper

Only Username and Password

  1. --username, --password
  2. --to-username, --to-password
  3. --from-username, --from-password
  4. --to-username, --to-password, --from-username, --from-password

Mixed Mode

  1. --to-credential-helper, --from-username, --from-password
  2. --from-credential-helper, --to-username, --to-password

Info Params

text
--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 information

Debugging Params

text
--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 mode

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, then mirror.gcr.io, localhost:5000, and the Docker Hub (registry-1.docker.io) are tried in order until Jib can successfully pull a base image.
json
{
  "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`)

text
/* 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 src is directory, dest is always considered a directory, directory and contents will be copied over and renamed to dest
    • if src is file
      • if dest ends with / then it is considered a target directory, file will be copied into directory
      • if dest doesn't end with / then is is the target file location, src file will be copied and renamed to dest
  • 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.txt as seen on the running container will have filePermissions 234.
    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, /somewhere on the container will have the directory permissions 755, not 777 as some might expect.
    text
    - name: layer
      properties:
        directoryPermissions: "777"
      - src: file.txt
        dest: /somewhere/file.txt
  • excludes on a directory can lead to unintended inclusion of files in the directory, to exclude a directory and all its files
    text
    excludes:
      - "**/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:

  • volumes
  • exposedPorts

Parameters that will append any new keys, and overwrite existing keys:

  • labels
  • environment

Parameters that will be overwritten:

  • user
  • workingDirectory
  • entrypoint
  • cmd

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:

xml
<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:

groovy
dependencies {
  compile 'com.google.cloud.tools:jib-core:0.28.2'
}

Examples

java
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")));
  1. Jib.from("busybox") creates a new JibContainerBuilder configured with busybox as the base image.
  2. .addLayer(...) configures the JibContainerBuilder with a new layer with helloworld.sh (local file) to be placed into the container at /helloworld.sh.
  3. .setEntrypoint("sh", "/helloworld.sh") sets the entrypoint of the container to run /helloworld.sh.
  4. RegistryImage.named("gcr.io/my-project/hello-from-jib") creates a new RegistryImage configured with gcr.io/my-project/hello-from-jib as the target image to push to.
  5. .addCredential adds the username/password credentials to authenticate the push to gcr.io/my-project/hello-from-jib. See CredentialRetrieverFactory for common credential retrievers (to retrieve credentials from Docker config or credential helpers, for example). These credential retrievers can be used with .addCredentialRetriever.
  6. Containerizer.to creates a new Containerizer configured to push to the RegistryImage.
  7. .containerize executes the containerization. If successful, the container image will be available at gcr.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:

Other useful classes:

  • ImageReference - represents an image reference and has useful methods for parsing and manipulating image references
  • LayerConfiguration - configures a container layer to build
  • CredentialRetriever - implement with custom credential retrieval methods for authenticating against a container registry
  • CredentialRetrieverFactory - provides useful CredentialRetrievers to retrieve credentials from Docker config and credential helpers

Java-specific API:

API reference

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:

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.

java
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 using getMessage() and getLevel(), 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 using getElapsed() and getDuration(), 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 using getAllocation().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

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:

groovy
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:

shell
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:

shell
gradle jibDockerBuild

If 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:

groovy
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:

groovy
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:

groovy
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:

groovy
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:

groovy
jib.to.image = 'my_acr_name.azurecr.io/my-app'

Build Your Image

Build your container image with:

shell
gradle jib

Subsequent 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.

shell
gradle jibDockerBuild

If you are using minikube's remote Docker daemon, make sure you set up the correct environment variables to point to the remote daemon:

shell
eval $(minikube docker-env)
gradle jibDockerBuild

Alternatively, 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:

shell
gradle jibBuildTar

This builds and saves your image to build/jib-image.tar, which you can load into docker with:

shell
docker load --input build/jib-image.tar

Run `jib` with each build

You can also have jib run with each build by attaching it to the build task:

groovy
tasks.build.dependsOn tasks.jib

Then, 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
  • Java 8 or Jib < 3.1: When set to true, does not use a wildcard (for example, /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.
  • Java >= 9 and Jib >= 3.1: The option has no effect. Jib always enumerates the dependency JARs. This is achieved by creating and using an argument file for the --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:

    shell
    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,arg3

    The 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, then mirror.gcr.io, localhost:5000, and the Docker Hub (registry-1.docker.io) are tried in order until Jib can successfully pull a base image.
    json
    {
      "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, and localhost: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
    groovy
    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:

    groovy
    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:

    groovy
    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:

    groovy
    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:

    groovy
    extraDirectories {
       paths = project.provider { 'src/main/custom-extra-dir' }
       permissions = project.provider { ['/path/on/container/to/fileA': '755'] }
    }
    groovy
    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:

    Configure credential helpers to use by specifying them as a credHelper for their respective image in the jib extension.

    Example configuration:

    groovy
    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.

    groovy
    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):

    groovy
    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:

    groovy
    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.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:

    gradle
    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.

    gradle
    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

    Quickstart

    You can containerize your application easily with one command:

    shell
    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:

    shell
    mvn compile com.google.cloud.tools:jib-maven-plugin:3.5.2:dockerBuild

    If 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:

    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:

    xml
    <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:

    xml
    <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:

    xml
    <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:

    xml
    <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:

    xml
    <configuration>
      <to>
        <image>my_acr_name.azurecr.io/my-app</image>
      </to>
    </configuration>

    Build your image

    Build your container image with:

    shell
    mvn compile jib:build

    Subsequent 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.

    shell
    mvn compile jib:dockerBuild

    If you are using minikube's remote Docker daemon, make sure you set up the correct environment variables to point to the remote daemon:

    shell
    eval $(minikube docker-env)
    mvn compile jib:dockerBuild

    Alternatively, 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:

    shell
    mvn compile jib:buildTar

    This builds and saves your image to target/jib-image.tar, which you can load into docker with:

    shell
    docker load --input target/jib-image.tar

    Bind 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:

    xml
    <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:

    shell
    mvn package

    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 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
  • Java 8 or Jib < 3.1: When set to true, does not use a wildcard (for example, /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.
  • Java >= 9 and Jib >= 3.1: The option has no effect. Jib always enumerates the dependency JARs. This is achieved by creating and using an argument file for the --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:

    shell
    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,arg3

    The 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, then mirror.gcr.io, localhost:5000, and the Docker Hub (registry-1.docker.io) are tried in order until Jib can successfully pull a base image.
    json
    {
      "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, and localhost: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
    xml
    <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:

    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:

    xml
    <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:

    xml
    <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:

    Configure credential helpers to use by specifying them as a credHelper for their respective image.

    Example configuration:

    xml
    <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.

    xml
    <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:

    xml
    <settings>
      ...
      <servers>
        ...
        <server>
          <id>MY_REGISTRY</id>
          <username>MY_USERNAME</username>
          <password>{MY_SECRET}</password>
        </server>
      </servers>
    </settings>
    • The id field 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:

    xml
    <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.

    xml
    <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

    1. Run ./mvnw clean package to build your container
    2. Start the application
      • With Docker: docker run --rm -p 8080:8080 dropwizard-jib-example:1
      • Without Docker: ./mvnw exec:java
    3. 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

    sh
    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:

    1. In pom.xml or build.gradle, replace REPLACE-WITH-YOUR-GCP-PROJECT with your GCP project.

    2. Run mvn compile jib:build or ./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:

    1. Replace REPLACE-WITH-YOUR-GCP-PROJECT with your GCP project in pom.xml or build.gradle.

    2. Run mvn package or ./gradlew to 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.

    shell
    ./gradlew jibDockerBuild
    
    docker run --rm -p 8080:8080 ktor-jib-example:1

    The 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)
    • 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

    shell
    ./gradlew jibDockerBuild
    
    docker run -d -p 8080:8080 micronaut-jib:0.1
    shell
    curl localhost:8080/hello
    > Hello World

    Give it a

    With Kubernetes

    shell
    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 &
    shell
    curl localhost:8080/hello
    > Hello World

    Give it a

    More 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:

    1. name-service - responds with a name
    2. shared-library - a project dependency used by name-service
    3. hello-service - calls name-service and 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 the
    shared-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:

    shell
    export PROJECT_ID=$(gcloud config list --format 'value(core.project)')

    Run the Maven build:

    shell
    # 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 -am

    Run the Gradle build:

    shell
    # build everything
    ./gradlew jib
    
    # build just hello-service
    ./gradlew :hello-service:jib
    
    # build name-service (with dependency on shared-library)
    ./gradlew :name-service:jib

    You 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.0
    • hello-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:

    shell
    gcloud container clusters create jib

    Apply to your Kubernetes cluster:

    shell
    kubectl apply -f kubernetes.yaml

    Find the EXTERNAL-IP of the hello-service.

    text
    NAME                TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
    svc/hello-service   LoadBalancer   10.19.243.223   35.237.89.148   80:30196/TCP   1m

    Visit the IP in your web browser and you should see:

    text
    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:

    shell
    ./mvnw compile jib:build -Dimage=<your image, eg. gcr.io/my-project/spring-boot-jib>

    Gradle:

    shell
    ./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.

    shell
    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 8080
    shell
    curl localhost:8080
    > Greetings from Spring Boot and Jib!

    * If you are using Gradle, use ./gradlew jib --image=$IMAGE instead of the ./mvnw command

    Give it a

    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.

    shell
    ./gradlew jibDockerBuild
    
    docker run -d --rm -p 8080:8080 vertx-jib-example

    More 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:

    text
    /* 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:

    shell
    gcloud components install docker-credential-gcr

    Alternatively, if you have go get installed, you can run:

    shell
    go get -u github.com/GoogleCloudPlatform/docker-credential-gcr

    Alternatively, 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:

    shell
    docker-credential-gcr gcr-login

    This 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:

    text
    > 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.
    • 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

      groovy
      jib {
        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. (Note gcr.io/distroless/java-debian10 doesn't have :8.)

    • WAR projects

      gradle
      jib {
        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:

    shell
    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

      groovy
      jib.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

    xml
    <configuration>
      <container>
        <creationTime>2019-07-15T10:15:30+09:00</creationTime>
      </container>
    </configuration>

    Gradle

    groovy
    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.extraDirectories in 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:

    yaml
    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:

    yaml
    apiVersion: v1
    kind: Pod
    spec:
      containers:
      - name: <name>
        image: <image name>
        env:
        - name: NAME
          value: VALUE

    Arguments to Main

    Using Docker: docker run <arg1> <arg2> <arg3>

    Using Kubernetes:

    yaml
    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 package in Maven or the jar task 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:

    xml
    <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:

    groovy
    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:

    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:

    sh
    mvn compile resources:copy-resources jib:build

    Gradle

    The same can be accomplished in Gradle by using a Copy task. In your build.gradle:

    groovy
    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 setupExtraDir

    The 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:dockerBuild for Maven or jibDockerBuild for Gradle to build directly to your local Docker daemon.
    • Use jib:buildTar for Maven or jibBuildTar for Gradle to build the image to a tarball, then use docker load --input to load the image into Docker (the tarball built with these commands will be located in target/jib-image.tar for Maven and build/jib-image.tar for Gradle by default).
    • docker pull the 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:

    text
    -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=localhost:5005

    Then 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

    xml
    <configuration>
      <container>
        <jvmFlags>
          <jvmFlag>-javaagent:/myfolder/agent.jar</jvmFlag>
        </jvmFlags>    
      </container>
    </configuration>

    Gradle

    groovy
    jib.container.jvmFlags = ['-javaagent:/myfolder/agent.jar']

    See also:

    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:

    xml
    <properties>
      <maven.build.timestamp.format>yyyyMMdd-HHmmssSSS</maven.build.timestamp.format>
    </properties>

    Then in the jib-maven-plugin configuration, set the tag to:

    xml
    <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:

    groovy
    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:

    dockerfile
    # 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,

    xml
    <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>
    gradle
    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 architecture and os are 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.

    text
    $ 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 set jib.from.image at 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 --offline to Maven or Gradle. Before that, you need to run Jib online once to cache the image. However, --offline means 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.
    • Retry with increasing backoffs. For example, using the retry tool.

    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:

    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 login or podman login) at

        • $XDG_RUNTIME_DIR/containers/auth.json, $XDG_CONFIG_HOME/containers/auth.json or $HOME/.config/containers/auth.json
        • $DOCKER_CONFIG/config.json
        • $HOME/.docker/config.json

        This is one of the configuration files for the docker or podman command line tool. See configuration files document, credential store and credential helper sections, and this for how to configure auth. For example, you can do docker login to save auth in config.json, but it is often recommended to configure a credential helper (also configurable in config.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

    • 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
    • $HOME/.docker/config.json may also contain short-lived authorizations in the auths block that may have expired. In the case of Google Container Registry, if you had previously used gcloud docker to configure these authorizations, you should remove these stale authorizations by editing your config.json and deleting lines from auths associated with gcr.io (for example: "https://asia.gcr.io"). You can then run gcloud auth configure-docker to correctly configure the credHelpers block 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:

    text
    Using credentials from Docker config (/home/user/.docker/config.json) for localhost:5000/java
    text
    Using credential helper docker-credential-gcr for gcr.io/project/repo
    text
    Using credentials from Maven settings file for gcr.io/project/repo
    text
    Using credentials from <from><auth> for gcr.io/project/repo
    text
    Using credentials from to.auth for gcr.io/project/repo

    If 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:

    text
    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=CONFIG

    And then launch your build tool as follows:

    sh
    mvn --batch-mode -Djava.util.logging.config.file=path/to/logging.properties -Djib.serialize=true ...

    or

    sh
    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:

    text
    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)

    groovy
    plugins {
      id 'com.google.cloud.tools.jib' version 'x.y.z' apply false
    }

    build.gradle (sub-project)

    groovy
    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):

    text
    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 61

    Jib 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:

    text
    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.

    shell
    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):

    shell
    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:

    text
    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.

    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.

    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:

    text
    $ jib war --target=<image-reference> myapp.war --from=tomcat:8.5-jre8-alpine --app-root=/usr/local/tomcat/webapps/ROOT

    Google Cloud Build (`docs/google-cloud-build.md`)

    Jib on Google Cloud Build

    You can use Jib on Google Cloud Build in a simple step:

    yaml
    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:

    yaml
    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:

    yaml
    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_SHA

    Privacy (`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

    1. set the jib.disableUpdateChecks system property to true
    2. set disableUpdateCheck to true in 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_HOME is defined), else $HOME/.config/google-cloud-tools-java/jib/config.json
      • Mac: $XDG_CONFIG_HOME/Google/Jib/config.json (if $XDG_CONFIG_HOME is defined), else $HOME/Library/Preferences/Google/Jib/config.json
      • Windows: $XDG_CONFIG_HOME\Google\Jib\Config\config.json (if $XDG_CONFIG_HOME is defined), else %LOCALAPPDATA%\Google\Jib\Config\config.json

    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:

    shell
    $ 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:

    text
    println org.gradle.internal.jvm.Jvm.current().getJavaHome()

    And run gradle -I /path/to/script to output the executing JRE location.

    shell
    $ 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 no jre/ directory then this is a JRE distribution and should navigate and instead open the file at lib/security/cacerts.
      • In the example above, this file would be /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/jre/lib/security/cacerts.
    • You will likely be prompted for a password. The default password for the cacerts file is changeit.

    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:

    shell
    $ ./mvnw -Djavax.net.ssl.trustStore=path/to/truststore.jks \
      -Djavax.net.ssl.trustStorePassword=password \
      -Dimage=<host>:<port>/<image> jib:build

    Gradle

    The following snippet shows how to configure Gradle to use this new truststore file:

    shell
    $ ./gradlew jib \
      -Djavax.net.ssl.trustStore=path/to/truststore.jks \
      -Djavax.net.ssl.trustStorePassword=password

    Option 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 ---