From e595840919274310dffd61a4c0f337677a01e29b Mon Sep 17 00:00:00 2001 From: Shrij34 Date: Tue, 20 Jan 2026 09:38:37 +0530 Subject: [PATCH] added dockerfile,compose,changed aplication proprty,readme and setup.txt --- .dockerignore | 6 + DOCKER_SETUP_COMPLETE_GUIDE.txt | 504 +++++++++++++++++++ Dockerfile | 14 + README.md | 559 ++++++++++++++++++++++ docker-compose.yml | 41 ++ src/main/resources/application.properties | 8 +- 6 files changed, 1128 insertions(+), 4 deletions(-) create mode 100644 .dockerignore create mode 100644 DOCKER_SETUP_COMPLETE_GUIDE.txt create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..8d6d5a0b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +target/ +.git +.gitignore +.mvn +*.md +.DS_Store diff --git a/DOCKER_SETUP_COMPLETE_GUIDE.txt b/DOCKER_SETUP_COMPLETE_GUIDE.txt new file mode 100644 index 00000000..16cdfef1 --- /dev/null +++ b/DOCKER_SETUP_COMPLETE_GUIDE.txt @@ -0,0 +1,504 @@ +================================================================================ + JAVA BANK APP - DOCKER SETUP COMPLETE GUIDE + Full Chat History & Documentation +================================================================================ + +DATE: January 20, 2026 +PROJECT: Java-Bank-App (Spring Boot + MySQL) +STATUS: Successfully containerized and deployed in Docker Desktop + +================================================================================ +SECTION 1: GIT BRANCH SETUP (Initial Issue) +================================================================================ + +PROBLEM: +- When cloning from GitHub, only got 'start' branch locally +- 'end' branch existed on GitHub but not locally +- Needed to pull the 'end' branch + +SOLUTION: +1. Check all branches: + git branch -a + +2. Fetch all remote branches: + git fetch --all + +3. Check out end branch from remote: + git checkout -b end origin/end + +RESULT: +- Local 'end' branch now tracks origin/end from GitHub +- Both 'start' and 'end' branches available locally + +================================================================================ +SECTION 2: DOCKER SETUP - FILES CREATED +================================================================================ + +FILE 1: Dockerfile +================================================================================ +# Build stage +FROM maven:3.9.6-eclipse-temurin-17-alpine AS builder +WORKDIR /app +COPY pom.xml . +COPY src ./src +RUN mvn clean package -DskipTests + +# Runtime stage +FROM eclipse-temurin:17-jre-alpine +WORKDIR /app +COPY --from=builder /app/target/bankapp-0.0.1-SNAPSHOT.jar app.jar + +EXPOSE 8080 +ENTRYPOINT ["java", "-jar", "app.jar"] + +PURPOSE: +- Multi-stage build reduces image from 500MB to 200MB +- First stage: builds app with Maven +- Second stage: includes only JRE (no build tools) +- Result: lightweight, production-ready image + +================================================================================ +FILE 2: docker-compose.yml +================================================================================ +services: + mysql: + image: mysql:8.0 + container_name: bankapp-mysql + environment: + MYSQL_ROOT_PASSWORD: Test@123 + MYSQL_DATABASE: bankappdb + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - bankapp-network + + bankapp: + build: . + container_name: bankapp + environment: + SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/bankappdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true + SPRING_DATASOURCE_USERNAME: root + SPRING_DATASOURCE_PASSWORD: Test@123 + SPRING_JPA_HIBERNATE_DDL_AUTO: update + ports: + - "8080:8080" + depends_on: + mysql: + condition: service_healthy + networks: + - bankapp-network + +volumes: + mysql_data: + +networks: + bankapp-network: + driver: bridge + +PURPOSE: +- Orchestrates both MySQL and Spring Boot containers +- Health checks ensure MySQL starts before app connects +- Named volume persists database data across restarts +- Bridge network allows container-to-container communication +- Environment variables for flexible configuration + +================================================================================ +FILE 3: .dockerignore +================================================================================ +target/ +.git +.gitignore +.mvn +*.md +.DS_Store + +PURPOSE: +- Excludes unnecessary files from Docker build context +- Keeps image size small +- Faster build times + +================================================================================ +SECTION 3: CONFIGURATION CHANGES - application.properties +================================================================================ + +BEFORE: +spring.application.name=bankapp +spring.datasource.url=jdbc:mysql://localhost:3306/bankappdb?useSSL=false&serverTimezone=UTC +spring.datasource.username=root +spring.datasource.password=Test@123 +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.jpa.hibernate.ddl-auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect +spring.jpa.show-sql=true + +PROBLEMS WITH BEFORE: +- Hardcoded localhost (doesn't work in Docker) +- No environment variable support +- MySQL 8 authentication issues + +AFTER: +spring.application.name=bankapp +spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/bankappdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true} +spring.datasource.username=${SPRING_DATASOURCE_USERNAME:root} +spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:Test@123} +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.jpa.hibernate.ddl-auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect +spring.jpa.show-sql=true + +WHAT CHANGED AND WHY: +1. Added ${SPRING_DATASOURCE_URL:...} - Environment variable with default value +2. Added allowPublicKeyRetrieval=true - Fixes MySQL 8 CachingSha2Password authentication +3. Changed MySQL8Dialect to MySQLDialect - Updated for Hibernate 6.5.2 +4. Same changes in docker-compose.yml environment variables + +================================================================================ +SECTION 4: ERRORS ENCOUNTERED & SOLUTIONS +================================================================================ + +ERROR 1: Communications link failure +================================================================================ +Error Log: +java.sql.SQLNonTransientConnectionException: Communications link failure + +CAUSE: +- App trying to connect to localhost:3306 +- In Docker, containers communicate via hostname 'mysql', not localhost + +SOLUTION: +- Update application.properties to use environment variables +- Set SPRING_DATASOURCE_URL in docker-compose.yml to: jdbc:mysql://mysql:3306/... +- 'mysql' is the service name in docker-compose.yml + +================================================================================ +ERROR 2: Public Key Retrieval is not allowed +================================================================================ +Error Log: +com.mysql.cj.exceptions.UnableToConnectException: Public Key Retrieval is not allowed + +CAUSE: +- MySQL 8 uses CachingSha2Password authentication by default +- JDBC driver needs to retrieve server's public key +- Security feature blocks this by default + +SOLUTION: +- Add ?allowPublicKeyRetrieval=true to JDBC URL +- Updated in TWO places: + 1. application.properties (for local development) + 2. docker-compose.yml environment variable (for Docker) + +Full URL: +jdbc:mysql://mysql:3306/bankappdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true + +================================================================================ +ERROR 3: Access denied for user 'root'@'172.20.0.3' (using password: YES) +================================================================================ +Error Log: +java.sql.SQLException: Access denied for user 'root'@'172.20.0.3' (using password: YES) + +CAUSE: +- MySQL container initialized with wrong password +- Application properties had different credentials than docker-compose +- Old volume had stale data with different password + +SOLUTION: +1. Stop containers and remove volumes: + docker-compose down -v + +2. Ensure credentials match in TWO places: + - docker-compose.yml: MYSQL_ROOT_PASSWORD: Test@123 + - application.properties: spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:Test@123} + +3. Ensure database name matches in TWO places: + - docker-compose.yml: MYSQL_DATABASE: bankappdb + - application.properties URL: jdbc:mysql://mysql:3306/bankappdb + +4. Rebuild and start fresh: + docker-compose up -d --build + +================================================================================ +SECTION 5: ALL CHANGES SUMMARY +================================================================================ + +CHANGE 1: Created Dockerfile (Multi-stage build) +WHY: Optimize image size - build tools only needed in first stage + +CHANGE 2: Created docker-compose.yml (Orchestration) +WHY: Manage both app and database containers with one command + +CHANGE 3: Updated application.properties (Environment variables) +WHY: Support flexible configuration for different environments + +CHANGE 4: Added allowPublicKeyRetrieval=true +WHY: Fix MySQL 8 authentication issues + +CHANGE 5: Created .dockerignore +WHY: Keep Docker image size small by excluding unnecessary files + +CHANGE 6: Added bridge network to docker-compose +WHY: Enable container-to-container communication by hostname + +CHANGE 7: Removed version line from docker-compose +WHY: Version attribute is deprecated, causes warnings + +CHANGE 8: Matched database credentials +WHY: MySQL container and app need same credentials + +================================================================================ +SECTION 6: VOLUME NAMING EXPLANATION +================================================================================ + +Volume Name: java-bank-app_mysql_data + +Naming Convention: +{project-folder-name}_{service-name}_{volume-name} + +Breakdown: +- java-bank-app = Your folder name (Java-Bank-App) +- mysql = Service name from docker-compose.yml +- mysql_data = Volume name we defined in docker-compose.yml + +To verify: +docker volume ls + +Output shows: +DRIVER VOLUME NAME +local java-bank-app_mysql_data + +PURPOSE: +- Persistent storage for MySQL data +- Data survives container restarts +- Prevents data loss + +================================================================================ +SECTION 7: DEPLOYMENT COMMANDS +================================================================================ + +FIRST TIME SETUP: +docker-compose up -d --build + +This will: +1. Build Docker image from Dockerfile +2. Pull MySQL 8.0 image +3. Create bridge network +4. Create mysql_data volume +5. Start MySQL container +6. Wait for MySQL to be healthy (health check) +7. Start bankapp container +8. Connect app to database + +CHECK RUNNING CONTAINERS: +docker ps + +CHECK LOGS: +docker-compose logs -f bankapp + +Verify Success Signs: +- "Tomcat initialized with port 8080" +- "HikariPool-1 - Starting..." +- "Root WebApplicationContext: initialization completed" + +ACCESS APPLICATION: +http://localhost:8080 + +STOP CONTAINERS: +docker-compose down + +STOP AND REMOVE DATA: +docker-compose down -v + +RESTART CONTAINERS: +docker-compose restart + +================================================================================ +SECTION 8: INTERVIEW EXPLANATION (ONE PARAGRAPH) +================================================================================ + +I containerized a Java Spring Boot banking application by creating a Dockerfile +with a multi-stage build to optimize the image size, then used Docker Compose to +orchestrate both the app and MySQL database in separate containers with automatic +networking and health checks. I configured environment variables in the Spring Boot +application to support flexible database credentials across different environments, +fixed MySQL 8 authentication issues by adding `allowPublicKeyRetrieval=true`, and +set up a persistent named volume for database data so it survives container +restarts. The result was a production-ready, fully containerized solution that +deploys with a single command (`docker-compose up -d --build`), making the +application portable and consistent across development, testing, and production +environments. + +================================================================================ +SECTION 9: BEFORE RUNNING docker-compose up NEXT TIME +================================================================================ + +PREREQUISITES: +✅ Docker Desktop installed & running +✅ Source code ready (Java app with pom.xml) +✅ All dependencies in pom.xml (MySQL connector, JPA, Spring Boot, etc.) + +CONFIGURATION FILES NEEDED: +✅ Dockerfile in project root +✅ docker-compose.yml in project root +✅ .dockerignore in project root +✅ application.properties with environment variables + +DATABASE SETUP: +✅ Match database credentials in both: + - application.properties + - docker-compose.yml +✅ Use same database name in both places +✅ For MySQL 8: Add allowPublicKeyRetrieval=true +✅ Set proper environment variables in docker-compose + +KEY SETTINGS TO VERIFY: +1. Dockerfile: + - FROM maven:3.9.6-eclipse-temurin-17-alpine (builder) + - FROM eclipse-temurin:17-jre-alpine (runtime) + - EXPOSE 8080 + +2. docker-compose.yml: + - MySQL service with MYSQL_ROOT_PASSWORD and MYSQL_DATABASE + - App service with SPRING_DATASOURCE_URL and port 8080 + - Health checks for MySQL + - Named volume for database + - Bridge network configuration + +3. application.properties: + - Uses ${SPRING_DATASOURCE_URL:...} format + - Has allowPublicKeyRetrieval=true + - Uses MySQLDialect (not MySQL8Dialect) + +4. .dockerignore: + - Excludes target/, .git, .gitignore, .mvn, *.md + +COMMON PITFALLS TO AVOID: +❌ Hardcoding localhost in app config (use hostname in Docker) +❌ Mismatched credentials between app and database +❌ Not waiting for database to be ready before app starts +❌ Missing port mappings in docker-compose +❌ Not using volumes (data lost on restart) +❌ Missing health checks (app starts before DB is ready) + +QUICK VERIFICATION: +1. docker ps + - Shows both bankapp and bankapp-mysql running + +2. docker-compose logs -f bankapp + - Should see successful startup messages + - No connection errors + +3. http://localhost:8080 + - Application accessible + +================================================================================ +SECTION 10: PROJECT STRUCTURE +================================================================================ + +Java-Bank-App/ +├── src/ +│ ├── main/ +│ │ ├── java/com/example/bankapp/ +│ │ │ └── BankappApplication.java +│ │ └── resources/ +│ │ ├── application.properties (UPDATED) +│ │ ├── static/ +│ │ │ └── mysql/SQLScript.txt +│ │ └── templates/ +│ │ ├── dashboard.html +│ │ ├── login.html +│ │ ├── register.html +│ │ └── transactions.html +│ └── test/ +│ └── java/com/example/bankapp/ +│ └── BankappApplicationTests.java +├── pom.xml +├── Dockerfile (CREATED) +├── docker-compose.yml (CREATED) +├── .dockerignore (CREATED) +├── mvnw +├── mvnw.cmd +└── target/ (generated by Maven) + +================================================================================ +SECTION 11: QUICK REFERENCE - COMMON COMMANDS +================================================================================ + +Start all containers: +docker-compose up -d --build + +View logs: +docker-compose logs -f + +Stop containers: +docker-compose down + +Stop and remove data: +docker-compose down -v + +Check running containers: +docker ps + +Check all containers (including stopped): +docker ps -a + +Check volumes: +docker volume ls + +Access MySQL: +docker exec -it bankapp-mysql mysql -u root -p + +Build image only: +docker build -t bankapp:latest . + +Push to registry (after docker login): +docker push /bankapp:latest + +Clean up everything: +docker system prune -a + +================================================================================ +SECTION 12: PRODUCTION CONSIDERATIONS +================================================================================ + +For production deployment, consider: + +1. Security: + - Don't use root user for MySQL + - Use strong passwords (not Test@123) + - Enable SSL for connections + - Use secrets management (Docker Secrets or Kubernetes) + +2. Scaling: + - Use Docker Swarm or Kubernetes + - Load balancing for multiple app instances + - Database replication + +3. Monitoring: + - Log aggregation (ELK, Splunk) + - Health checks and alerting + - Performance monitoring + +4. CI/CD Pipeline: + - Automated builds on git push + - Test containers + - Push to registry + - Deploy to production + +5. Database: + - Backup strategy + - Disaster recovery + - Database migrations + +================================================================================ +END OF COMPLETE DOCUMENTATION +================================================================================ + +Created: January 20, 2026 +Last Updated: January 20, 2026 +Status: Ready for Interview & Production Use diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..01eab2b0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +# Build stage +FROM maven:3.9.6-eclipse-temurin-17-alpine AS builder +WORKDIR /app +COPY pom.xml . +COPY src ./src +RUN mvn clean package -DskipTests + +# Runtime stage +FROM eclipse-temurin:17-jre-alpine +WORKDIR /app +COPY --from=builder /app/target/bankapp-0.0.1-SNAPSHOT.jar app.jar + +EXPOSE 8080 +ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/README.md b/README.md new file mode 100644 index 00000000..94245249 --- /dev/null +++ b/README.md @@ -0,0 +1,559 @@ +# Java Bank App - Docker Setup Guide + +A complete step-by-step guide to containerize and deploy a Java Spring Boot banking application with MySQL using Docker and Docker Compose. + +## Table of Contents +1. [Prerequisites](#prerequisites) +2. [Project Structure](#project-structure) +3. [Step-by-Step Setup](#step-by-step-setup) +4. [File Creation](#file-creation) +5. [Verification](#verification) +6. [Deployment](#deployment) +7. [Troubleshooting](#troubleshooting) +8. [Common Commands](#common-commands) + +--- + +## Prerequisites + +Before starting, ensure you have: + +- **Docker Desktop** installed and running ([Download here](https://www.docker.com/products/docker-desktop)) +- **Java Spring Boot application** with Maven (pom.xml) +- **MySQL Connector** dependency in pom.xml: + ```xml + + com.mysql + mysql-connector-j + + ``` +- **Git** (optional, for version control) +- **Command line** (PowerShell on Windows, Terminal on Mac/Linux) + +--- + +## Project Structure + +Your project should look like this: + +``` +Java-Bank-App/ +├── src/ +│ ├── main/ +│ │ ├── java/com/example/bankapp/ +│ │ │ └── BankappApplication.java +│ │ └── resources/ +│ │ └── application.properties +│ └── test/ +├── pom.xml +├── mvnw +├── mvnw.cmd +├── Dockerfile ← Create this +├── docker-compose.yml ← Create this +├── .dockerignore ← Create this +└── README.md +``` + +--- + +## Step-by-Step Setup + +### Step 1: Clone or Navigate to Your Repository + +```bash +# If cloning for first time +git clone +cd Java-Bank-App + +# If already cloned, fetch the correct branch +git branch -a +git checkout -b end origin/end # or your desired branch +``` + +### Step 2: Create Dockerfile + +Create a new file named `Dockerfile` in your project root: + +```dockerfile +# Build stage +FROM maven:3.9.6-eclipse-temurin-17-alpine AS builder +WORKDIR /app +COPY pom.xml . +COPY src ./src +RUN mvn clean package -DskipTests + +# Runtime stage +FROM eclipse-temurin:17-jre-alpine +WORKDIR /app +COPY --from=builder /app/target/bankapp-0.0.1-SNAPSHOT.jar app.jar + +EXPOSE 8080 +ENTRYPOINT ["java", "-jar", "app.jar"] +``` + +**What this does:** +- **Stage 1 (builder):** Compiles your Java app with Maven +- **Stage 2 (runtime):** Only includes JRE, drops build tools +- **Result:** Optimized image (~200MB instead of 500MB+) + +### Step 3: Create docker-compose.yml + +Create a new file named `docker-compose.yml` in your project root: + +```yaml +services: + mysql: + image: mysql:8.0 + container_name: bankapp-mysql + environment: + MYSQL_ROOT_PASSWORD: Test@123 + MYSQL_DATABASE: bankappdb + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - bankapp-network + + bankapp: + build: . + container_name: bankapp + environment: + SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/bankappdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true + SPRING_DATASOURCE_USERNAME: root + SPRING_DATASOURCE_PASSWORD: Test@123 + SPRING_JPA_HIBERNATE_DDL_AUTO: update + ports: + - "8080:8080" + depends_on: + mysql: + condition: service_healthy + networks: + - bankapp-network + +volumes: + mysql_data: + +networks: + bankapp-network: + driver: bridge +``` + +**What this does:** +- **MySQL service:** Database container with persistent volume +- **BankApp service:** Java application container +- **Health checks:** Ensures MySQL is ready before app starts +- **Networking:** Allows containers to communicate +- **Volumes:** Persists database data across restarts + +### Step 4: Create .dockerignore + +Create a new file named `.dockerignore` in your project root: + +``` +target/ +.git +.gitignore +.mvn +*.md +.DS_Store +node_modules/ +``` + +**What this does:** +- Excludes unnecessary files from Docker image +- Reduces build time and image size + +### Step 5: Update application.properties + +Modify `src/main/resources/application.properties`: + +```properties +spring.application.name=bankapp + +# MySQL Database configuration (supports environment variables) +spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/bankappdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true} +spring.datasource.username=${SPRING_DATASOURCE_USERNAME:root} +spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:Test@123} +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +# JPA & Hibernate configuration +spring.jpa.hibernate.ddl-auto=update +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect +spring.jpa.show-sql=true +``` + +**Key changes:** +- `${SPRING_DATASOURCE_URL:...}` - Environment variable with default value +- `allowPublicKeyRetrieval=true` - Fixes MySQL 8 authentication +- Uses `MySQLDialect` not `MySQL8Dialect` + +--- + +## File Creation + +### Summary of Files to Create + +| File | Location | Purpose | +|------|----------|---------| +| Dockerfile | Project root | Container image definition | +| docker-compose.yml | Project root | Orchestrates app + MySQL | +| .dockerignore | Project root | Excludes unnecessary files | +| (modify) application.properties | src/main/resources/ | Environment variable support | + +--- + +## Verification + +Before running docker-compose, verify: + +```bash +# Check file exists +ls Dockerfile +ls docker-compose.yml +ls .dockerignore + +# Check application.properties has environment variables +cat src/main/resources/application.properties | grep SPRING_DATASOURCE + +# Verify pom.xml has MySQL connector +cat pom.xml | grep mysql-connector +``` + +--- + +## Deployment + +### First Time: Build and Start Everything + +```powershell +# Navigate to project directory +cd D:\Inteview\CICD_local\BankApp\Java-Bank-App + +# Build images and start containers +docker-compose up -d --build + +# Wait 15 seconds for MySQL to initialize +Start-Sleep -Seconds 15 + +# Check if running +docker ps +``` + +**Expected output:** +``` +CONTAINER ID IMAGE COMMAND STATUS +abc123 java-bank-app-bankapp:latest "java -jar app.jar" Up 2 seconds +def456 mysql:8.0 "docker-entrypoint..." Up 3 seconds (healthy) +``` + +### View Logs + +```powershell +# Follow logs in real-time +docker-compose logs -f bankapp + +# View only MySQL logs +docker-compose logs -f mysql + +# View logs from specific time +docker-compose logs --since 10m +``` + +**Success signs in logs:** +``` +bankapp | Tomcat initialized with port 8080 (http) +bankapp | HikariPool-1 - Starting... +bankapp | Root WebApplicationContext: initialization completed +bankapp | Started BankappApplication +``` + +### Access the Application + +Open your browser and go to: +``` +http://localhost:8080 +``` + +**Database connection:** +``` +Host: localhost +Port: 3306 +Username: root +Password: Test@123 +Database: bankappdb +``` + +--- + +## Troubleshooting + +### Issue 1: MySQL Not Starting + +```bash +# Check MySQL logs +docker-compose logs mysql + +# Solution: Increase wait time +Start-Sleep -Seconds 30 + +# Check if volume is corrupted +docker volume ls +docker volume rm java-bank-app_mysql_data + +# Start fresh +docker-compose down -v +docker-compose up -d --build +``` + +### Issue 2: App Can't Connect to Database + +**Error:** `Communications link failure` or `Access denied` + +**Solution:** +1. Verify credentials match in both places: + - `docker-compose.yml`: `MYSQL_ROOT_PASSWORD: Test@123` + - `application.properties`: `spring.datasource.password=Test@123` + +2. Verify database name matches: + - `docker-compose.yml`: `MYSQL_DATABASE: bankappdb` + - Connection URL: `jdbc:mysql://mysql:3306/bankappdb` + +3. Clean restart: + ```powershell + docker-compose down -v + docker-compose up -d --build + ``` + +### Issue 3: Port Already in Use + +**Error:** `Port 8080 is already in use` + +**Solution:** +```bash +# Option 1: Stop the process using the port +netstat -ano | findstr :8080 +taskkill /PID /F + +# Option 2: Use different port in docker-compose.yml +# Change: "8080:8080" to "9090:8080" +``` + +### Issue 4: Docker Image Build Fails + +**Error:** `failed to solve with frontend dockerfile.v0` + +**Solution:** +```bash +# Check Dockerfile syntax +docker build -t test:latest . + +# Verify pom.xml is in project root +ls pom.xml + +# Check src folder exists +ls src/ + +# Clean Docker cache and rebuild +docker system prune -a +docker-compose up -d --build --no-cache +``` + +--- + +## Common Commands + +### Container Management + +```bash +# Start containers +docker-compose up -d --build + +# Stop containers +docker-compose down + +# Stop and remove data +docker-compose down -v + +# Restart containers +docker-compose restart + +# View running containers +docker ps + +# View all containers (including stopped) +docker ps -a +``` + +### Logs and Debugging + +```bash +# View live logs +docker-compose logs -f + +# View logs from specific service +docker-compose logs -f bankapp +docker-compose logs -f mysql + +# View last 50 lines +docker-compose logs --tail 50 + +# View logs from last 10 minutes +docker-compose logs --since 10m +``` + +### Database Access + +```bash +# Connect to MySQL +docker exec -it bankapp-mysql mysql -u root -p +# Enter password: Test@123 + +# Run SQL query +docker exec -it bankapp-mysql mysql -u root -p -e "SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'bankappdb';" +``` + +### Cleaning Up + +```bash +# Remove all stopped containers +docker container prune + +# Remove unused images +docker image prune + +# Remove unused volumes +docker volume prune + +# Remove everything (careful!) +docker system prune -a + +# Remove specific volume +docker volume rm java-bank-app_mysql_data +``` + +--- + +## Environment Variables + +### How to Override Credentials + +Instead of modifying docker-compose.yml, you can pass environment variables: + +```bash +# Method 1: Command line +docker-compose up -d -e SPRING_DATASOURCE_PASSWORD=newpassword + +# Method 2: Create .env file +echo "MYSQL_ROOT_PASSWORD=newpassword" > .env +echo "SPRING_DATASOURCE_PASSWORD=newpassword" >> .env +docker-compose up -d + +# Method 3: Update docker-compose.yml directly +``` + +### Available Variables + +```yaml +# MySQL +MYSQL_ROOT_PASSWORD=Test@123 +MYSQL_DATABASE=bankappdb + +# Spring Boot +SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/bankappdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true +SPRING_DATASOURCE_USERNAME=root +SPRING_DATASOURCE_PASSWORD=Test@123 +SPRING_JPA_HIBERNATE_DDL_AUTO=update +``` + +--- + +## Production Checklist + +Before deploying to production: + +- [ ] Use strong passwords (not Test@123) +- [ ] Don't run as root user +- [ ] Enable SSL for database connections +- [ ] Set up automated backups +- [ ] Configure health checks +- [ ] Set resource limits (CPU, memory) +- [ ] Enable logging and monitoring +- [ ] Use secrets management +- [ ] Set up CI/CD pipeline +- [ ] Document deployment process + +--- + +## Quick Start Template + +```bash +# 1. Clone repository +git clone +cd Java-Bank-App + +# 2. Create Docker files (copy from above) +# - Dockerfile +# - docker-compose.yml +# - .dockerignore + +# 3. Update application.properties with environment variables + +# 4. Build and deploy +docker-compose up -d --build + +# 5. Verify +docker ps +docker-compose logs -f bankapp + +# 6. Access app +# Browser: http://localhost:8080 +``` + +--- + +## Interview Explanation + +**One Paragraph:** +I containerized a Java Spring Boot banking application by creating a Dockerfile with a multi-stage build to optimize the image size, then used Docker Compose to orchestrate both the app and MySQL database in separate containers with automatic networking and health checks. I configured environment variables in the Spring Boot application to support flexible database credentials across different environments, fixed MySQL 8 authentication issues by adding `allowPublicKeyRetrieval=true`, and set up a persistent named volume for database data so it survives container restarts. The result was a production-ready, fully containerized solution that deploys with a single command (`docker-compose up -d --build`), making the application portable and consistent across development, testing, and production environments. + +--- + +## Additional Resources + +- [Docker Documentation](https://docs.docker.com/) +- [Docker Compose Documentation](https://docs.docker.com/compose/) +- [Spring Boot Docker Guide](https://spring.io/guides/gs/spring-boot-docker/) +- [MySQL Docker Hub](https://hub.docker.com/_/mysql) +- [Java Docker Best Practices](https://docs.docker.com/language/java/) + +--- + +## Support + +For issues or questions: + +1. Check [Troubleshooting](#troubleshooting) section +2. View logs: `docker-compose logs -f` +3. Verify file contents match examples above +4. Ensure Docker Desktop is running +5. Check Docker version: `docker --version` + +--- + +## License + +This setup guide is provided as-is for educational and development purposes. + +--- + +**Last Updated:** January 20, 2026 +**Status:** Production Ready +**Java Version:** 17 +**Spring Boot Version:** 3.3.3 +**MySQL Version:** 8.0 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..9ae0a3d0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,41 @@ +services: + mysql: + image: mysql:8.0 + container_name: bankapp-mysql + environment: + MYSQL_ROOT_PASSWORD: Test@123 + MYSQL_DATABASE: bankappdb + ports: + - "3306:3306" + volumes: + - mysql_data:/var/lib/mysql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - bankapp-network + + bankapp: + build: . + container_name: bankapp + environment: + SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/bankappdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true + SPRING_DATASOURCE_USERNAME: root + SPRING_DATASOURCE_PASSWORD: Test@123 + SPRING_JPA_HIBERNATE_DDL_AUTO: update + ports: + - "8080:8080" + depends_on: + mysql: + condition: service_healthy + networks: + - bankapp-network + +volumes: + mysql_data: + +networks: + bankapp-network: + driver: bridge diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 08663a63..ef3a1f8c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,11 +1,11 @@ spring.application.name=bankapp # MySQL Database configuration -spring.datasource.url=jdbc:mysql://localhost:3306/bankappdb?useSSL=false&serverTimezone=UTC -spring.datasource.username=root -spring.datasource.password=Test@123 +spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/bankappdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true} +spring.datasource.username=${SPRING_DATASOURCE_USERNAME:root} +spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:Test@123} spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver # JPA & Hibernate configuration spring.jpa.hibernate.ddl-auto=update -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect spring.jpa.show-sql=true