Easily convert Java application to Docker container with Jib ~ Build with gradle and register in local repository

Overview

In this entry, I will try the procedure to easily make a Java application into a Docker container by using Jib published by Google.

The content we are checking is almost the same as the one on Jib's Gradle plugin site, but the following two points are different.

--I'm trying jibDockerBuild first (because I've tried private repositories later). --This is an example of using a private repository instead of {GCR, ACE, Docker Hub Registry} as the storage destination of the Docker container.

Premise

The middleware and libraries use the following.

Target audience

For the following readers: --Those who have knowledge of Java and Spring Framework and have experience of building and executing "Hello World" apps with build tools. --Those who can work using the command line on the OS terminal --Those who are interested in Docker containerization of Java applications

Related entries

As of July 16, 2018, there was the following entry on Qiita with the keyword of Jib.

-Easy Dockerization of Java applications with Jib ... this entry makes use of the maven plugin.

Development environment preparation

JDK

Obtain "jdk-8u171-macosx-x64.dmg" from the distribution source site and start the installer from the dmg file.

spring (CLI)

Install the command line program to create a sample app. (This is not required. It is enough to refer to the sample on GitHub.)

Install with sdkman.

$ sdk install springboot

Prepare the application

Prepare the source code of the application that can be built with Gradle using the CLI of Spring Boot.

$ spring init -d=web --build=gradle jib-test Using service at https://start.spring.io Project extracted to '/Users/hiroki/jib-test'

Refurbishment

The main class of the project has been modified as follows so that it functions as RestController. (I'm sorry for the omission) This source is stored on GitHub as tag 1.0.

package com.example.jibtest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class DemoApplication {

    @RequestMapping("/")
    @GetMapping
	public String hello() {
        return "Hello World!";
    }

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}

Make sure the application can run

Launch the application with gradlew.

$ cd jib-test
$ ./gradrew bootRun

Make sure the application is running on port 8080 in your local environment.

$ curl http://localhost:8080/
Hello World!

Build

Assuming you are ready and running the Docker daemon, use gradle to build the container.

「gcr.io/distroless/java」が利用されていることがわかります。

$ gradle jibDockerBuild
Tagging image with generated image reference jib-test:0.0.1-SNAPSHOT. If you'd like to specify a different tag, you can set the jib.to.image parameter in your build.gradle, or use the --image=<MY IMAGE> commandline flag.
warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible

Containerizing application to Docker daemon as jib-test:0.0.1-SNAPSHOT...

Getting base image gcr.io/distroless/java...
Building dependencies layer...
Building resources layer...
Building classes layer...
Finalizing...
Loading to Docker daemon...
(The following is omitted)

Make sure you have an image. (Hmm, isn't it cute that the time stamp is strange? Since this year is 2018, it seems that the subtraction from 1970 is somehow calculated.) The size was 134MB.

$ docker images | grep jib-test
jib-test            0.0.1-SNAPSHOT      2ce8c6f47c83        48 years ago        134MB

I will start it. Note that you are exposing port 8080 to the host and you are specifying the version "0.0.1-SNAPSHOT" built with the Gradle plugin.

$ docker run -p 8080:8080 -it jib-test:0.0.1-SNAPSHOT 

Make sure your application is running the same way it was before containerization.

$ curl http://localhost:8080/
Hello World!

feel well. The projects so far are stored in GitHub as "Add-Gradle-Plugin".

Since it runs on distroless, the JavaVM binaries exist,

$ docker exec -it 481fc8ea9d2a java -version
openjdk version "1.8.0_171"
OpenJDK Runtime Environment (build 1.8.0_171-8u171-b11-1~deb9u1-b11)
OpenJDK 64-Bit Server VM (build 25.171-b11, mixed mode)

/ bin / bash does not exist.

$ docker exec -it 481fc8ea9d2a /bin/bash
OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown

Under the build directory, there was a directory called jib-cache, in which there was a tar.gz file with a size of a dozen MB.

Contents of tar.gz file under build / jib-cache
$ tar tvf dc3bf5c6afa437de068b6d692f7bd72e29fd7501577c2886c946f719fc3be05f.tar.gz
-rw-r--r--  0 0      0       65100  1  1  1970 app/libs//classmate-1.3.4.jar
-rw-r--r--  0 0      0     1133563  1  1  1970 app/libs//hibernate-validator-6.0.10.Final.jar
-rw-r--r--  0 0      0       66519  1  1  1970 app/libs//jackson-annotations-2.9.0.jar
-rw-r--r--  0 0      0      323848  1  1  1970 app/libs//jackson-core-2.9.6.jar
-rw-r--r--  0 0      0     1349339  1  1  1970 app/libs//jackson-databind-2.9.6.jar
-rw-r--r--  0 0      0       33395  1  1  1970 app/libs//jackson-datatype-jdk8-2.9.6.jar
-rw-r--r--  0 0      0       99987  1  1  1970 app/libs//jackson-datatype-jsr310-2.9.6.jar
-rw-r--r--  0 0      0        8645  1  1  1970 app/libs//jackson-module-parameter-names-2.9.6.jar
-rw-r--r--  0 0      0       26586  1  1  1970 app/libs//javax.annotation-api-1.3.2.jar
-rw-r--r--  0 0      0       66469  1  1  1970 app/libs//jboss-logging-3.3.2.Final.jar
-rw-r--r--  0 0      0        4596  1  1  1970 app/libs//jul-to-slf4j-1.7.25.jar
-rw-r--r--  0 0      0      255485  1  1  1970 app/libs//log4j-api-2.10.0.jar
-rw-r--r--  0 0      0       17519  1  1  1970 app/libs//log4j-to-slf4j-2.10.0.jar
-rw-r--r--  0 0      0      290339  1  1  1970 app/libs//logback-classic-1.2.3.jar
-rw-r--r--  0 0      0      471901  1  1  1970 app/libs//logback-core-1.2.3.jar
-rw-r--r--  0 0      0       41203  1  1  1970 app/libs//slf4j-api-1.7.25.jar
-rw-r--r--  0 0      0      297518  1  1  1970 app/libs//snakeyaml-1.19.jar
-rw-r--r--  0 0      0      366340  1  1  1970 app/libs//spring-aop-5.0.7.RELEASE.jar
-rw-r--r--  0 0      0      660545  1  1  1970 app/libs//spring-beans-5.0.7.RELEASE.jar
-rw-r--r--  0 0      0      930680  1  1  1970 app/libs//spring-boot-2.0.3.RELEASE.jar
-rw-r--r--  0 0      0     1162436  1  1  1970 app/libs//spring-boot-autoconfigure-2.0.3.RELEASE.jar
-rw-r--r--  0 0      0         592  1  1  1970 app/libs//spring-boot-starter-2.0.3.RELEASE.jar
-rw-r--r--  0 0      0         645  1  1  1970 app/libs//spring-boot-starter-json-2.0.3.RELEASE.jar
-rw-r--r--  0 0      0         613  1  1  1970 app/libs//spring-boot-starter-logging-2.0.3.RELEASE.jar
-rw-r--r--  0 0      0         591  1  1  1970 app/libs//spring-boot-starter-tomcat-2.0.3.RELEASE.jar
-rw-r--r--  0 0      0         588  1  1  1970 app/libs//spring-boot-starter-web-2.0.3.RELEASE.jar
-rw-r--r--  0 0      0     1090739  1  1  1970 app/libs//spring-context-5.0.7.RELEASE.jar
-rw-r--r--  0 0      0     1226075  1  1  1970 app/libs//spring-core-5.0.7.RELEASE.jar
-rw-r--r--  0 0      0      280032  1  1  1970 app/libs//spring-expression-5.0.7.RELEASE.jar
-rw-r--r--  0 0      0       21703  1  1  1970 app/libs//spring-jcl-5.0.7.RELEASE.jar
-rw-r--r--  0 0      0     1254656  1  1  1970 app/libs//spring-web-5.0.7.RELEASE.jar
-rw-r--r--  0 0      0      789866  1  1  1970 app/libs//spring-webmvc-5.0.7.RELEASE.jar
-rw-r--r--  0 0      0     3115994  1  1  1970 app/libs//tomcat-embed-core-8.5.31.jar
-rw-r--r--  0 0      0      240244  1  1  1970 app/libs//tomcat-embed-el-8.5.31.jar
-rw-r--r--  0 0      0      256776  1  1  1970 app/libs//tomcat-embed-websocket-8.5.31.jar
-rw-r--r--  0 0      0       93107  1  1  1970 app/libs//validation-api-2.0.1.Final.jar

Allow a container to be created each time you build

This can be achieved by using the gradle function with the gradle plugin and specifying the dependency for the task.

Change the version with guild.gradle so that it becomes another name.

version = '0.0.2-SNAPSHOT'

Build.

./gradlew build -x test
(Omission)
Containerizing application to Docker daemon as jib-test:0.0.2-SNAPSHOT...

Getting base image gcr.io/distroless/java...
Building dependencies layer...
Building resources layer...
Building classes layer...
Finalizing...
Loading to Docker daemon...

Container entrypoint set to [java, -cp, /app/libs/*:/app/resources/:/app/classes/, com.example.jibtest.DemoApplication]

Built image to Docker daemon as jib-test:0.0.2-SNAPSHOT

The projects so far are stored in GitHub as "Add-Gradle-Plugin".

Use a local private repository

Let's try the part that registers the created container in the repository.

Preparing a private repository

Use the Container for Private Registry published by docker.

$ docker run -d -p 5000:5000 --restart always --name registry registry:2

Make sure the private repository container is working.

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
8378d3fa853c        registry:2          "/entrypoint.sh /etc…"   2 minutes ago       Up 2 minutes        0.0.0.0:5000->5000/tcp   registry
Try manually selling the tag and pushing it to your local repository.

$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry 2 b2b03e9146e1 9 days ago 33.3MB graalvm latest 751a11aa3b93 3 weeks ago 985MB centos centos7 49f7960eb7e4 5 weeks ago 200MB jib-test 0.0.1-SNAPSHOT 2ce8c6f47c83 48 years ago 134MB jib-test 0.0.2-SNAPSHOT 2ce8c6f47c83 48 years ago 134MB

$ docker tag jib-test:0.0.1-SNAPSHOT localhost:5000/jib-test-0.0.1

$ docker push localhost:5000/jib-test-0.0.1 The push refers to repository [localhost:5000/jib-test-0.0.1] 2c5e48a8f567: Pushed 6ef8c795d7a5: Pushed 72bcd5740b92: Pushed 40930fb97dd9: Pushed 6189abe095d5: Pushed a9872a8d1d84: Pushed latest: digest: sha256:b61de386936e2a5726d91445c1af080c4a32762cd6745298f2872c0fb413b222 size: 1575 hirokis-MBP:jib-test hiroki$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE registry 2 b2b03e9146e1 9 days ago 33.3MB graalvm latest 751a11aa3b93 3 weeks ago 985MB centos centos7 49f7960eb7e4 5 weeks ago 200MB jib-test 0.0.1-SNAPSHOT 2ce8c6f47c83 48 years ago 134MB jib-test 0.0.2-SNAPSHOT 2ce8c6f47c83 48 years ago 134MB localhost:5000/jib-test-0.0.1 latest 2ce8c6f47c83 48 years ago 134MB

Change docker daemon settings

Enable insecure access to the private registry with the docker daemon.

On macOS, click the Docker icon in the menu bar at the top of the screen and select the "Daemon" tab from the "Preferences" menu. Check "Experimental features" and add "localhost: 5000" to Insecure registries. Press "Apply & Restart" and wait for the Docker daemon to restart.

docker_option.png

(Supplement) This entry uses macOS, but for Linux etc., [Around here] on StackOverflow (https://stackoverflow.com/questions/32808215/where-to-set-the-insecure-registry) -flag-on-mac-os) may be helpful.

Specify options

See Jib's gradle plugins page and under "allowInsecureRegistries" Specify the parameters. The default is false, so running the jib task with no options will result in an error. Set the parameter to true for the purpose of using the local registry for testing purposes. _ Please note that this is for testing purposes only and is not a production setting. _

jib {
  allowInsecureRegistries = true
}

Build a container

Try pushing to your local private repository with gradle's jib task.

warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible

Containerizing application to localhost:5000/jib-test-0.0.2...

Retrieving registry credentials for localhost:5000...
Getting base image gcr.io/distroless/java...
Building dependencies layer...
Building resources layer...
Building classes layer...
Finalizing...

Container entrypoint set to [java, -cp, /app/libs/*:/app/resources/:/app/classes/, com.example.jibtest.DemoApplication]

Make sure the container is stored

Check the contents of the private registry with the curl command. Contains jib-test-0.0.2.

$ curl -X GET http://localhost:5000/v2/_catalog
{"repositories":["jib-test-0.0.1","jib-test-0.0.2"]}

Try to move

Let's move the container registered in the private registry above.

$ docker run -p 8080:8080 -it localhost:5000/jib-test-0.0.2 

Check the operation in the same way as before in this entry.

$ curl http://localhost:8080/
Hello World!

The projects so far are stored in GitHub as "Add-Gradle-Plugin".

Summary

In this entry, we've seen how to easily containerize Java applications using Jib, a container or tool, and Jib's Gradle plugin. I launched a private repository and confirmed that I can register a container with Gradle's jib command.

At the time of writing this entry, Jib is under development, and there are some features that are on the roadmap but not realized, such as containerization of WAR files. Whether it can be applied or not depends on the circumstances of the project, but the work of containerization is It seems worth considering the application, as there are benefits to the simplicity.

Recommended Posts

Easily convert Java application to Docker container with Jib ~ Build with gradle and register in local repository
Easily Docker Java applications with Jib
I tried to build a Firebase application development environment with Docker in 2020
Build and test Java + Gradle applications with Wercker
Create a Java (Gradle) project with VS Code and develop it on a Docker container
How to build docker environment with Gradle for intelliJ
[2018 definitive edition] [Java 11 containerization] After downsizing the Spring Boot application to the limit, build it with Jib and push it to ECR
[Java] [Maven] Template of pom.xml to register 3rd party jar file in local repository
How to convert A to a and a to A using AND and OR in Java
How to build a Jenkins server with a Docker container on CentOS 7 of VirtualBox and access the Jenkins server from a local PC
Build WordPress environment with Docker (Local) and AWS (Production)
What happened in "Java 8 to Java 11" and how to build an environment
Build a Node-RED environment with Docker to move and understand
How to develop and register a Sota app in Java
Java: Start WAS with Docker and deploy your own application
Write DiscordBot to Spreadsheets Write in Ruby and run with Docker
Build DynamoDB local with Docker
[Android] Convert Map to JSON using GSON in Kotlin and Java
How to encrypt and decrypt with RSA public key in Java
Build Couchbase local environment with Docker
Build a Java project with Gradle
Build a web application development environment that uses Java, MySQL, and Redis with Docker CE for Windows
Hello world in Java and Gradle
Build WebRTC Janus with Docker container
Spring Boot gradle build with Docker
Build debug environment on container --Build local development environment for Rails tutorial with Docker-
Creating a project (and GitHub repository) using Java and Gradle in IntelliJ IDEA
Starting with installing Docker on EC2 and running Yellowfin in a container
How to migrate a web application created in a local docker environment to AWS
How to start a Docker container with a volume mounted in a batch file
Let's create a TODO application in Java 2 I want to create a template with Spring Initializr and make a Hello world
Kind @ Mac in Docker and vctl container
Build Spring Boot + Docker image in Gradle
CICS-Run Java applications-(3) Build management with Gradle
Convert SVG files to PNG files in Java
Docker container build fails to install php-radis
Java to C and C to Java in Android Studio
Convert JSON to TSV and TSV to JSON with Ruby
How to build Rails 6 environment with Docker
Test, build, and push your Docker image to GitHub Container Registry using GitHub Actions
Build Apache and Tomcat environment with Docker. By the way, Maven & Java cooperation
I tried to convert JavaBean and XML with Jackson formatter XML in this era