This blog post is about the fundamentals of Java Maven. The focus is on the manually steps, from the creation of a project, to the package of the application. I also provide a multistage Dockerfile, that combines the these steps.
Java Overview #
Java Language #
- Object-oriented programming language that can run on many operating systems without modification.
Core Components:
- 
Java Virtual Machine (JVM): Executes Java programs, providing a platform-independent runtime. 
- 
Java Development Kit (JDK): A toolkit for developing Java applications (includes the compiler, libraries, and JVM). 
- 
Java Runtime Environment (JRE): A subset of the JDK that includes only what’s needed to run Java applications. 
OpenJDK #
- 
Open-source version of Java SE (Java Platform Standard Edition) 
- 
Alternative to the official Java implementation by Oracle, which has a more restrictive license. 
OpenJDK Components:
- 
Java Developer Kit (JDK): Includes the Javac compiler, used for compiling Java into bytecode. Necessary to create stand-alone Java executables. 
- 
Java Runtime Environment (JRE): Executes Java code and compiled Java bytecode. 
- 
To only run Java programs, JRE can be used without the JDK. 
Maven #
- 
Build automation tool and dependency management tool for Java projects. Simplifies and standardizes the build process of Java applications. 
- 
Compiles source code into executable code like .classor.jarfiles
- 
Maven automatically downloads and manages external libraries / dependencies from a pom.xmlconfiguration file, that are needed for the project.
- 
Provides a standardized project structure (e.g., where to place source code, resources and tests). 
 
Java Setup (Linux Server) #
Java Development Kit (JDK) Installation #
# Find the latest OpenJDK version
https://jdk.java.net/
# Install OpenJDK version 17
sudo apt install openjdk-17-jdk -y
# Optional, install only the JRE component of OpenJDK
sudo apt install openjdk-17-jre -y
Verify Java installation #
# Verify installation / check version
java -version
# Shell output:
openjdk version "17.0.13" 2024-10-15
OpenJDK Runtime Environment (build 17.0.13+11-Ubuntu-2ubuntu124.04)
OpenJDK 64-Bit Server VM (build 17.0.13+11-Ubuntu-2ubuntu124.04, mixed mode, sharing)
# Verify Java compiler / check version (Only with JDK installation, not with JRE only)
javac -version
# Shell output:
javac 17.0.13
Set Java Environment Variables #
Current user:
# Append .bashrc of the current user
echo -e 'export JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java))))' >> ~/.bashrc
echo -e 'export PATH=$PATH:$JAVA_HOME/bin' >> ~/.bashrc
# Apply changes
source ~/.bashrc
# Verify environemtn variables
echo $JAVA_HOME
echo $PATH
# Shell output:
/usr/lib/jvm/java-17-openjdk-amd64
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/lib/jvm/java-17-openjdk-amd64/bin
 
Java Maven Setup (Linux Server) #
- Java Development Kit (JDK) must be installed
Maven Installation #
# Install Maven
sudo apt install maven -y
Verify Installation #
# Verify the Installation
mvn -version
# Shell output:
Apache Maven 3.8.7
Maven home: /usr/share/maven
Java version: 17.0.13, vendor: Ubuntu, runtime: /usr/lib/jvm/java-17-openjdk-amd64
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "6.8.0-49-generic", arch: "amd64", family: "unix"
Maven Commands Overview #
# Clean up the "target/" directory
mvn clean
# Verify the "pom.xml" is correct
mvn validate
# Compile the source code
mvn compile
# Run unit tests
mvn test
# Package the compiled code into a JAR or WAR
mvn package
 
Java Example Application #
Create Application #
# Create a simple hello world application
vi HelloWorld.java
// Define public class named 'HelloWorld'. The class name must match the file name (HelloWorld.java).
public class HelloWorld {
    // Entry point of the Java application
    public static void main(String[] args) {
        // Standard output stream, print sting to the console
        System.out.println("Hi there, Java test");
    }
}
Run Application Using the (OpenJDK) JRE #
Use the previously installed(OpenJDK) JRE to run the Java code:
# Run a Java Application
java HelloWorld.java
# Shell output:
Hi there, Java test
Compile & Run Application Using the JDK / JRE #
Compile Java code into Java bytecode:
# Compile with Javac compiler
javac HelloWorld.java
# Run the compiled class with JRE
java HelloWorld
# Shell output:
Hi there, Java test
 
Java Maven Example Application #
Create Project #
# Create a new Maven project: Standard Maven project structure
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=HelloMaven-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5 -DinteractiveMode=false
- 
DgroupIdUnique identifier for the project, typically your domain name in reverse
- 
-DartifactIdThe name of your project, for exampleHelloMaven-app
Verify Project Structure #
# Navigate into the project
cd HelloMaven-app
HelloMaven-app
├── pom.xml  # Maven configuration file
└── src
    ├── main
    │   └── java
    │       └── com
    │           └── mycompany
    │               └── app
    │                   └── App.java  # Main Java file
    └── test
        └── java
            └── com
                └── mycompany
                    └── app
                        └── AppTest.java  # Test file
- pom.xmlCore of a project configuration in Maven.
Project Files #
Main Java File #
# Open the main Java file "App.java"
vi src/main/java/com/mycompany/app/App.java
// Define the package name for this class: A package is a namespace that organizes related classes and interfaces
package com.mycompany.app;
// Import the DateTime class from the Joda-Time library
import org.joda.time.DateTime;
// Define a public class named "App"
public class App {
    // Print some text
    public static void main(String[] args) {
        System.out.println("Hello, from Maven. Time:");
        // Use Joda-Time to get and print the current date and time
        DateTime currentTime = new DateTime();
        System.out.println(currentTime.toString("yyyy-MM-dd HH:mm:ss"));
    }
}
Add Dependencies to pom.xml #
Add the Joda and Junit test dependencies to pom.xml:
# Open "pom.xml"
vi pom.xml
The original “dependency” configuration looks like this:
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.junit</groupId>
        <artifactId>junit-bom</artifactId>
        <version>5.11.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- Optionally: parameterized tests support -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-params</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
Add the Joda and Junit test dependencies:
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.junit</groupId>
        <artifactId>junit-bom</artifactId>
        <version>5.11.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <scope>test</scope>
    </dependency>
    <!-- Optionally: parameterized tests support -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-params</artifactId>
      <scope>test</scope>
    </dependency>
  # Add Joda & Junit test dependency 
    <!-- Joda-Time dependency -->
    <dependency>
      <groupId>joda-time</groupId>
      <artifactId>joda-time</artifactId>
      <version>2.10.14</version>
    </dependency>
    <!-- Junit dependency -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
Add Plugins to pom.xml #
- 
The default behavior of Maven does not include dependencies in the packaged JAR file (thin JAR). 
- 
Add the maven-assembly-plugintopom.xmlbundle the dependencies into the final JAR, creating a fat JAR that can run without needing external dependencies.
- 
This plugin simplifies deployment by producing a standalone, self-contained JAR file 
# Open "pom.xml"
vi pom.xml
The original “plugins” sections looks like this:
  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.4.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.3.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.13.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>3.3.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.4.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>3.1.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>3.1.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.12.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.6.1</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
Add the maven-assembly-plugin:
  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.4.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.3.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.13.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>3.3.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.4.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>3.1.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>3.1.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.12.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.6.1</version>
        </plugin>
        <!-- Add maven-assembly-plugin -->
        <plugin>
          <artifactId>maven-assembly-plugin</artifactId>
          <configuration>
            <archive>
              <manifest>
                <mainClass>com.mycompany.app.App</mainClass>
              </manifest>
            </archive>
            <descriptorRefs>
              <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
Adapt Unit Test #
# Adopt the Test
vi src/test/java/com/mycompany/app/AppTest.java
package com.mycompany.app;
import static org.junit.Assert.assertTrue;
import org.joda.time.DateTime;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
public class AppTest {
    @Test
    public void testMainOutput() {
        // Capture the console output
        ByteArrayOutputStream outContent = new ByteArrayOutputStream();
        System.setOut(new PrintStream(outContent));
        // Run the main method
        App.main(new String[]{});
        // Verify the output contains the greeting
        String output = outContent.toString();
        assertTrue("Output should contain the greeting", output.contains("Hello, from Maven. Time:"));
        // Verify the output contains a correctly formatted timestamp
        DateTime now = new DateTime();
        String expectedDate = now.toString("yyyy-MM-dd");
        assertTrue("Output should contain the current date", output.contains(expectedDate));
        // Reset the console output
        System.setOut(System.out);
    }
}
Build the Example project #
Run the Unit Test #
# Run the test
mvn test
# Shell output:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< com.mycompany.app:HelloMaven-app >------------------
[INFO] Building HelloMaven-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.3.1:resources (default-resources) @ HelloMaven-app ---
[INFO] skip non existing resourceDirectory /home/ubuntu/HelloMaven-app/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.13.0:compile (default-compile) @ HelloMaven-app ---
[INFO] Recompiling the module because of changed source code.
[INFO] Compiling 1 source file with javac [debug release 17] to target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.3.1:testResources (default-testResources) @ HelloMaven-app ---
[INFO] skip non existing resourceDirectory /home/ubuntu/HelloMaven-app/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.13.0:testCompile (default-testCompile) @ HelloMaven-app ---
[INFO] Recompiling the module because of changed dependency.
[INFO] Compiling 1 source file with javac [debug release 17] to target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:3.3.0:test (default-test) @ HelloMaven-app ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.022 s -- in com.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.815 s
[INFO] Finished at: 2024-11-26T21:10:24Z
[INFO] ------------------------------------------------------------------------
Run the Application Without Compiling #
Run the application without without manually compiling it (Direct Execution). Maven handles the build and execution in one step:
# Run the application
mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
# Shell output:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< com.mycompany.app:HelloMaven-app >------------------
[INFO] Building HelloMaven-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- exec-maven-plugin:3.5.0:java (default-cli) @ HelloMaven-app ---
Hello, from Maven. Time:
2024-11-26 21:20:03
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.214 s
[INFO] Finished at: 2024-11-26T21:20:03Z
[INFO] ------------------------------------------------------------------------
- 
mvn exec:javaRuns the exec plugin to execute the application.
- 
-Dexec.mainClass="com.mycompany.app.App"Specifies the fully qualified name of the main class.
Build the Application: Without Dependencies #
Compile the Application #
Compile the Java source code of the project into Java bytecode (.class files) that can be executed by the Java Virtual Machine (JVM):
- 
Maven checks the dependencies section in the pom.xmlfile and downloads any missing dependencies.
- 
Maven looks for .javafiles in thesrc/main/javadirectory and ompiles these files into.classfiles using the JDK’s Javac compiler.
- 
Compiled .classfiles are placed in thetarget/classesdirectory
# Compile the application
mvn compile
# Shell output:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< com.mycompany.app:HelloMaven-app >------------------
[INFO] Building HelloMaven-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.3.1:resources (default-resources) @ HelloMaven-app ---
[INFO] skip non existing resourceDirectory /home/ubuntu/HelloMaven-app/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.13.0:compile (default-compile) @ HelloMaven-app ---
[INFO] Nothing to compile - all classes are up to date.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.188 s
[INFO] Finished at: 2024-11-26T21:29:48Z
[INFO] ------------------------------------------------------------------------
Verify the file and folder structure:
HelloMaven-app
├── pom.xml  # Maven configuration file
├── src
│   ├── main
│   │   └── java
│   │       └── com
│   │           └── mycompany
│   │               └── app
│   │                   └── App.java  # Main Java file
│   └── test
│       └── java
│           └── com
│               └── mycompany
│                   └── app
│                       └── AppTest.java  # Test file
└── target
    ├── classes
    │   └── com
    │       └── mycompany
    │           └── app
    │               └── App.class  # Verify .class file
    ├── generated-sources
    │   └── annotations
    ├── generated-test-sources
    │   └── test-annotations
    ├── maven-status
    │   └── maven-compiler-plugin
    │       ├── compile
    │       │   └── default-compile
    │       │       ├── createdFiles.lst
    │       │       └── inputFiles.lst
    │       └── testCompile
    │           └── default-testCompile
    │               ├── createdFiles.lst
    │               └── inputFiles.lst
    ├── surefire-reports
    │   ├── com.mycompany.app.AppTest.txt
    │   └── TEST-com.mycompany.app.AppTest.xml
    └── test-classes
        └── com
            └── mycompany
                └── app
                    └── AppTest.class
Package the Application (Thin JAR) #
Create a distributable version of the application, such as a JAR (Java Archive) or WAR (Web Application Archive) file, which can be deployed or run:
- 
The format is defined by the <packaging>tag inpom.xml. By default, it’sJAR.
- 
Ensures the pom.xmlfile is valid and that all dependencies are resolved.
- 
If not already done, Maven compiles the source files into bytecode and places them in the target/classesdirectory.
- 
If tests are defined in the src/test/javadirectory, Maven runs them.
- 
The packaged file, for example HelloMaven-app-1.0-SNAPSHOT.jaris placed in thetarget/directory.
#  Package the application
mvn package
# Shell output:
...
[INFO] Building jar: /home/ubuntu/HelloMaven-app/target/HelloMaven-app-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.019 s
[INFO] Finished at: 2024-11-26T21:56:06Z
[INFO] ------------------------------------------------------------------------
Build the Application: With Dependencies #
Compile / Build the Application (Fat JAR) #
# Build a standalone JAR file
mvn clean compile assembly:single
- 
cleanDeletes any existing compiled files and build artifacts from the target directory to ensure a fresh build.
- 
compileCompiles the Java source code in thesrc/main/javadirectory into.classfiles and places them in thetarget/classesdirectory.
- 
assembly:singleInvokes themaven-assembly-pluginto create a fat JAR that includes the compiled application code and all required dependencies bundled together.
- 
The resulting JAR is placed in the targetdirectory:HelloMaven-app-1.0-SNAPSHOT-jar-with-dependencies.jar
Run the Packaged Application #
# Run the resulting JAR file
java -jar target/HelloMaven-app-1.0-SNAPSHOT-jar-with-dependencies.jar
# Shell output:
Hello, from Maven. Time:
2024-11-27 09:56:15
Containerize the Packaged Application #
Thin Jar #
- 
By default, Maven packages only the application’s compiled code in the JAR (thin JAR). 
- 
Required dependencies like joda-timeare not bundled inside the JAR and must be provided separately.
- 
The following example copies the dependencies into the container 
Generate the Dependencies #
# Use Maven to copy all runtime dependencies to a directory
mvn dependency:copy-dependencies -DoutputDirectory=target/dependency
Dockerfile #
# Create a Dockerfile
vi Dockerfile
# Use an official OpenJDK runtime as a base image
FROM openjdk:17-jdk-slim
# Set the working directory
WORKDIR /app
# Copy the application's thin JAR to the image
COPY target/HelloMaven-app-1.0-SNAPSHOT.jar app.jar
# Copy all dependencies to the image
COPY target/dependency /app/dependency
# Command to run the application
CMD ["java", "-cp", "app.jar:/app/dependency/*", "com.mycompany.app.App"]
Build Container Image #
# Build the container image
docker build -t hello-maven-app .
Verify the Container Image #
# List images
docker images
# Shell output:
REPOSITORY        TAG       IMAGE ID       CREATED         SIZE
hello-maven-app   latest    ec8a509bb53d   4 seconds ago   410MB
Run the Container #
# Run the container: 
docker run --rm hello-maven-app
# Shell output:
Hello, from Maven. Time:
2024-11-27 10:05:35
- --rmAutomatically removes the container after it stops.
 
Fat Jar #
- The Fat Jar includes all it’s necessary dependencies
Dockerfile #
# Create a Dockerfile
vi Dockerfile
# Use a lightweight JRE image as the base image
FROM eclipse-temurin:17-jre-alpine
# Set the working directory
WORKDIR /app
# Copy the application's thin JAR to the image
COPY target/HelloMaven-app-1.0-SNAPSHOT-jar-with-dependencies.jar app.jar
# Command to run the application
CMD ["java", "-jar", "app.jar"]
Build Container Image #
# Build the container image
docker build -t hello-maven-app-thin-jar .
Verify the Container Image #
# List images
docker images
# Shell output:
REPOSITORY                 TAG       IMAGE ID       CREATED         SIZE
hello-maven-app-thin-jar   latest    acbaa3dc6923   4 seconds ago   186MB
hello-maven-app            latest    ec8a509bb53d   5 minutes ago   410MB
Run the Container #
# Run the container: 
docker run --rm hello-maven-app-thin-jar
# Shell output:
Hello, from Maven. Time:
2024-11-27 10:10:41
- --rmAutomatically removes the container after it stops.
Multistage Dockerfile #
Dockerfile #
- 
Build Stage: The application is built in a dedicated environment with all necessary tools and dependencies. 
- 
Runtime Stage: A lightweight base image eclipse-temurin:17-jre-alpineis used to copy only the compiled Fat Jar from the build stage.
# Create a Dockerfile
vi Dockerfile
### Stage 1: Build Stage
# Use a lightweight JRE image as the base image / define as build stage
FROM maven:3.9.4-eclipse-temurin-17 AS build
# Set the working directory inside the build stage
WORKDIR /app
# Copy the Maven project files into the container
COPY pom.xml ./
COPY src ./src
# Build the application with dependencies included
RUN mvn clean compile assembly:single
### Stage 2: Runtime Stage
# Use a lightweight JRE image as the base image
FROM eclipse-temurin:17-jre-alpine
# Set the working directory inside the runtime stage
WORKDIR /app
# Copy the built JAR file from the build stage to the runtime stage
COPY --from=build /app/target/HelloMaven-app-1.0-SNAPSHOT-jar-with-dependencies.jar app.jar
# Expose port 80 for the web server
EXPOSE 80
# Command to run the application
ENTRYPOINT ["java", "-jar", "app.jar"]
Build Container Image #
# Build the container image
docker build -t maven-webserver-multistage .
Verify the Container Image #
# List images
docker images
# Shell output:
REPOSITORY                   TAG       IMAGE ID       CREATED          SIZE
maven-webserver-multistage   latest    f9e9fe1d8aa2   12 seconds ago   189MB
Run the Container #
# Run the container: 
docker run --rm maven-webserver-multistage
# Shell output:
Hello, from Maven. Time:
2024-11-27 13:47:55