# 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:

```plaintext
git clone https://github.com/your-repository/BankApp.git
cd BankApp
```

You should see the following structure in the project:

```plaintext
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:

```plaintext
./mvnw clean install
```

or if the `mvnw` script isn’t available, use:

```plaintext
mvn clean install
```

This will:

1. **Download dependencies** specified in `pom.xml`.
    
2. **Compile the code** and run any tests.
    
3. **Package** the application as a `.jar` file in the `target/` 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:

```plaintext
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`](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:

```plaintext
# 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:

```plaintext
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:

```plaintext
docker run -p 8080:81 bankapp:latest
```

* The `-p 81:8080` option maps port `81` on your machine to port `8080` in the container.
    
* Your application should now be accessible at [`http://localhost:81`](http://localhost:8080).
    

---

## Step 5: Verify the Application

To verify that everything is working:

1. Open a web browser or use a tool like `curl` to access [`http://localhost:81`](http://localhost:8080).
    
2. Check the logs in your terminal to ensure there are no errors.
    

---

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731484474455/3d8ff7f4-6d71-4ec9-a409-f3d9ac02d2c5.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1731484485530/29998c42-6574-40bb-bebb-6715832bd2ac.png align="center")

## Recap

Here’s what we covered in this guide:

1. **Manual Build and Run**: Built and ran the application locally using Maven.
    
2. **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.
