Load Balancer (Nginx)
April 7, 2025 ยท View on GitHub
This directory contains the configuration for the Nginx load balancer used in the MEAN Stack Contacts application.
Overview
The Nginx load balancer serves two primary purposes in this application:
- Unified Access Point: Provides a single entry point (port 80) to access both frontend and backend services
- Reverse Proxy: Routes requests to the appropriate container (Angular frontend or Express.js API)
Configuration
The core configuration is defined in nginx.conf:
events {
worker_connections 1024;
}
http {
upstream frontend {
# Reference to the Angular container
server angular:4000;
}
upstream backend {
# Reference to the Express.js container
server express:3000;
}
server {
listen 80;
server_name frontend;
server_name backend;
location / {
resolver 127.0.0.11 valid=30s;
proxy_pass http://frontend;
proxy_set_header Host $host;
}
location /api {
resolver 127.0.0.11 valid=30s;
proxy_pass http://backend;
proxy_set_header Host $host;
}
}
}
Key Components
upstreamBlocks: Define the backend server groupslocationDirectives:/: Routes all root requests to the Angular frontend/api: Routes all API requests to the Express.js backend
resolver: Used for Docker's internal DNS resolutionproxy_pass: Forwards requests to the appropriate upstream serverproxy_set_header: Preserves the original host information
Dockerfile
The Nginx container is built using the following Dockerfile:
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Usage
The load balancer is configured in the docker-compose.nginx.yml file at the root of the project:
nginx:
build: loadbalancer
container_name: ${ID_PROJECT:-mean}_nginx
restart: always
ports:
- "80:80"
links:
- express
- angular
Request Flow
When a user makes a request to the application:
- The request is received by Nginx on port 80
- Nginx examines the URL path:
- If it starts with
/api, the request is forwarded to the Express.js container - For all other paths, the request is forwarded to the Angular container
- If it starts with
- The appropriate service processes the request and sends a response
- Nginx forwards the response back to the client
HTTP Headers
The following headers are set for proxied requests:
Host: Set to the original host requested by the client
Accessing Services
With the load balancer in place, you can access services through these URLs:
- Frontend + API:
http://localhost - Frontend directly:
http://localhost:4000 - API directly:
http://localhost:3000
Advanced Configuration Options
For production deployments, consider enhancing the Nginx configuration with:
SSL Termination
server {
listen 443 ssl;
ssl_certificate /etc/nginx/certs/cert.pem;
ssl_certificate_key /etc/nginx/certs/key.pem;
# Rest of configuration...
}
HTTP/2 Support
server {
listen 443 ssl http2;
# Rest of configuration...
}
Caching Static Assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
Load Balancing Multiple Instances
For high availability, you can load balance across multiple instances of the frontend and backend:
upstream frontend {
server angular1:4000 weight=3;
server angular2:4000 weight=1;
server angular3:4000 backup;
}
upstream backend {
server express1:3000;
server express2:3000;
least_conn;
}
Rate Limiting
To protect the application from abuse:
# Define a limit zone
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;
# Apply rate limiting to the API
location /api {
limit_req zone=api_limit burst=10 nodelay;
proxy_pass http://backend;
}
Security Considerations
Enhance security with these settings:
# Hide nginx version
server_tokens off;
# Add security headers
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options SAMEORIGIN;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; font-src 'self'; connect-src 'self'";