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?
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.
To be able to use JIB, you have 3 ways to do it :
- with Maven plugin (jib-maven-plugin)
- with Gradle plugin (jib-gradle-plugin)
- with the Core library (jib-core)
We will talk a little more about the first one.
In its simplest form, the Maven plugin implementation looks like this.
<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.
<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...
<to> <image>docker.io/my-docker-id/my-app</image> <auth> <username>dockerRegistry_username</username> <password>dockerRegistry_password</password> </auth> </to>
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 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.
<from> <image>openjdk:alpine</image> </from>
<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
<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
<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
<container> <ports> <port>8080</port> <port>9999</port> </ports> </container>
- environment to define environment variables
<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 which can do the same things for other languages like:
- 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.)