How to Run a Maven Project Locally and with Docker Using a Multi-Stage Dockerfile
If you're working with Java applications, Maven is a popular choice for managing dependencies and automating the build process. Once you have a working application, you may want to containerize it using Docker, which can make deploying your app more manageable and portable. This guide will walk you through running a Maven application manually and then show you how to package it with Docker using a multi-stage Dockerfile for an optimized final image.
Prerequisites
Before starting, ensure that you have the following installed:
Java Development Kit (JDK): Make sure it’s compatible with the project.
Apache Maven: Verify it’s installed by running
mvn -v
.Docker: To containerize and run the application in a container.
Step 1: Clone and Set Up the Project
Since you've already cloned the project, navigate to your project directory. Here’s a quick reminder:
git clone https://github.com/your-repository/BankApp.git
cd BankApp
You should see the following structure in the project:
BankApp/
├── pom.xml
└── src/
├── main/
└── test/
pom.xml
contains your project’s dependencies and build instructions, while the src/
folder contains the Java source code.
Step 2: Run the Application Manually with Maven
Let's start by building and running the application manually.
Build the Application
In your project directory, run:
./mvnw clean install
or if the mvnw
script isn’t available, use:
mvn clean install
This will:
Download dependencies specified in
pom.xml
.Compile the code and run any tests.
Package the application as a
.jar
file in thetarget/
directory.
After a successful build, you should see something like BankApp-0.0.1-SNAPSHOT.jar
in the target/
folder.
Run the Application
To start the application, use:
java -jar target/BankApp-0.0.1-SNAPSHOT.jar
The application should now be running, and you can access it (if it’s a web app) by navigating to http://localhost:8080
.
Step 3: Containerize the Application with Docker
Now, let’s make the application easier to deploy by containerizing it with Docker. A multi-stage Dockerfile will help us build and run the application more efficiently.
What is a Multi-Stage Dockerfile?
A multi-stage Dockerfile separates the build and runtime environments. We use a Maven-based image to compile the project, then copy only the compiled .jar
file to a minimal Java runtime image, resulting in a smaller, more efficient Docker image.
Writing the Multi-Stage Dockerfile
In the project’s root directory, create a file named Dockerfile
and add the following contents:
# Stage 1: Build the application
FROM maven:3.8.7-openjdk-17 AS build
# Set the working directory in the container
WORKDIR /app
# Copy the pom.xml and source code
COPY pom.xml .
COPY src ./src
# Build the application
RUN mvn clean install -DskipTests
# Stage 2: Run the application
FROM openjdk:17-jdk-alpine
# Set the working directory
WORKDIR /app
# Copy the jar file from the build stage
COPY --from=build /app/target/BankApp-0.0.1-SNAPSHOT.jar app.jar
# Expose the port (update if the app uses a different port)
EXPOSE 8080
# Command to run the application
CMD ["java", "-jar", "app.jar"]
Explanation of the Dockerfile
Stage 1 (Build Stage):
We use
maven:3.8.7-openjdk-17
as the base image.The source code and
pom.xml
are copied into the container.The
mvn clean install -DskipTests
command compiles the application and skips tests for faster builds.The compiled
.jar
file is created in/app/target
.
Stage 2 (Runtime Stage):
We use a smaller image,
openjdk:17-jdk-alpine
, to run the app.The
.jar
file from the build stage is copied over.The container exposes port
8080
(adjust as needed).The
CMD
instruction starts the app.
Step 4: Build and Run the Docker Image
Now that the Dockerfile is ready, let’s build and run the Docker image.
Build the Docker Image
Run the following command to build the Docker image:
docker build -t bankapp:latest .
The -t bankapp:latest
option tags the image as bankapp
with the latest
tag.
Run the Docker Container
Start a container from the Docker image:
docker run -p 8080:81 bankapp:latest
The
-p 81:8080
option maps port81
on your machine to port8080
in the container.Your application should now be accessible at
http://localhost:81
.
Step 5: Verify the Application
To verify that everything is working:
Open a web browser or use a tool like
curl
to accesshttp://localhost:81
.Check the logs in your terminal to ensure there are no errors.
Recap
Here’s what we covered in this guide:
Manual Build and Run: Built and ran the application locally using Maven.
Containerized Build and Run: Used a multi-stage Dockerfile to build a Docker image and run it in a container.
By containerizing the application, you’ve made it easier to deploy across environments consistently, without the need for a specific JDK or Maven installation. The multi-stage Dockerfile ensures the final image is optimized for size and performance, containing only what’s needed to run the application.
Subscribe to my newsletter
Read articles from Muhammad Hassan directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Muhammad Hassan
Muhammad Hassan
Hey there! I'm currently working as an Associate DevOps Engineer, and I'm diving into popular DevOps tools like Azure Devops,Linux, Docker, Kubernetes,Terraform and Ansible. I'm also on the learning track with AWS certifications to amp up my cloud game. If you're into tech collaborations and exploring new horizons, let's connect!