How to convert a Spring-Boot web service into a Docker image?
I want to access my website from a Docker container but I can't. The steps I am trying to implement are as follows. After all the steps I can't access the http://localhost:8080/index
page, where did I make a mistake?
The Spring-Boot project name is demo
. Parts of my code:
package com.qwerty.demo.rest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class FunRestService {
@GetMapping("/index")
public String setIndex() {
return "HELLO WORLD!";
}
}
My dockerfile
code:
FROM openjdk:8
COPY . /usr/var/www/MYPROJECT
WORKDIR /usr/var/www/MYPROJECT
EXPOSE 8080
CMD ./mvnw spring-boot:run
I build the Spring-Boot project to myimage1
with this command.
docker build -t myimage1 .
Then, I create a new container from myimage1
with this command.
docker run --name mycontainer1 myimage1
And Maven downloads necessary files and starts my app for me. Last output:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.2.RELEASE)
2019-01-19 17:40:32.604 INFO 6 --- [ main] com.qwerty.demo.DemoApplication : Starting DemoApplication on 8086b6e010fb with PID 6 (/usr/var/www/MYPROJECT/target/classes started by root in /usr/var/www/MYPROJECT)
2019-01-19 17:40:32.613 INFO 6 --- [ main] com.qwerty.demo.DemoApplication : No active profile set, falling back to default profiles: default
2019-01-19 17:40:34.119 INFO 6 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-01-19 17:40:34.170 INFO 6 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-01-19 17:40:34.171 INFO 6 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.14]
2019-01-19 17:40:34.186 INFO 6 --- [ main] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib]
2019-01-19 17:40:34.288 INFO 6 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-01-19 17:40:34.289 INFO 6 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1559 ms
2019-01-19 17:40:34.602 INFO 6 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-01-19 17:40:34.882 INFO 6 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''2019-01-19 17:40:34.888 INFO 6 --- [ main] com.qwerty.demo.DemoApplication : Started DemoApplication in 3.176 seconds (JVM running for 69.839)
What should we do to convert one such Spring-Boot project (using a Dockerfile
) into an image? How can I access my web page?
Solution 1:
When you run a Docker container, all the ports, which any application happen to listen on within it, are not published by default.
In order to publish a port, you need to specify it while running the container using your image. For all the details on how to do it, you can check the "EXPOSE" section in the documentation of docker run command: https://docs.docker.com/engine/reference/run/
Shortly speaking, you want to add another option while running your container:
docker run --name mycontainer1 -p 8080:8080 myimage1
I'm not sure if you wanted to achieve this by adding
EXPOSE 8080
in your Dockerfile. Actually, this does not mean that the port will be exposed when the image is used to run a container. As you might find in Dockerfile reference:
The EXPOSE instruction does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published. To actually publish the port when running the container, use the -p flag on docker run to publish and map one or more ports, or the -P flag to publish all exposed ports and map them to high-order ports.