JIB - A Powerful Docker Image Builder
Published: 2021-01-27 18:31:13

## Introduction
What is JIB? JIB is a library created by Google to help you to generate Docker images of your Java projects without Docker locally.

What does it mean? 

<br/>

## Global Presentation
In a classic way, we must have a dockerfile in our Java project. Build the Docker image with the command lines and push it to a registry. This way forces us to have Docker locally to be able to build the image and have some knowledge about Docker and how to construct a dockerfile.

The new way proposed by Google is a lot more simplified. We now have an entry element (the project) and 1 step (the build) in the process. We don't need Docker anymore locally. And devs only have to configure some elements to build the image we want.

<br/>

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0nfa0bjjaza8xraw9y74.png)

<br/>

## Technical Presentation
To be able to use JIB, you have 3 ways to do it :
* with Maven plugin ([jib-maven-plugin](https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#container-object))
* with Gradle plugin ([jib-gradle-plugin](https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin))
* with the Core library ([jib-core](https://github.com/GoogleContainerTools/jib/tree/master/jib-core))

We will talk a little more about the first one.

<br/>

### Maven Plugin - Base

In its simplest form, the Maven plugin implementation looks like this.

```xml
<project>
  ...
  <build>
    <plugins>
      ...
      <plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>jib-maven-plugin</artifactId>
        <version>2.5.2</version>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>
```

It's simple, just a declaration in the Build section. But with this, you are only able to generate a local **.tar** file with the following command.

```
mvn compile jib:buildTar
```

If you try to create a Dockerimage and push it to a registry with this configuration, you will quickly see that you need more parameters. 
```
> mvn compile jib:build
...
[ERROR] Failes to execute goal com.google.cloud.tools:jib-maven-plugin:2.5.2:build (default-cli) on project jib-demo: Missing target image parameter.
```

With the documentation, you have two options to give the required data :
* In a command parameter: **-Dimage**
* In the pom configuration

Here is the minimal configuration to generate a Docker image and push it to a library with the command **mvn compile jib:build**.

```xml
<build>
    <plugins>
        <plugin>
            <groupId>com.google.cloud.tools</groupId>
            <artifactId>jib-maven-plugin</artifactId>
            <version>2.5.2</version>
            <configuration>
                <to>
                    <image>docker.io/my-docker-id/my-app</image>
                </to>
            </configuration>
        </plugin>
    </plugins>
</build>
```

If you want to push the Docker image to a private repository, it's also possible with the next options. In this place you also can add other configs like tags...
```xml
<to>
    <image>docker.io/my-docker-id/my-app</image>
    <auth>
        <username>dockerRegistry_username</username>
        <password>dockerRegistry_password</password>
    </auth>
</to>
```

<br/>

### Maven Plugin - Options
As it's possible to define a lot of things for future Docker images, you can define some elements for your image basis.

By default, JIB will use a **[distoless](https://github.com/GoogleContainerTools/distroless/tree/master/java)** image which only contains the minimum for Linux and an OpenJDK runtime. But for several reasons, you may need other tools like a terminal or curl. That's the objective of the **from** parameter. You can define the image to use with its version and the credentials if the image is in a private registry.

```xml
<from>
    <image>openjdk:alpine</image>
</from>
```
```xml
<from>
    <image>docker.io/my-docker-id/my-app</image>
    <auth>
        <username>dockerRegistry_username</username>
        <password>dockerRegistry_password</password>
    </auth>
</from>
```

Also you have so much options to configure your image, like : 
* **extraDirectories** which inject files to the image and define their rights in the image
```xml
<configuration>
  <extraDirectories>
    <paths>
      <!-- Copies from 'src/main/custom-extra-dir' into '/' on the container. -->
      <path>src/main/custom-extra-dir</path>
      <!-- Copies from '/home/user/jib-extras' into '/extras' on the container -->
      <path>
        <from>/home/user/jib-extras</from>
        <into>/extras</into>
      </path>
    </paths>
    <permissions>
      <permission>
        <file>/path/on/container/to/fileA</file>
        <mode>755</mode> <!-- Read/write/execute for owner, read/execute for group/other -->
      </permission>
      <permission>
        <file>/path/to/another/file</file>
        <mode>644</mode> <!-- Read/write for owner, read-only for group/other -->
      </permission>
      <permission>
        <file>/glob/pattern/**/*.sh</file>
        <mode>755</mode>
      </permission>
    </permissions>
  </extraDirectories>
</configuration>
```
* **jvmflags** to add JVM flags
```xml
<container>
    <jvmFlags>
        <jvmFlag>-Duser.timezone=America/Montreal</jvmFlag>
        <jvmFlag>-XX:MetaspaceSize=96m </jvmFlag>
        <jvmFlag>-XX:MaxMetaspaceSize=256m</jvmFlag>
        <jvmFlag>-Djava.net.preferIPv4Stack=true</jvmFlag>
        <jvmFlag>-Xss228k</jvmFlag>
        <jvmFlag>-XX:+HeapDumpOnOutOfMemoryError</jvmFlag>
        <jvmFlag>-XX:HeapDumpPath=/tmp</jvmFlag>
    </jvmFlags>
</container>
```
* **ports** to define which ports have to be exposed
```xml
<container>
    <ports>
        <port>8080</port>
        <port>9999</port>
    </ports>
</container>
```
* **environment** to define environment variables
```xml
<container>
  <environment>
      <DB_PASSWORD>pwd</DB_PASSWORD>
      <DB_USERNAME>usr</DB_USERNAME>
  </environment>
</container>
```

... 

If you want more information, please check the Maven plugin README: https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin 

If you are not a Java dev, you can check the project **[rules_docker](https://github.com/bazelbuild/rules_docker)** which can do the same things for other languages like:
- Python
- NodeJS
- Java
- Scala
- Groovy
- C
- Go
- Rust 
- D
*(I don't use it or even try it, I want to mention them because Google mention them and it can be really useful.)*

<br/>

---

<br/>

## Sources 
### JIB
* https://cloud.google.com/java/getting-started/jib
* https://github.com/GoogleContainerTools/jib
* https://cloud.google.com/blog/products/gcp/introducing-jib-build-java-docker-images-better 
* https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#frequently-asked-questions-faq

### Rules Docker
* https://github.com/bazelbuild/rules_docker