Containerizing a Two-Tier Java Application with Docker Compose and Image Scanning using Docker Scout


π Introduction
In this blog, we will explore how to containerize a two-tier Java application using Docker, manage services with Docker Compose, and ensure image security through Docker Scout.
We'll walk through a practical use case: a Java Spring Boot backend connected to a MySQL database, containerized using modern DevOps techniques like multi-stage builds, health checks, and vulnerability scanning.
π§± Docker Compose
Docker Compose allows you to define and orchestrate multi-container applications using a single docker-compose.yml
file.
β¨ Key Benefits:
Multi-container management: Define backend, database, and other services together.
Networking: Automatic internal networking with simple service names.
Scaling: Increase container replicas with ease.
Environment variables: Easily configure apps for different environments.
π§° Multi-stage Docker Builds
Multi-stage builds reduce the final image size and improve build performance by separating build-time and runtime environments.
β¨ Key Benefits:
Smaller images: Only necessary files included in the final image.
Faster builds: Clean and layered build stages.
Improved security: No dev tools in production image.
π§ Prerequisites
Ensure the following tools are installed:
Docker (v23+ recommended for Docker Scout)
Git
AWS EC2
π Step 1: Clone the Repository
git clone https://github.com/Ajinkya-Giri27/Expenses-Tracker-WebApp.git
cd Expenses-Tracker-WebApp
π οΈ Step 2: Create a Dockerfile
Here is a basic Dockerfile using Maven to build the JAR file:
FROM maven:3.8.3-openjdk-17 AS builder
WORKDIR /app
COPY . /app
RUN mvn clean install -DskipTests=true
EXPOSE 8080
CMD ["java", "-jar", "/expenseapp.jar"]
β‘ This works, but we can optimize it using multi-stage builds.
ποΈ Step 3: Optimize with Multi-stage Dockerfile
# Stage 1 - Build the JAR
FROM maven:3.8.3-openjdk-17 AS builder
WORKDIR /app
COPY . /app
RUN mvn clean install -DskipTests=true
# Stage 2 - Run the JAR
FROM openjdk:17-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar /app/target/expenseapp.jar
EXPOSE 8080
CMD ["java", "-jar", "/app/target/expenseapp.jar"]
π§ This significantly reduces image size and improves security.
π Step 4: Create a Docker Compose File
version: "3.8"
services:
java_app:
build: .
container_name: "expensesapp"
environment:
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/expenses_tracker?allowPublicKeyRetrieval=true&useSSL=false
SPRING_DATASOURCE_PASSWORD: Test@123
ports:
- "8080:8080"
networks:
- expenses-app-nw
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000 || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 60s
depends_on:
- mysql_db
restart: always
mysql_db:
image: mysql
container_name: "mysql"
environment:
MYSQL_ROOT_PASSWORD: Test@123
MYSQL_DATABASE: expenses_tracker
volumes:
- ./mysql-data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- expenses-app-nw
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-pTest@123"]
interval: 10s
timeout: 5s
retries: 5
start_period: 60s
restart: always
networks:
expenses-app-nw:
volumes:
mysql-data:
π Step 5: Run with Docker Compose
docker-compose up --build
π§ This command builds the images and runs both containers.
π Step 6: Access the Application
Once the containers are running, visit:
http://<your-ec2-ip>:8080
You should see the Expense Tracker App up and running!
π‘οΈ Docker Scout Image Scanning
π Scan for vulnerabilities:
docker scout cves expensesapp
π Generate a Software Bill of Materials (SBOM):
docker scout sbom expensesapp
π§ Make sure you're logged in to Docker Hub (
docker login
) and using Docker CLI v23+.
π Summary
In this guide, we:
π’ Containerized a Java + MySQL two-tier app
βοΈ Used Docker Compose for orchestration
ποΈ Optimized with multi-stage Docker builds
π‘οΈ Scanned image for vulnerabilities using Docker Scout
This approach ensures:
Smaller, production-ready images
Better build performance
Improved security and maintainability
π Happy Shipping!
Fork the repo π, try it on your machine π, and feel free to ask questions or share feedback in the comments!
β¨ Donβt forget to follow me on Hashnode & GitHub for more DevOps content!
Subscribe to my newsletter
Read articles from Ajinkya Giri directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Ajinkya Giri
Ajinkya Giri
π Aspiring DevOps Engineer | Computer Engineering Student π Passionate about bridging the gap between development and operations, I am a computer engineering student with a keen interest in DevOps, automation, and cloud computing. I thrive on optimizing workflows, implementing CI/CD pipelines, and exploring the latest DevOps tools to enhance software deployment and scalability. πΉ Tech Interests: DevOps, Cloud Computing (AWS/Azure/GCP), Kubernetes, CI/CD, Infrastructure as Code πΉ Skills in Progress: Linux, Git, Docker, Terraform, Python/Bash scripting πΉ Goal: To master DevOps methodologies and contribute to seamless software delivery π Always eager to learn, collaborate, and automate! π‘