Build Spring Boot + Docker image in Gradle

TL;DR

--Try to create a Docker image using Gradle --Build SpringBoot in jar format and create a Docker image including java + jar file --Basically, just try according to the Spring Official documentation.

Execution environment construction

environment

The following verification items are implemented on macOS The version of the library etc. used is as follows

Create a project

Select a project using SPRING INITIALIZR

Try to build with Gradle as Generate a "Gradle Project" and include the web in Dependencies

screenshot_spring_init.png

Unzip the completed demo.zip, build and run the project with gradle

$ unzip demo.jar
$ cd demo
$ ./gradlew build
$ java -jar build/libs/demo-0.0.1-SNAPSHOT.jar
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.8.RELEASE)

2017-11-10 10:04:09.107  INFO 41308 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on mac0137.local.furyu.jp with PID 41308 (/Users/moriokanaoki/Downloads/demo/build/libs/demo-0.0.1-SNAPSHOT.jar started by moriokanaoki in /Users/moriokanaoki/Downloads/demo)
2017-11-10 10:04:09.111  INFO 41308 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2017-11-10 10:04:09.193  INFO 41308 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@45283ce2: startup date [Fri Nov 10 10:04:09 JST 2017]; root of context hierarchy
2017-11-10 10:04:10.577  INFO 41308 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2017-11-10 10:04:10.591  INFO 41308 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2017-11-10 10:04:10.592  INFO 41308 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.23
2017-11-10 10:04:10.676  INFO 41308 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-11-10 10:04:10.676  INFO 41308 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1486 ms
2017-11-10 10:04:10.804  INFO 41308 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2017-11-10 10:04:10.809  INFO 41308 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-11-10 10:04:10.810  INFO 41308 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-11-10 10:04:10.810  INFO 41308 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-11-10 10:04:10.810  INFO 41308 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2017-11-10 10:04:11.191  INFO 41308 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@45283ce2: startup date [Fri Nov 10 10:04:09 JST 2017]; root of context hierarchy
2017-11-10 10:04:11.299  INFO 41308 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-11-10 10:04:11.300  INFO 41308 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2017-11-10 10:04:11.332  INFO 41308 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-11-10 10:04:11.333  INFO 41308 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-11-10 10:04:11.372  INFO 41308 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
2017-11-10 10:04:11.509  INFO 41308 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2017-11-10 10:04:11.578  INFO 41308 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2017-11-10 10:04:11.583  INFO 41308 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 2.98 seconds (JVM running for 3.412)

It's working, but it's hard to understand, so I'll try to output about Hello World.

src/main/java/com/example/demo/DemoApplication.java


package com.example.demo;

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

@SpringBootApplication
@RestController
public class DemoApplication {

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

        @RequestMapping(value = "/")
        String sayHello() {
                return "Hello World!";
        }
}

If you start demo.jar again and access port 8080 of localhost, you should see" Hello World! ".

Prepare a Dockerfile

In order to create a Docker image that executes the above java -jar, prepare a Dockerfile directly under the project. Creation of demo.jar etc. is linked with build.gradle change described later

Dockerfile


FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD target/demo.jar app.jar
ENV JAVA_OPTS=""
ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar

Added gradle-docker plugin

Modify build.gradle to generate Docker image in Gradle.

build.gradle


buildscript {
	ext {
		springBootVersion = '1.5.8.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
		classpath "se.transmode.gradle:gradle-docker:1.2"
	}
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'docker'

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

repositories {
	mavenCentral()
}

dependencies {
	compile('org.springframework.boot:spring-boot-starter-web')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}

jar {
    baseName = 'demo'
    archiveName = "${baseName}.jar"
}

task buildDocker(type: Docker, dependsOn: build) {
    applicationName = jar.baseName
    dockerfile = file('Dockerfile')
    doFirst {
        copy {
            from jar
            into "${stageDir}/target"
        }
    }
}

Build

Let's build it right away. Don't forget to start Docker on macOS here

$ ./gradlew build buildDocker
Starting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details
:compileJava
:processResources UP-TO-DATE
:classes
:findMainClass
:jar
:bootRepackage
:assemble
:compileTestJava
:processTestResources NO-SOURCE
:testClasses
:test
2017-11-10 22:27:45.286  INFO 43631 --- [       Thread-5] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@697f2062: startup date [Fri Nov 10 22:27:43 JST 2017]; root of context hierarchy
:check
:build
:buildDocker
Sending build context to Docker daemon   14.5MB
Step 1/5 : FROM openjdk:8-jdk-alpine
 ---> xxxxxxxxxxxx
Step 2/5 : VOLUME /tmp
 ---> Using cache
 ---> xxxxxxxxxxxx
Step 3/5 : ADD target/demo.jar app.jar
 ---> xxxxxxxxxxxx
Removing intermediate container xxxxxxxxxxxx
Step 4/5 : ENV JAVA_OPTS ""
 ---> Running in xxxxxxxxxxxx
 ---> xxxxxxxxxxxx
Removing intermediate container xxxxxxxxxxxx
Step 5/5 : ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar
 ---> Running in xxxxxxxxxxxx
 ---> xxxxxxxxxxx
Removing intermediate container xxxxxxxxxxxx
Successfully built xxxxxxxxxxxx
Successfully tagged com.example/demo:0.0.1-SNAPSHOT

BUILD SUCCESSFUL

$ docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             SIZE
com.example/demo                0.0.1-SNAPSHOT      xxxxxxxxxxxx        1 minutes ago       116MB

It seems that it was completed successfully

Launching Spring Boot with Docker

$ docker run -p 8080:8080 -d com.example/demo:0.0.1-SNAPSHOT
xxxxxxxxxxxxxxxcf54172bd224611a7a184d3d454ee06a289143c191041706
$ docker ps
CONTAINER ID        IMAGE                             COMMAND                  CREATED             STATUS              PORTS                    NAMES
xxxxxxxxxxxx        com.example/demo:0.0.1-SNAPSHOT   "/bin/sh -c 'exec ..."   36 seconds ago      Up 10 seconds       0.0.0.0:8080->8080/tcp   friendly_murdock

It seems to be running. When I access port 8080 on localhost, "Hello World!" Is displayed again.

Summary

I haven't adjusted the image name or tag this time. I also loosely deployed Docker images locally.

I was able to create a Docker image in the same way as creating a jar file with Gradle Since the adoption of Java 9 and OpenJDK is expected to progress in the future, there may be a future where Docker seems to be the first choice for running Spring Boot.

References

Recommended Posts

Build Spring Boot + Docker image in Gradle
Spring Boot gradle build with Docker
Spring Boot 2 multi-project in Gradle
Implement Spring Boot application in Gradle
How to make Spring Boot Docker Image smaller
Build Java x Spring x VSCode x Gradle on Docker (1)
Build Spring Boot project by environment with Gradle
Java tips-Create a Spring Boot project in Gradle
View the Gradle task in the Spring Boot project
Install yarn in docker image
Spring Boot starting with Docker
Docker × Spring Boot environment construction
Major changes in Spring Boot 1.5
NoHttpResponseException in Spring Boot + WireMock
Database environment construction with Docker in Spring boot (IntellJ)
Spring Boot Hello World in Eclipse
Spring Boot application development in Eclipse
◆ Spring Boot + gradle environment construction memo
Write test code in Spring Boot
Implement REST API in Spring Boot
What is @Autowired in Spring boot?
Thymeleaf usage notes in Spring Boot
[Splunk] Build Splunk Enterprise (use docker image)
spring × docker
Image Spring Boot app using jib-maven-plugin and start it with Docker
Launch (old) Spring Boot project in IntelliJ
Static file access priority in Spring boot
Output Spring Boot log in json format
Local file download memorandum in Spring Boot
Create Java Spring Boot project in IntelliJ
Loosen Thymeleaf syntax checking in Spring Boot
[Practice! ] Display Hello World in Spring Boot
Spring Boot + Docker Java development environment construction
Use DynamoDB query method in Spring Boot
[Docker] Start container, start bash in container, delete image
Spring Boot, Doma2, Gradle initial setting summary
DI SessionScope Bean in Spring Boot 2 Filter
(IntelliJ + gradle) Hello World with Spring Boot
Add spring boot and gradle to eclipse
Change session timeout time in Spring Boot
Spring Boot environment construction with Docker (January 2021 version)
Create a website with Spring Boot + Gradle (jdk1.8.x)
SameSite cookie in Spring Boot (Spring Web MVC + Tomcat)
Test controller with Mock MVC in Spring Boot
Asynchronous processing with regular execution in Spring Boot
Run Scala applications with Spring Boot through Gradle
Output request and response log in Spring Boot
Challenge Spring Boot
Use Servlet filter in Spring Boot [Spring Boot 1.x, 2.x compatible]
How to add a classpath in Spring Boot
Docker in LXD
Spring Boot Form
How to bind to property file in Spring Boot
I wanted to gradle spring boot with multi-project
Spring Boot Memorandum
gae + spring boot
Annotations used in Spring Boot task management tool
Create a Spring Boot development environment with docker
Java development environment construction (Mac + Pleiades All in One Eclipse 4.7 + Spring Boot + Gradle (Buildship))
Cache Gradle dependent files to speed up docker build
Specify the encoding of static resources in Spring Boot