Dockerizing Spring Boot War
In this blog post, I will show you how to create Docker images of Spring Boot Applications which are deployed as war files in Tomcat.
In one of previous blog post, I have covered how to dockerize the Spring Boot Jar files.
Now Let’s see , How to dockerize the Spring Boot war file.
1. Create Sample Spring Boot application
Head over to start.spring.io and create sample application and select war as packaging.
For demonstration purpose, I have created sample controller which responds with “Hello World” when the path is /welcome/hello
If you have existing Spring Boot application which deployed as Jar file, You can convert to package as war file. You can find step by step guide here.
Run following command to create war file
mvn clean package
Code language: Java (java)
2. Writing Dockerfile
Since Spring Boot war file needs to be deployed in webserver, we will take Tomcat as base image for Docker image.
The default Tomcat environment in the image is:
CATALINA_BASE: /usr/local/tomcat
CATALINA_HOME: /usr/local/tomcat
CATALINA_TMPDIR: /usr/local/tomcat/temp
JRE_HOME: /usr
CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.ja
Code language: Java (java)
To deploy our application, we need to copy our war file to /usr/local/tomcat/webapps folder
FROM docker.io/tomcat:9.0.68-jdk17
COPY /target/*.war /usr/local/tomcat/webapps/samplewarapp.war
RUN addgroup springboot && adduser tomcat
RUN usermod -G springboot tomcat
RUN chown -R tomcat /usr/local/tomcat
USER tomcat
EXPOSE 8080
Code language: Dockerfile (dockerfile)
Inside container default user will be root,it is not best practice to run the application with root user so I am running application under “tomcat” user
In above Docker file, we are copying our war file to samplewarapp file inside Tomcat webapps folder.
So the application context will be /samplewarapp
Building docker image
docker build . -f ./Dockerfile.multistage -t springboot-war-docker
Code language: Java (java)
Running the docker container
docker run -p 8080:8080 springboot-war-docker
Code language: Java (java)
When you enter following address in the browser, you should see “hello World” on the browser.
http://localhost:8080/samplewarapp/welcome/hello
Multistage Dockerfile
You can also use multistage docker file to deploy the war file.
In multistage file, instead of depending on tomcat to expand the war file, we manually extract and copy the project files to webapps folder.
FROM docker.io/tomcat:9.0.68-jdk17 as stage1
ARG WAR_FILE=target/*.war
RUN mkdir -p /app/samplewarapp
COPY ${WAR_FILE} /app/samplewarapp/samplewarapp.war
WORKDIR /app/samplewarapp
RUN jar -xf samplewarapp.war && rm samplewarapp.war
FROM docker.io/tomcat:9.0.68-jdk17
ARG PROJECT_DIR=app
COPY --from=stage1 ${PROJECT_DIR} /usr/local/tomcat/webapps/
RUN addgroup springboot && adduser tomcat
RUN usermod -G springboot tomcat
RUN chown -R tomcat /usr/local/tomcat
USER tomcat
EXPOSE 8080
Code language: Java (java)
Following dockerfile is another version of multi stage docker file.
In this file we are copying individual folders after extracting the war file.
FROM docker.io/tomcat:9.0.68-jdk17 as stage1
ARG WAR_FILE=target/*.war
RUN mkdir -p /app/samplewarapp
COPY ${WAR_FILE} /app/samplewarapp/samplewarapp.war
WORKDIR /app/samplewarapp
RUN jar -xf samplewarapp.war
FROM docker.io/tomcat:9.0.68-jdk17
RUN mkdir /usr/local/tomcat/webapps/samplewarapp
ARG PROJECT_DIR=app/samplewarapp
COPY --from=stage1 ${PROJECT_DIR}/META-INF /usr/local/tomcat/webapps/samplewarapp/META-INF
COPY --from=stage1 ${PROJECT_DIR}/org /usr/local/tomcat/webapps/samplewarapp/org
COPY --from=stage1 ${PROJECT_DIR}/WEB-INF /usr/local/tomcat/webapps/samplewarapp/WEB-INF
RUN addgroup springboot && adduser tomcat
RUN usermod -G springboot tomcat
RUN chown -R tomcat /usr/local/tomcat
USER tomcat
EXPOSE 8080
Code language: Java (java)
Building docker image
docker build . -f ./Dockerfile.multistage -t springboot-war-docker
Code language: Java (java)
Running the docker container
docker run -p 8080:8080 springboot-war-docker
Code language: Java (java)
Testing war file in Local Development.
When you are developing application, if you want to test your war application in docker container
you can use docker compose file to simplify the testing process instead of repeating docker commands to to create image and run the container.
We use the volume concept to copy the war file inside container.
volumes tag copies the war file to specified path inside container.
You can use following docker compose file
version: '3'
services:
sb-war-app:
image: 'docker.io/tomcat:9.0.68-jdk17'
ports:
- 8080:8080
volumes:
- ./target/sb-war-docker-0.0.1-SNAPSHOT.war:/usr/local/tomcat/webapps/samplewarapp.war
Code language: Java (java)
If you have already built the image of your application, you can also use that image instead of tomcat image.
version: '3'
services:
sb-war-app:
image: 'sb-war-docker'
ports:
- 8080:8080
volumes:
- ./target/sb-war-docker-0.0.1-SNAPSHOT.war:/usr/local/tomcat/webapps/samplewarapp.war
Code language: Java (java)
First build your applications
mvn clean package
Code language: Java (java)
Now , you can bring-up the container with your application deployed with below command.
docker-compose up
Code language: Java (java)
You can stop the container with following command
docker-compose down
Code language: Java (java)