Dockerized FullโStack Spring Boot Application โ EndโtoโEnd Web App
A modern, fully containerized two-tier Spring Boot web application with integrated Docker support, MySQL database, and multi-stage Docker builds for optimized production deployments.
- Project Overview
- Tech Stack
- Architecture
- Features
- Prerequisites
- Project Structure
- Getting Started
- Configuration
- Database Setup
- API Documentation
- Docker Deep Dive
- Troubleshooting
- Contributing
- License
PGTools is a comprehensive web application built with Spring Boot 3.5.3 that demonstrates enterprise-level containerization practices. This project implements a complete end-to-end Docker setup with two independent containers communicating through a custom Docker bridge network.
- Two-Tier Architecture: Application tier + Database tier
- Multi-Stage Docker Build: Optimized image size and security
- Docker Compose Orchestration: Single command deployment
- Custom Bridge Network: Secure container communication
- Health Checks: Database readiness monitoring
- Volume Persistence: Data durability across container restarts
- Maven Build Integration: Automated compilation and packaging
| Technology | Version | Purpose |
|---|---|---|
| Spring Boot | 3.5.3 | Web Framework & MVC |
| Java | 17 | Programming Language |
| MySQL | Latest | Relational Database |
| Maven | 3.8.3 | Build Automation |
| Docker | Latest | Containerization |
| Docker Compose | 3.8 | Multi-Container Orchestration |
| Thymeleaf | 3.5.3+ | Template Engine |
| Spring Data JPA | 3.5.3+ | ORM & Data Access |
| Spring Web | 3.5.3+ | REST APIs & Web Controllers |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Docker Compose Network (pgtools-network) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ
โ โ PGTools App โ โ MySQL 8.0 โ โ
โ โ (Container Port) โ โ (Container Port) โ โ
โ โ 8080 โ Host 8080 โ โ 3306 โ Host 3306 โ โ
โ โ โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโ โ โ
โ โ โ Spring Boot App โ โ โ โ MySQL Server โ โ โ
โ โ โ (Thymeleaf UI) โ โ โ โ pgtoolsdata โ โ โ
โ โ โ (REST APIs) โ โ โ โ PgtoolsDB โ โ โ
โ โ โ (Mail Service) โ โ โ โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโ โ โ โโโโโโโโโโโโโโโโ โ โ
โ โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โ
โ depends_on: mysql โ Health Check โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Network Communication
- Responsive Web UI - Built with Thymeleaf templates and Bootstrap
- Data Validation - Spring Validation framework
- RESTful APIs - Web services for data operations
- Email Service - SMTP integration with Gmail
- JPA ORM - Hibernate-based data persistence
- Application Metrics - Spring Boot Actuator
- Large File Support - Multipart uploads up to 1GB
- Multi-Stage Builds - Optimized production images
- Custom Bridge Network - Inter-container communication
- Volume Persistence - MySQL data durability
- Health Checks - Container readiness monitoring
- Auto Restart - Fault tolerance with restart policies
- Port Mapping - Flexible port configuration
Before you begin, ensure you have the following installed:
- Java Development Kit (JDK) 17+
- Maven 3.8.3+
- MySQL Server 8.0+ (for local testing)- Docker Desktop (or Docker Engine)
- Docker Compose 1.29+
- At least 2GB free disk spaceUbuntu/Debian:
sudo apt-get update
sudo apt-get install openjdk-17-jdk maven mysql-server
sudo apt-get install docker.io docker-composespringboot-app/
โโโ README.md # Project documentation
โโโ Dockerfile # Multi-stage Docker image definition
โโโ docker-compose.yml # Container orchestration config
โโโ pom.xml # Maven build configuration
โโโ mvnw / mvnw.cmd # Maven wrapper (Linux/Windows)
โ
โโโ src/
โ โโโ main/
โ โ โโโ java/
โ โ โ โโโ com/pg/PGTools/
โ โ โ โโโ PgToolsApplication.java # Spring Boot entry point
โ โ โ โโโ config/ # Configuration classes
โ โ โ โโโ entity/ # JPA entities
โ โ โ โโโ repository/ # Data access layer
โ โ โ โโโ service/ # Business logic interfaces
โ โ โ โโโ serviceImp/ # Service implementations
โ โ โ โโโ restController/ # REST API endpoints
โ โ โ โโโ Controller/ # MVC controllers
โ โ โ
โ โ โโโ resources/
โ โ โโโ application.properties # Spring Boot configuration
โ โ โโโ static/ # Static assets (CSS, JS, Images)
โ โ โ โโโ css/
โ โ โ โโโ js/
โ โ โ โโโ fonts/
โ โ โ โโโ images/
โ โ โโโ templates/ # Thymeleaf HTML templates
โ โ โโโ about.html
โ โ โโโ contact.html
โ โ โโโ customers.html
โ โ โโโ gallery.html
โ โ โโโ products.html
โ โ โโโ index.html
โ โ โโโ Admin/ # Admin dashboard templates
โ โ
โ โโโ test/
โ โโโ java/com/pg/ # Unit tests
โ
โโโ target/ # Build output (auto-generated)
โโโ .gitignore # Git ignore patterns
git clone https://github.com/pratikk-devops/springboot-app.git
cd springboot-appEdit src/main/resources/application.properties:
# Local MySQL setup
spring.datasource.url=jdbc:mysql://localhost:3306/pgtoolsdata?allowPublicKeyRetrieval=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update# Using Maven wrapper (recommended)
./mvnw clean install
# Or using system Maven
mvn clean install./mvnw spring-boot:runAccess the application at: http://localhost:8080
This is the easiest way to run the entire two-tier application with a single command.
Ensure Docker and Docker Compose are running:
docker --version
docker-compose --versionCheck docker-compose.yml for environment variables and credentials:
services:
mysql:
container_name: mysql
image: mysql:latest
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: pgtools@2025
MYSQL_DATABASE: PgtoolsDB
pgtoolapp:
container_name: pgtoolapp
image: pratikchaudhari555/springboot-pgtool-app:latest
ports:
- 8080:8080
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://13.49.232.110:3306/pgtoolsdata?allowPublicKeyRetrieval=true&useSSL=false
SPRING_DATASOURCE_USERNAME: pgtools
SPRING_DATASOURCE_PASSWORD: pgtools@2025# Start all containers in detached mode
docker-compose up -d
# View running containers
docker-compose ps
# View logs
docker-compose logs -f pgtoolapp
docker-compose logs -f mysql# Check MySQL health
docker-compose exec mysql mysqladmin ping -h localhost -upgtools -ppgtools@2025
# Check app logs
docker-compose logs pgtoolapp | grep "Started"- Application: http://localhost:8080
- MySQL: localhost:3306
# Stop all containers
docker-compose stop
# Stop and remove containers
docker-compose down
# Stop and remove containers + volumes (cleans everything)
docker-compose down -vFor understanding the containerization process step-by-step:
# Build using the provided Dockerfile
docker build -t springboot-pgtool-app:latest .
# Or with custom tags
docker build -t springboot-pgtool-app:1.0 .
docker build -t pratikchaudhari555/springboot-pgtool-app:latest .# Create the bridge network
docker network create pgtools-network
# Verify network creation
docker network lsdocker run -d \
--name mysql \
--network pgtools-network \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=pgtools@2025 \
-e MYSQL_DATABASE=PgtoolsDB \
-v mysql-data:/var/lib/mysql \
mysql:latestdocker exec mysql mysqladmin ping -h localhost -uroot -ppgtools@2025
# Keep checking until you get "mysqld is alive"docker run -d \
--name pgtoolapp \
--network pgtools-network \
-p 8080:8080 \
-e SPRING_DATASOURCE_URL="jdbc:mysql://mysql:3306/pgtoolsdata?allowPublicKeyRetrieval=true&useSSL=false" \
-e SPRING_DATASOURCE_USERNAME=pgtools \
-e SPRING_DATASOURCE_PASSWORD=pgtools@2025 \
springboot-pgtool-app:latestdocker ps
# View logs
docker logs -f pgtoolapp
docker logs -f mysqlLocated at: src/main/resources/application.properties
# Database connection
spring.datasource.url=jdbc:mysql://13.49.232.110:3306/pgtoolsdata?allowPublicKeyRetrieval=true&useSSL=false
spring.datasource.username=pgtools
spring.datasource.password=pgtools@2025
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# Connection pooling
spring.datasource.hikari.connection-timeout=30000
# Hibernate/JPA
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialectserver.port=8080
# Caching
spring.resources.cache.cachecontrol.max-age=0
spring.resources.cache.cachecontrol.no-cache=true
spring.resources.cache.cachecontrol.must-revalidate=truespring.servlet.multipart.max-file-size=1000MB
spring.servlet.multipart.max-request-size=1200MB
spring.servlet.multipart.file-size-threshold=1000000KB# SMTP Server (Gmail)
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=pgtools@gmail.com
spring.mail.password=fqqi shij ttnf jsfc
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com-- Database
CREATE DATABASE PgtoolsDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Tables are auto-created by Hibernate (spring.jpa.hibernate.ddl-auto=update)
-- Entities defined in: src/main/java/com/pg/PGTools/entity/If running MySQL locally:
# Connect to MySQL
mysql -h localhost -u root -p
# Create database
CREATE DATABASE pgtoolsdata CHARACTER SET utf8mb4;
# Create user
CREATE USER 'pgtools'@'%' IDENTIFIED BY 'pgtools@2025';
GRANT ALL PRIVILEGES ON pgtoolsdata.* TO 'pgtools'@'%';
FLUSH PRIVILEGES;# Access MySQL inside Docker
docker exec -it mysql mysql -u root -ppgtools@2025
# View databases
SHOW DATABASES;
# Use database
USE PgtoolsDB;
# View tables
SHOW TABLES;| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Home page |
/about |
GET | About page |
/products |
GET | Products listing |
/customers |
GET | Customers page |
/contact |
GET | Contact form page |
/gallery |
GET | Gallery page |
| Endpoint | Method | Description |
|---|---|---|
/Admin/dashboard |
GET | Admin dashboard |
/Admin/adminProducts |
GET | Manage products |
/Admin/adminCustomers |
GET | Manage customers |
/Admin/adminIndustries |
GET | Manage industries |
View the restController/ directory in the source code for available REST endpoints.
Our Dockerfile uses two-stage build for optimal image size and security:
FROM maven:3.8.3-openjdk-17 AS builder
WORKDIR /app
COPY . /app
RUN mvn clean install -DskipTests=truePurpose:
- Uses Maven image to compile source code
- Generates executable JAR file
- Skips tests for faster builds
- Only this stage contains Maven and build tools
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar /app/target/pgtools.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app/target/pgtools.jar"]Purpose:
- Uses lightweight JRE image (Alpine Linux)
- Only copies the compiled JAR
- Final image is 300MB+ smaller than using single-stage build
- No Maven or build tools in production image
| Benefit | Details |
|---|---|
| Smaller Image Size | ~400MB vs ~900MB single-stage |
| Faster Deployments | Quicker image pulls and startups |
| Enhanced Security | No build tools in production image |
| Better Practices | Follows production image optimization |
# Build with default tag
docker build -t pgtoolapp:latest .
# Build with specific version
docker build -t pgtoolapp:1.0.0 .
# Build with progress output
docker build --progress=plain -t pgtoolapp:latest .
# Build without cache
docker build --no-cache -t pgtoolapp:latest .
# Multi-stage build - view specific stage
docker build --target builder -t pgtoolapp:builder .A custom bridge network (pgtools-network) provides:
-
Service Discovery: Containers can reference each other by name
# Inside app container, connect to: mysql:3306 jdbc:mysql://mysql:3306/pgtoolsdata -
Isolation: Network isolation from other containers
-
Automatic DNS: Container names resolve to IP addresses
# View network
docker network inspect pgtools-network
# Output example:
# {
# "Name": "pgtools-network",
# "Driver": "bridge",
# "Containers": {
# "mysql": { ... },
# "pgtoolapp": { ... }
# }
# }
# Create custom network
docker network create my-network --driver bridge
# Connect container to network
docker network connect my-network container-name
# Disconnect
docker network disconnect my-network container-namevolumes:
mysql-data:
services:
mysql:
volumes:
- mysql-data:/var/lib/mysql# List volumes
docker volume ls
# Inspect volume
docker volume inspect mysql-data
# Remove volume ( Deletes data)
docker volume rm mysql-data
# Backup data
docker run --rm -v mysql-data:/data -v $(pwd):/backup \
alpine tar czf /backup/mysql-backup.tar.gz -C /data .
# Restore data
docker run --rm -v mysql-data:/data -v $(pwd):/backup \
alpine tar xzf /backup/mysql-backup.tar.gz -C /data .MySQL container includes health checking:
healthcheck:
test: ["CMD","mysqladmin","ping","-h","localhost","-upgtools","-ppgtools@2025"]
interval: 10s
timeout: 5s
retries: 5
start_period: 50sMonitor health:
docker compose ps
# View health status
docker inspect --format='{{json .State.Health}}' mysql | jq .
# Output:
# {
# "Status": "healthy",
# "FailingStreak": 0,
# "Passes": 5,
# "StartedAt": "2025-11-17T10:00:00Z"
# }Symptoms:
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
Solutions:
-
Verify MySQL is healthy:
docker-compose ps docker-compose exec mysql mysqladmin ping -u root -ppgtools@2025 -
Check network connectivity:
docker-compose exec pgtoolapp ping mysql -
Wait for MySQL startup:
# Add wait script or increase start_period in docker-compose.yml docker-compose up -d mysql sleep 30 docker-compose up pgtoolapp -
Verify environment variables:
docker inspect pgtoolapp | grep -A 5 "Env"
Error: Error response from daemon: driver failed programming external connectivity
Solutions:
# Find what's using port 8080
lsof -i :8080
# Find what's using port 3306
lsof -i :3306
# Kill process
kill -9 <PID>
# Or use different ports in docker-compose.yml
ports:
- "8081:8080" # Use 8081 instead
- "3307:3306" # Use 3307 insteadError: RUN mvn clean install -DskipTests=true failed
Solutions:
# Clear Maven cache
rm -rf ~/.m2/repository
# Build with verbose output
docker build --progress=plain --no-cache -t pgtoolapp:latest .
# Check available disk space
df -h
# Build locally first to verify
./mvnw clean install -DskipTests=trueCommands:
# View real-time logs
docker-compose logs -f pgtoolapp
# View last 100 lines
docker-compose logs --tail=100 pgtoolapp
# View logs from specific time
docker-compose logs --since 5m pgtoolapp
# Export logs to file
docker-compose logs pgtoolapp > app-logs.txt# Check container resource usage
docker stats
# Limit container resources
docker run -d \
--name pgtoolapp \
--memory 512m \
--cpus 1 \
...
# View system info
docker system info
# Prune unused resources
docker system prune -a# List running containers
docker ps
# List all containers (including stopped)
docker ps -a
# View container logs
docker logs container_name
# Execute command in container
docker exec -it container_name bash
# Stop container
docker stop container_name
# Start stopped container
docker start container_name
# Remove container
docker rm container_name
# View container details
docker inspect container_name# List images
docker images
# Remove image
docker rmi image_name
# Tag image
docker tag image_name:old_tag image_name:new_tag
# Push to registry
docker push image_name:tag
# Pull from registry
docker pull image_name:tag# Start services
docker-compose up -d
# Stop services
docker-compose stop
# Remove services
docker-compose down
# View service logs
docker-compose logs -f service_name
# Execute command
docker-compose exec service_name command# MySQL
MYSQL_ROOT_PASSWORD=pgtools@2025
MYSQL_DATABASE=PgtoolsDB
MYSQL_USER=pgtools
MYSQL_PASSWORD=pgtools@2025
# Spring Boot
SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/pgtoolsdata
SPRING_DATASOURCE_USERNAME=pgtools
SPRING_DATASOURCE_PASSWORD=pgtools@2025export SPRING_DATASOURCE_URL=jdbc:mysql://localhost:3306/pgtoolsdata
export SPRING_DATASOURCE_USERNAME=root
export SPRING_DATASOURCE_PASSWORD=your_password# Clean and install
./mvnw clean install
# Skip tests
./mvnw clean install -DskipTests=true
# Run tests
./mvnw test
# Run specific test
./mvnw test -Dtest=ClassName
# Package only (no tests)
./mvnw package -DskipTests
# View dependency tree
./mvnw dependency:tree
# Update dependencies
./mvnw versions:display-dependency-updates
# Check for vulnerabilities
./mvnw org.owasp:dependency-check-maven:checkCore dependencies used in this project:
<!-- Spring Boot -->
spring-boot-starter-web
spring-boot-starter-thymeleaf
spring-boot-starter-data-jpa
spring-boot-starter-validation
spring-boot-starter-mail
spring-boot-starter-actuator
spring-boot-starter-web-services
<!-- Database -->
mysql-connector-j
<!-- Testing -->
spring-boot-starter-testSee pom.xml for complete dependency list and versions.
- All tests passing locally
- Docker image builds successfully
- Docker Compose file validated
- Environment variables configured
- Database backups created
- Security vulnerabilities checked
- Performance tested
- Documentation updated
# Build production image
docker build -t registry.example.com/pgtoolapp:1.0.0 .
# Push to registry
docker push registry.example.com/pgtoolapp:1.0.0
# Deploy using Compose
docker-compose -f docker-compose.prod.yml up -dPratik Chaudhari
- GitHub: @pratikk-devops
- Docker Hub: @pratikchaudhari555
- Spring Boot Documentation
- Docker Documentation
- Docker Compose Documentation
- Maven Documentation
- MySQL Documentation
- Java 17 Documentation
- Language: Java
- Framework: Spring Boot 3.5.3
- Build Tool: Maven 3.8.3+
- Container Runtime: Docker
- Database: MySQL 8.0+
- JDK Version: 17+
- Lines of Code: Custom implementation
- Test Coverage: Unit tests included
- Title: Dockerized Spring Boot FullโStack App