Skip to content

Latest commit

 

History

History
452 lines (322 loc) · 20.2 KB

faq.md

File metadata and controls

452 lines (322 loc) · 20.2 KB

Analytics

Frequently Asked Questions (FAQ)

If a question you have is not answered below, please submit an issue.

But, I'm not a Java developer.
How do I run the image I built?
Where is bash?
How do I set parameters for my image at runtime?
What image format does Jib use?
Can I define a custom entrypoint?
I want to containerize an executable JAR.
Where is the application in the container filesystem?
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?
What would a Dockerfile for a Jib-built image look like?
How can I inspect the image Jib built?
I am seeing ImagePullBackoff on my pods.
How do I configure a proxy?
How can I diagnose problems pulling or pushing from remote registries?
How can I examine network traffic?
How do I view debug logs for Jib?
How do I enable debugging?
Why is my image created 48 years ago?
I would like to run my application with a javaagent.
How can I tag my image with a timestamp?

But, I'm not a Java developer.

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.

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 <image name>.

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 <image name> before using docker run.

To run your image on Kubernetes, you can use kubectl:

kubectl run jib-deployment --image=<image name>

For more information, see steps 4-6 of the Kubernetes Engine deployment tutorial.

Where is bash?

By default, Jib uses distroless/java as the base image. Distroless images contain only runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution. Check out the distroless project for more information about distroless images.

If you would like to include a shell for debugging, set the base image to gcr.io/distroless/java:debug instead. The shell will be located at /busybox/sh. Note that :debug images are not recommended for production use.

Configuring a base image in Maven

In jib-maven-plugin, you can use the gcr.io/distroless/java:debug base image by adding the following configuration:

<configuration>
  <from>
    <image>gcr.io/distroless/java:debug</image>
  </from>
</configuration>

Configuring a base image in Gradle

In jib-gradle-plugin, you can use the gcr.io/distroless/java:debug base image by adding the following configuration:

jib.from.image = 'gcr.io/distroless/java:debug'


You can then run the image in shell form with Docker: docker run -it --entrypoint /busybox/sh <image name>

How do I set parameters for my image at runtime?

JVM Flags

For the default distroless/java 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>" <image name>

Using Kubernetes:

apiVersion: v1
kind: Pod
spec:
  containers:
  - name: <name>
    image: <image name>
    env:
    - name: JAVA_TOOL_OPTIONS
      value: <JVM flags>

Other Environment Variables

Using Docker: docker run -e "NAME=VALUE" <image name>

Using Kubernetes:

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

Arguments to Main

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

Using Kubernetes:

apiVersion: v1
kind: Pod
spec:
  containers:
  - name: <name>
    image: <image name>
    args:
    - <arg1>
    - <arg2>
    - <arg3>

For more information, see the JAVA_TOOL_OPTIONS environment variable, the docker run -e reference, and defining environment variables for a container in Kubernetes.

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.

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 an executable JAR.

Although it is possible to configure Jib to add a JAR to the container and run it using a custom java -jar ... or java -cp ... entrypoint command, the intention of Jib is to add individual class files and dependency JARs into the container instead of putting a runnable JAR into the container. 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.

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 (/)

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

Maven

In jib-maven-plugin, you can then use this custom base image by adding the following configuration:

<configuration>
  <from>
    <image>custom-base-image</image>
  </from>
</configuration>

Gradle

In jib-gradle-plugin, you can then use this custom base image by adding the following configuration:

jib.from.image = 'custom-base-image'

Can I ADD a custom directory to the image?

We currently support adding a custom directory with an incubating feature. This feature may change in later versions. If your application needs to use custom files, place them into the src/main/jib folder. Files placed here will be added to the filesystem of the container. For example, src/main/jib/foo/bar would add /foo/bar into the container filesystem.

I need to add files generated during the build process to a custom directory on the image.

If the current extra directory 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

Maven

In Maven, you can use the maven-resources-plugin to copy files to your extra directory. For example, if you generate files in target/generated/files and want to add them to /my/files on the container, you can add the following to your pom.xml:

<plugins>
  ...
  <plugin>
    <artifact>jib-maven-plugin</artifact>
    ...
    <configuration>
      <extraDirectory>${project.basedir}/target/extra-directory/</extraDirectory>
    </configuration>
  </plugin>
  ...
  <plugin>
    <artifact>maven-resources-plugin</artifact>
    <version>3.1.0</version>
    <configuration>
      <outputDirectory>${project.basedir}/target/extra-directory/my/files</outputDirectory>
      <resources>
        <resource>
          <directory>${project.basedir}/target/generated/files</directory>
        </resource>
      </resources>
    </configuration>
  </plugin>
  ...
</plugins>

The copy-resources goal will run automatically before compile, so if you are copying files from your build output to the extra directory, you will need to either set the life-cycle phase to post-compile or later, or run the goal manually:

mvn compile resources:copy-resources jib:build

Gradle

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

jib.extraDirectory = file('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.

What would a Dockerfile for a Jib-built image look like?

A Dockerfile that performs a Jib-like build is shown below:

# Jib uses distroless java as the default base image
FROM gcr.io/distroless/java:latest

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

I am seeing ImagePullBackoff on my pods (in minikube).

When you use your private image built with Jib in a Kubernetes cluster, the cluster needs to be configured with credentials to pull the image. This involves 1) creating a Secret, and 2) using the Secret as imagePullSecrets.

kubectl create secret docker-registry registry-json-key \
  --docker-server=<registry> \
  --docker-username=<username> \
  --docker-password=<password> \
  --docker-email=<any valid email address>

kubectl patch serviceaccount default \
  -p '{"imagePullSecrets":[{"name":"registry-json-key"}]}'

For example, if you are using GCR, the commands would look like (see Advanced Authentication Methods):

kubectl create secret docker-registry gcr-json-key \
  --docker-server=https://gcr.io \
  --docker-username=_json_key \
  --docker-password="$(cat keyfile.json)" \
  --docker-email=any@valid.com

kubectl patch serviceaccount default \
  -p '{"imagePullSecrets":[{"name":"gcr-json-key"}]}'

See more at Using Google Container Registry (GCR) with Minikube.

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

  • Access requires a proxy. See How do I configure a proxy? for details.
  • The registry does not support HTTPS. We do not pass authentication details on non-HTTPS connections, though this can be overridden with the sendCredentialsOverHttp system property, but it is not recommend (version 0.9.9).
  • The registry's SSL certificates have expired or are not trusted. We have a separate document on handling registries that use self-signed certificates, which may also apply if the SSL certificate is signed by an untrusted Certificate Authority. Jib supports an allowInsecureRegistries flag to ignore SSL certificate validation, but it is not recommend (version 0.9.9).
  • The registry does not support the Docker Image Format V2 Schema 2 (sometimes referred to as v2-2). This problem is usually shown by failures wth INVALID_MANIFEST errors. Some registries can be configured to support V2-2 such as Artifactory and OpenShift. Other registries, such as Quay.io/Quay Enterprise, are in the process of adding support.

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 jibSerialize property.

To see the HTTP traffic, create a logging.properties file with the following:

handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=ALL

# CONFIG hides authentication data
# ALL includes authentication data
com.google.api.client.http.level=CONFIG

And then launch your build tool as follows:

mvn -Djava.util.logging.config.file=path/to/log.properties -DjibSerialize=true ...

or

gradle -Djava.util.logging.config.file=path/to/log.properties -DjibSerialize=true ...

How do I view debug logs for Jib?

Maven: use mvn -X -DjibSerialize=true to enable more detailed logging and serialize Jib's actions.

Gradle: use grade --debug -DjibSerialize=true to enable more detailed logging and serialize Jib's actions.

How do I enable debugging?

If using the distroless/java base image, then use the JAVA_TOOL_OPTIONS to pass along debugging configuration arguments. For example, to have the remote VM accept debug connections on port 5005, but not suspend:

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

Then connect your debugger to port 5005 on the given host. You can port-forward the container port to a localhost port for easy access.

Using Docker: docker run -p 5005:5005 <image>

Using Kubernetes: kubectl port-forward <pod name> 5005:5005

Why is my image created 48 years ago?

For reproducibility purposes, Jib sets the creation time of the container images to 0 (January 1st, 1970). If you would like to forgo reproducibility and use the real creation time, set the useCurrentTimestamp parameter to true in your build configuration.

Maven

<configuration>
  <container>
    <useCurrentTimestamp>true</useCurrentTimestamp>
  </container>
</configuration>

Gradle

jib.container.useCurrentTimestamp = true

I would like to run my application with a javaagent.

See Can I ADD a custom directory to the image?.

TODO: Provide more comprehensive solution.

How can I tag my image with a timestamp?

Maven

To tag the image with a simple timestamp, add the following to your pom.xml:

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

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

<configuration>
  <to>
    <image>my-image-name:${maven.build.timestamp}</image>
  </to>
</configuration>

You can then use the same timestamp to reference the image in other plugins.

Gradle

To tag the image with a timestamp, simply set the timestamp as the tag for to.image in your jib configuration. For example:

jib.to.image = 'gcr.io/my-gcp-project/my-app:' + System.nanoTime()