### 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 ---