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.
The middleware and libraries use the following.
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
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.
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 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'
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);
}
}
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!
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.
$ 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
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".
Let's try the part that registers the created container in the 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
$ 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
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.
(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.
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
}
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]
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"]}
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".
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