Platform: Azure Linux VM Tools: Docker • Docker Compose • GitHub Actions • Spring Boot • Nginx
This project demonstrates the full containerization and deployment of a two-tier web application using Docker, Docker Compose, and Azure Cloud Virtual Machine (VM). It consists of:
- A Java Spring Boot backend providing REST APIs for student data management.
- A frontend web interface served through Nginx.
- Both services containerized, orchestrated, and deployed together using Docker Compose.
The project validates practical knowledge in containerization, CI/CD automation, and cloud-based deployment workflows.
- Containerize backend (Java) and frontend (HTML/JS) services.
- Use Docker Compose to orchestrate both containers.
- Build and push Docker images to Docker Hub.
- Automate builds and pushes using GitHub Actions CI/CD.
- Deploy and run containers on an Azure Linux VM.
- Validate container communication and public accessibility.
docker-project/
│
├── backend/
│ ├── src/main/java/com/example/demo/
│ │ ├── model/Student.java
│ │ ├── service/StudentService.java
│ │ └── controller/StudentController.java
│ ├── pom.xml
│ └── Dockerfile
│
├── frontend/
│ ├── index.html
│ ├── style.css
│ ├── script.js
│ └── Dockerfile
│
├── docker-compose.yml
└── .github/workflows/docker-publish.yml
API Endpoints
GET /api/students
POST /api/students
PUT /api/students/{id}
DELETE /api/students/{id}
Dockerfile
# Build stage
FROM maven:3.9.6-eclipse-temurin-17 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn -B clean package -DskipTests
# Run stage
FROM eclipse-temurin:17-jdk
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]Dockerfile
FROM nginx:alpine
COPY . /usr/share/nginx/html
EXPOSE 80Frontend connects to backend using:
fetch("http://20.0.250.3:8080/api/students")services:
backend:
image: dukeyico/java-backend:latest
build: ./backend
container_name: java-backend
ports:
- "8080:8080"
frontend:
image: dukeyico/web-frontend:latest
build: ./frontend
container_name: web-frontend
ports:
- "5173:80"
depends_on:
- backendservices:
backend:
image: dukeyico/java-backend:latest
container_name: java-backend
restart: always
ports:
- "8080:8080"
frontend:
image: dukeyico/web-frontend:latest
container_name: web-frontend
restart: always
ports:
- "5173:80"
depends_on:
- backenddocker compose up --build
docker psAccess:
- Frontend → http://localhost:5173
- Backend → http://localhost:8080/api/students
ssh azureuser@20.0.250.3
sudo docker compose up -d
docker psAccess:
- Frontend → http://20.0.250.3:5173
- Backend → http://20.0.250.3:8080/api/students
Option 1: Clone Repository and Deploy
ssh azureuser@20.0.250.3
git clone https://github.com/dukeyico/docker-project.git
cd docker-project
sudo docker compose up -dOption 2: Manual Compose File Creation
ssh azureuser@20.0.250.3
nano docker-compose.yml
# Paste YAML content
sudo docker compose up -ddocker build -t dukeyico/java-backend:latest ./backend
docker build -t dukeyico/web-frontend:latest ./frontend
docker push dukeyico/java-backend:latest
docker push dukeyico/web-frontend:latestFile: .github/workflows/docker-publish.yml
name: CI/CD Pipeline - Build, Push, Deploy
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push backend image
uses: docker/build-push-action@v6
with:
context: ./backend
push: true
tags: dukeyico/java-backend:latest
- name: Build and push frontend image
uses: docker/build-push-action@v6
with:
context: ./frontend
push: true
tags: dukeyico/web-frontend:latest
- name: Deploy on Azure VM
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.VM_HOST }}
username: ${{ secrets.VM_USER }}
key: ${{ secrets.VM_SSH_KEY }}
script: |
sudo docker compose down
sudo docker pull dukeyico/java-backend:latest
sudo docker pull dukeyico/web-frontend:latest
sudo docker compose up -d| Secret Name | Description | Example |
|---|---|---|
DOCKERHUB_USERNAME |
Your Docker Hub username | dukeyico |
DOCKERHUB_TOKEN |
Docker Hub access token | dckr_pat_xxxxxxx |
VM_HOST |
Public IP address of your Azure VM | 20.0.250.3 |
VM_USER |
SSH username for your VM | azureuser |
VM_SSH_KEY |
Private SSH key content | -----BEGIN OPENSSH PRIVATE KEY----- ... |
How to Create Secrets
- Go to your GitHub repository → Settings
- Navigate to Secrets and variables → Actions
- Click New repository secret
- Add all five secrets listed above
docker ps
curl http://localhost:8080/api/students
curl http://localhost:5173Expected Result:
- Both containers run successfully.
- The frontend communicates properly with backend APIs.
| Issue | Cause | Fix |
|---|---|---|
| CORS & Cross-Container Networking | Different origins between containers | Added @CrossOrigin(origins="*") in Spring Boot |
| Dockerfile Build Path Errors | Wrong build context | Corrected working directory and JAR path |
| YAML Indentation Errors | Misplaced keys | Fixed indentation and validated YAML |
| VM Permission Denied | Root-owned files | Used sudo chown -R $USER:$USER ./ |
| API Connectivity | Wrong base URL | Updated frontend API to use VM IP |
✅ Containers deployed successfully on Azure VM ✅ Backend and frontend images published on Docker Hub ✅ CI/CD pipeline automates builds and pushes ✅ System accessible via public IP with working API calls
- Deployed containers visible via
docker ps - Images published on Docker Hub
- Successful GitHub Actions workflow runs
- Browser access to frontend and backend endpoints
- End-to-end Docker workflow from build to deployment
- Importance of automation in CI/CD pipelines
- Managing cloud infrastructure using Docker Compose
- Debugging network and permission issues on VMs
- Secure handling of GitHub secrets
| Deliverable | Description |
|---|---|
backend/Dockerfile |
Java backend container |
frontend/Dockerfile |
Nginx frontend container |
docker-compose.yml |
Multi-container orchestration |
.github/workflows/docker-publish.yml |
CI/CD pipeline configuration |
| Docker Hub Images | Published backend & frontend |
| Azure VM Deployment | Live deployed application |
| README.md | Full project documentation |
This project achieved complete automation of container build, deployment, and orchestration. Using Docker, Compose, and GitHub Actions, a reproducible two-tier web application was created and hosted on Azure Cloud VM. It demonstrates real-world DevOps, cloud deployment, and CI/CD best practices that align with enterprise standards.