commit 5e9b137d3fdfe6108d10ae5878d4c002edcff893 Author: Marius Grosu Date: Thu Jan 29 19:05:51 2026 +0200 My first basic loadBalancer diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e1effcb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +# Use the official Node.js 18 image as the base image +FROM node:18-alpine + +# Set the working directory inside the container +WORKDIR /app + +# Copy package.json and package-lock.json to the working directory +COPY package*.json . + +# Install project dependencies +RUN npm install + +# Copy the rest of the application code to the working directory +COPY . . + +# Expose port 3000 for the application +EXPOSE 3000 + +# Start the application +CMD ["node", "server.js"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3a41848 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,43 @@ +version: '3.9' +services: + app-1: + image: node-app:v1 + ports: + - "3001:3000" + networks: + - app-network + environment: + - INSTANCE_NAME=app-1 + + app-2: + image: node-app:v1 + ports: + - "3002:3000" + networks: + - app-network + environment: + - INSTANCE_NAME=app-2 + + app-3: + image: node-app:v1 + ports: + - "3003:3000" + networks: + - app-network + environment: + - INSTANCE_NAME=app-3 + + + nginx: + image: nginx:alpine + ports: + - "80:80" + volumes: + - ./files/nginx.conf:/etc/nginx/nginx.conf:ro + networks: + - app-network + + +networks: + app-network: + driver: bridge \ No newline at end of file diff --git a/files/README.md b/files/README.md new file mode 100644 index 0000000..36084bd --- /dev/null +++ b/files/README.md @@ -0,0 +1,218 @@ +### Documentatie Stack Node.js + Docker + Docker Compose + Nginx + +--- + +# 1. Structura proiect + +``` +project/ +│ +├── Dockerfile # imaginea Node.js +├── docker-compose.yml # orchestration containere + Nginx +├── nginx.conf # configuratie Nginx +├── server.js # cod Node.js +├── package.json +└── index.html # pagina servita de Node +``` + +Stack-ul include: + +* Node.js – aplicatie stateless +* 3 containere Node, fiecare cu INSTANCE_NAME +* Nginx – reverse proxy si load balancer +* Docker Compose – orchestrare containere + retea + +--- + +# 2. Node.js + +## 2.1 server.js + +```js +const express = require('express'); +const path = require('path'); + +const instanceName = process.env.INSTANCE_NAME || 'unknown'; + +const app = express(); +const port = 3000; + +app.get('/', (req, res) => { + console.log(`[${instanceName}] Request received`); + res.sendFile(path.join(__dirname, 'index.html')); +}); + +app.listen(port, () => { + console.log(`[${instanceName}] Node app listening on port ${port}`); +}); +``` + +Explicatii: + +* `process.env.INSTANCE_NAME` pentru identificarea containerului +* Stateless design – aplicatia nu stie cate instante exista +* Log-urile arata care container a servit request-ul +* Servește `index.html` + +## 2.2 package.json + +```json +{ + "name": "node-app", + "version": "1.0.0", + "scripts": { + "start": "node server.js" + }, + "dependencies": { + "express": "^4.17.1" + } +} +``` + +--- + +# 3. Dockerfile + +```dockerfile +FROM node:18-alpine + +WORKDIR /app + +COPY package*.json . +RUN npm install + +COPY index.html . +COPY server.js . + +EXPOSE 3000 + +CMD ["node", "server.js"] +``` + +Explicatii: + +* Imagine oficiala Node minimală +* COPY package*.json pentru caching optim +* EXPOSE 3000 – port intern container +* CMD – comanda de start + +--- + +# 4. Docker Compose + +```yaml +version: "3.9" + +services: + app-1: + image: node-app:v1 + ports: + - "3001:3000" + networks: + - app-network + environment: + - INSTANCE_NAME=app-1 + + app-2: + image: node-app:v1 + ports: + - "3002:3000" + networks: + - app-network + environment: + - INSTANCE_NAME=app-2 + + app-3: + image: node-app:v1 + ports: + - "3003:3000" + networks: + - app-network + environment: + - INSTANCE_NAME=app-3 + + nginx: + image: nginx:alpine + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + depends_on: + - app-1 + - app-2 + - app-3 + ports: + - "80:80" + networks: + - app-network + +networks: + app-network: +``` + +Explicatii: + +* 3 servicii Node identice, fiecare pe port intern 3000 +* Nginx ascultă pe port 80 și face proxy la Node +* `depends_on` pentru startup order +* retea comuna + +--- + +# 5. Nginx Configuration (nginx.conf) + +```nginx +events {} + +http { + upstream backend { + server app-1:3000; + server app-2:3000; + server app-3:3000; + } + + server { + listen 80; + + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + } +} +``` + +Explicatii: + +* `upstream backend` = grup backend-uri Node pentru load balancing +* `proxy_pass http://backend;` trimite request-ul la unul din backends +* Header-ele ajuta Node sa stie IP-ul real +* Nginx foloseste portul intern 3000 + +--- + +# 6. Workflow + +1. Build Node.js: + +```bash +docker build -t node-app:v1 . +``` + +2. Pornire Compose: + +```bash +docker-compose up -d +``` + +3. Verificare log-uri: + +```bash +docker-compose logs -f +``` + +4. Test load balancing: + +* [http://localhost](http://localhost) +* Refresh repetat → request-urile distribuite între app-1, app-2, app-3 + +--- diff --git a/files/index.html b/files/index.html new file mode 100644 index 0000000..e69de29 diff --git a/files/nginx.conf b/files/nginx.conf new file mode 100644 index 0000000..a881a01 --- /dev/null +++ b/files/nginx.conf @@ -0,0 +1,22 @@ +events { + worker_connections 1024; +} + +http { + upstream backend { + server app-1:3001; + server app-2:3002; + server app-3:3003; + } + + + server { + listen 80; + + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + } +} \ No newline at end of file diff --git a/files/package.json b/files/package.json new file mode 100644 index 0000000..f68b593 --- /dev/null +++ b/files/package.json @@ -0,0 +1,10 @@ +{ +"name": "node-app", +"version": "1.0.0", +"scripts": { +"start": "node server.js" +}, +"dependencies": { +"express": "^4.17.1" +} +} \ No newline at end of file diff --git a/files/server.js b/files/server.js new file mode 100644 index 0000000..0d9359b --- /dev/null +++ b/files/server.js @@ -0,0 +1,20 @@ +const express = require('express'); +const path = require('path'); + + +const instanceName = process.env.INSTANCE_NAME || 'unknown'; + + +const app = express(); +const port = 3000; + + +app.get('/', (req, res) => { +console.log(`[${instanceName}] Request received`); +res.sendFile(path.join(__dirname, 'index.html')); +}); + + +app.listen(port, () => { +console.log(`[${instanceName}] Node app listening on port ${port}`); +}); \ No newline at end of file