
# 🐳 Docker Deployment Guide for Product Project

## 🔍 What is Docker?

**Docker** is a platform that allows developers to **build, package, and run applications in isolated environments** called **containers**. It ensures your application runs consistently across different environments—local machines, servers, or the cloud.

### 🧱 Key Docker Concepts

#### 📦 Image
A **Docker image** is a **read-only template** that includes everything needed to run an application—OS, code, libraries, etc.  
> Think of it like a recipe for creating containers.

#### 🚢 Container
A **container** is a **running instance of an image**. It is isolated, lightweight, and includes everything the application needs to run.  
> Think of it like a ready-made dish from a recipe (image).

#### 💾 Volume
A **volume** is used to **persist data** outside the container’s lifecycle. It ensures your data isn’t lost even if the container stops or is deleted.  
> Useful for things like database storage.






---
This guide explains how to build and deploy a full-stack application using Docker. The project contains:

- 🧩 `productApp` — React frontend served via NGINX  
- ⚙️ `productSvc` — Spring Boot backend API  

## 📁 Project Folder Structure

```
your-project/
├── productApp/         # React frontend
│   ├── Dockerfile
│   ├── .env
│   └── nginx.conf
├── productSvc/         # Spring Boot backend
│   └── Dockerfile
├── nginx.conf          # NGINX config for serving React app (optional global config)
└── docker-compose.yml  # Compose file to run both services

```

📥 Clone the repository:

```bash
git clone <your-project-repo>
cd your-project
```

---

## 🚀 Deploying Individually

### 🔹 1. Deploy `productApp`

📌 **Why a Dockerfile is needed:**  
To containerize the React frontend, we need a `Dockerfile` that handles two main tasks:
1. **Build the app** using Node.js (install dependencies, compile React code).
2. **Serve the static build** using NGINX (a lightweight and efficient web server).

Without a `Dockerfile`, Docker won't know how to build and serve the React application.

**Dockerfile** (`productApp/Dockerfile`)

```Dockerfile
FROM node:16-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```

**Environment** `.env (productApp/.env):`
```
PUBLIC_URL=/product-ui
```

**NGINX Config** `(productApp/nginx.conf):`
```nginx
server {
    listen 80;

    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }
}
```

**Build and Run**

```bash
cd productApp
docker build -t product-ui .
docker run -d -p 3000:80 --name product-ui product-ui
docker ps
```

🌍 Open in browser: [http://localhost:3000/product-ui](http://localhost:3000/product-ui)

---

### 🔹 2. Deploy `productSvc`

📌 **Why a Dockerfile is needed:**  
To containerize the Spring Boot backend, we need a `Dockerfile` that:
1. **Builds the application JAR** using Gradle.
2. **Runs the JAR** inside a lightweight Java runtime image.

This ensures the backend service is self-contained and can run the same way across all environments (local, test, production). Without the `Dockerfile`, Docker cannot build or run your backend service as a container.

**Dockerfile** (`productSvc/Dockerfile`)

```Dockerfile
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY . .
RUN ./gradlew clean build -x test

FROM eclipse-temurin:21-jdk-alpine
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
```

**Build and Run**

```bash
cd productSvc

docker network create my-network

docker run -d --network my-network --name mysql-db -e MYSQL_ROOT_PASSWORD=S3cret -e MYSQL_DATABASE=productmngm -p 3306:3306 mysql:latest

docker build -t product-svc .

docker run -d --network my-network -p 8025:8025 --name product-service -e APP_INTERNAL_PORT=8025 -e DB_ADDRESS=mysql-db -e DB_PORT=3306 -e DB_NAME=productmngm -e DB_USERNAME=root -e DB_PASSWORD=S3cret product-svc

docker ps

```

🌍 API/Swagger available at: [http://localhost:8025/product-service/swagger-ui/index.html#/](http://localhost:8025/product-service/swagger-ui/index.html#/)

---

## 🧪 Running Both Services with Docker Compose (Using NGINX as Reverse Proxy)

Using Docker Compose, you can start both the frontend React app and backend Spring Boot service together, along with the database and NGINX server.

### What happens here?

- **NGINX acts as a reverse proxy:** It receives all incoming web requests on port 80 and forwards them to the right service based on the URL path.
- Requests to `/product-ui/` go to the React frontend.
- Requests to `/product-service/` go to the Spring Boot backend.
- This way, users access the whole app via one address (`http://localhost`) without worrying about different ports.

### Why do this?

- **One public port:** Only port 80 is exposed, so it’s easier to manage and safer.
- **Clean URLs:** Users see simple URLs with paths like `/product-ui` and `/product-service`.
- **Internal communication:** Services talk to each other inside the Docker network using container names, keeping things organized.
- **Flexible setup:** You can add more services later and route them through NGINX without changing how users connect.

### How NGINX helps

- Forwards requests correctly depending on the URL path.
- Adds useful headers to keep track of original client info.
- Can be extended for SSL, caching, or other web server features.

---

**🌐 NGINX Configuration**

```nginx
events {}

http {
    server {
        listen 80;

        location /product-service/ {
         proxy_pass http://productservice:8020/product-service/;
        }

        location /product-ui/ {
         proxy_pass http://product-ui:80/;
         }
    }
    }
}
```

**docker-compose.yml**

```yaml
version: '3.8'

services:
  product-svc:
    container_name: productservice
    build: ./productSvc
    ports:              
      - "8020:8020"
    environment:
      APP_INTERNAL_PORT: 8020
      DB_ADDRESS: mysql
      DB_PORT: 3306
      DB_NAME: productmngm
      DB_USERNAME: root
      DB_PASSWORD: S3cret
    depends_on:
      - mysql
    networks:
      - my-network  

  mysql:
    container_name: mysql
    image: mysql:latest
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: S3cret
      MYSQL_DATABASE: productmngm
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-network  

  nginx:
    container_name: nginx
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - product-svc
    networks:
      - my-network  

  product-ui:
    container_name: product-ui
    build: ./productApp     # path to your React app Dockerfile folder
    ports:
      - "8030:80"         
    networks:
      - my-network  

volumes:
  mysql-data:

networks:
  my-network:
    driver: bridge  

```

▶️ Start all services:

```bash
docker-compose up -d --build
docker ps
```

🛑 Stop all services:

```bash
docker-compose down
```

🌍 Product UI: [http://localhost/product-ui](http://localhost/product-ui)

🌍 API/SWAGGGER: [http://localhost/product-service/swagger-ui/index.html#/](http://localhost/product-service/swagger-ui/index.html#/)

---

