NGINX configuration with docker
I am a MERN stack developer. Here to learn and share my knowledge to help other to grow.
Here are the answers to your questions based on the text provided and standard NGINX/Node.js practices.
Qustion 1: Which nginx configation structure is right for windoes os:
/etc/nginx/nginx.conf sites-enabled/default
Qustion 2: where do I need to configure the in my project folder build with node.js and try to running multilple worker process on it.
Question 3: can you explain it's meaning step by step:
events {}
http {
upstream realtime_backend {
server 127.0.0.1:5000;
}
server {
events {}
http {
upstream realtime_backend {
server 127.0.0.1:5000;
}
server {
listen 80;
location / {
proxy_pass
http://realtime_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade
$http_upgrade;
proxy_set_header Connection
"upgrade";
proxy_set_header Host $host;
proxy_cache_bypass
$http_upgrade;
}
}}
Question 1: Which NGINX configuration structure is right for Windows OS?
The Linux structure (/etc/nginx/nginx.conf and sites-enabled/default) does not exist by default on Windows.
On Windows, NGINX typically uses a single configuration file located at conf/nginx.conf inside your installation directory (e.g., C:\nginx\conf\nginx.conf). You do not have a sites-enabled folder unless you create it manually.
To replicate the Linux sites-enabled behavior on Windows:
Create folders named
sites-availableandsites-enabledinsideC:\nginx\conf\.Place your server configuration files (e.g.,
myapp.conf) insites-available.Create a symbolic link (using
mklink) or simply copy the file intosites-enabled.Crucial Step: Modify
conf/nginx.confto include the files in that folder using forward slashes:http { # ... other settings include conf/sites-enabled/*.conf; }
Note: On Windows, file paths in NGINX config usually require forward slashes (/) or escaped backslashes (\\), and wildcards work with forward slashes. https://serverfault.com/questions/49414/how-do-i-specify-windows-file-paths-in-nginx https://stackoverflow.com/questions/13070986/nginx-windows-setting-up-sites-available-configs
Question 2: Where do I configure the entry point for multiple worker processes in my Node.js project?
You need to create a new entry point file (often named cluster.ts, index.ts, or server.js) that sits outside your main application logic. This file uses the built-in cluster module to fork workers.
The Workflow:
Create
cluster.ts: This file checkscluster.isPrimary.If it is the Primary process: It forks workers using
cluster.fork()based on your CPU cores. It also listens for worker exits to auto-restart them.If it is a Worker process: It imports and runs your main application file (e.g.,
app.tsorserver.ts).
Update
package.json: Change thestartscript to run this new file, not your app directly."scripts": { "start": "ts-node cluster.ts", "dev": "ts-node cluster.ts" }Your
app.ts: This file should only contain your Express/Socket.IO setup and callapp.listen(). It should not contain any cluster logic.
This ensures your app can be run as a single process for development or scaled across all CPU cores for production simply by running npm start. https://medium.com/@vadacodez/configurable-cluster-mode-in-node-js-ac26c81d9741 https://nodejs.org/api/cluster.html
Question 3: Step-by-step explanation of the NGINX config
This configuration sets up a Reverse Proxy that forwards incoming HTTP/WebSocket traffic from port 80 to your Node.js backend running on port 5000.
| Line/Block | Meaning |
|---|---|
events {} |
Defines connection handling for NGINX workers. The empty block uses default settings (usually 1024 worker connections). |
http { ... } |
The main block for HTTP server configuration. Everything inside here handles web traffic. |
upstream realtime_backend { ... } |
Defines a logical name (realtime_backend) for your backend server group. Here, it points to 127.0.0.1:5000 (your Node.js app). If you had multiple Node instances, you would list them all here for load balancing. |
server { ... } |
Defines the virtual server that listens for incoming requests. |
listen 80; |
Tells NGINX to listen for traffic on the standard HTTP port 80. |
location / { ... } |
Matches all incoming URLs. |
proxy_pass http://realtime_backend; |
Forwards the request to the upstream group defined earlier (port 5000). |
proxy_http_version 1.1; |
Critical for WebSockets. Forces NGINX to use HTTP/1.1 instead of the default 1.0, which is required for the WebSocket Upgrade mechanism. |
proxy_set_header Upgrade $http_upgrade; |
Passes the Upgrade header from the client to the backend. This tells the backend the client wants to switch protocols to WebSocket. |
proxy_set_header Connection "upgrade"; |
Passes the Connection: upgrade header. Without this, the WebSocket handshake fails. |
proxy_set_header Host $host; |
Ensures the backend knows the original domain name requested by the client. |
proxy_cache_bypass $http_upgrade; |
Prevents NGINX from caching WebSocket connections (which are dynamic and long-lived), ensuring real-time data isn't stale. |
Summary: This config acts as a bridge. When a client connects to http://your-domain.com, NGINX accepts the connection, upgrades it to a WebSocket if requested, and pipes the data directly to your Node.js server on port 5000, keeping the connection open for real-time updates. https://websocket.org/guides/infrastructure/nginx/ https://nginx.org/en/docs/http/websocket.html
###===>>> Not understood, please explain step by step in easy language, I had never used nginx. this is my first time, I read about it, not implemented yet.
No problem! Let's break this down as if we are setting up a small shop. Imagine NGINX is the Receptionist at the front desk, and your Node.js app is the Worker in the back room.
1. The Problem (Why do we need NGINX?)
Your Node.js App: It's great at doing calculations and handling real-time data (like stock prices), but it's like a worker who is busy and can't talk to the customer directly without getting confused. It listens on a specific door (Port 5000).
The Customer (User's Browser): They don't know about "Port 5000". They just want to visit
yourwebsite.com(which is Port 80).The Solution (NGINX): NGINX stands outside the door. Customers come to NGINX (Port 80), and NGINX quietly passes the message to your Worker (Port 5000).
2. Question 1: Where is the config file on Windows?
On Linux (like Ubuntu), the file is usually at /etc/nginx/nginx.conf. On Windows, it is different.
Find your installation folder: usually
C:\nginx.Look for the config file: It is inside
conf\nginx.conf.- Full path:
C:\nginx\conf\nginx.conf
- Full path:
How to edit:
Open Notepad (or VS Code) as Administrator (Right-click -> Run as Administrator).
Open that file.
Note: Windows uses backslashes
\in normal paths, but NGINX on Windows prefers **forward slashes**/or **double backslashes**\\inside the config file.Example: Use
C:/nginx/htmlinstead ofC:\nginx\html.
3. Question 2: Where do I configure Node.js for multiple workers?
You don't change the NGINX file for this. You change your Node.js code.
Think of this as hiring 5 workers instead of 1.
Create a new file: Call it
cluster.js(orindex.js).The Logic:
This file asks the computer: "How many CPU cores do you have?" (e.g., 4).
It says: "Okay, I will start 4 copies of my app."
It tells the computer: "If one worker crashes, start a new one immediately."
Run it:
Instead of running
node app.js, you runnode cluster.js.NGINX doesn't care how many workers you have; it just sends traffic to the main door (Port 5000), and Node.js handles splitting it between the workers.
Simple Code Example (cluster.js):
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
// If this is the "Boss" process
if (cluster.isMaster) {
console.log(`Boss: Starting ${numCPUs} workers...`);
// Fork (copy) the app for every CPU core
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
// If a worker dies, the Boss makes a new one
cluster.on('exit', (worker) => {
console.log('Worker died. Making a new one...');
cluster.fork();
});
} else {
// If this is a "Worker" (a copy of the app)
// Import your main app file (e.g., app.ts or server.js)
require('./app');
}
4. Question 3: Explaining the NGINX Config Step-by-Step
Here is that config code you showed, translated into plain English.
events {}
Meaning: "Get ready to handle connections."
Simple English: This is the engine room. It tells NGINX how many people it can talk to at once. The default is usually fine.
http {
upstream realtime_backend {
server 127.0.0.1:5000;
}
Meaning: "Define a group name called
realtime_backendthat points to my app on port 5000."Simple English: We created a shortcut name. Instead of writing
127.0.0.1:5000everywhere, we just call itrealtime_backend.
server {
listen 80;
Meaning: "Listen for incoming traffic on Port 80."
Simple English: This is the front door. When a user types
http://your-site.com, they hit this port.
location / {
proxy_pass http://realtime_backend;
Meaning: "For any request (the
/means everything), send it to therealtime_backendgroup."Simple English: "Whatever the customer asks for, I will run to the back room (Port 5000) and ask my worker."
proxy_http_version 1.1;
Meaning: "Use HTTP version 1.1."
Simple English: Crucial for WebSockets. Old versions (1.0) hang up the phone too fast. 1.1 keeps the line open so real-time data (like stock charts moving) can flow.
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
Meaning: "Tell the worker: The customer wants to upgrade from a normal web page to a WebSocket (live connection)."
Simple English: Without these two lines, NGINX acts like a normal postman and drops the "Live Connection" request. These lines tell the worker: "Hey, keep this line open! It's a live stream!"
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
}
Meaning: "Pass the website name to the worker, and don't save (cache) the live data."
Simple English: Make sure the worker knows which site the customer visited, and don't show them a 5-second-old snapshot. Show them the live data.
Summary Checklist for You
Install NGINX on Windows.
Edit
C:\nginx\conf\nginx.confand paste the config above inside thehttp { ... }block.Create
cluster.jsin your Node project to run multiple workers.Run NGINX: Open terminal in the
C:\nginxfolder and typestart nginx.Run your Node app: Type
node cluster.js.Test: Open your browser to
http://localhost. You should see your app!
Does this make more sense now? Let me know if you want to see the exact code to put in cluster.js for your specific project!
### ===>>> What if I setup nginx by using docker, by using this command:
docker run -it --rm -d -p 8080:80 --name web nginx
That is a much easier and cleaner way to start! Using Docker removes the headache of Windows file paths, permissions, and manual installations.
However, since you are running it with docker run, there are three critical changes you need to make to your workflow compared to a standard Windows install:
1. The Configuration File Problem
When you run docker run -d --name web nginx, Docker starts a fresh, empty NGINX container. It does not know about the config file on your Windows machine (C:\nginx\conf\nginx.conf).
If you try to edit a file on your computer, Docker won't see it.
✅ The Solution: Mount a Volume You need to tell Docker: "Take the config file on my Windows computer and put it inside the container at the exact spot NGINX expects it."
Use this command instead (assuming your config file is named nginx.conf in your current folder):
docker run -it --rm -d -p 8080:80 --name web -v ${PWD}/nginx.conf:/etc/nginx/nginx.conf:ro nginx
-v ${PWD}/nginx.conf:/etc/nginx/nginx.conf: This maps your local file to the container.:ro: Means "Read Only" (safer, prevents accidental overwrites).
If you don't have a config file yet: You can copy the default config from the container to your computer first:
docker cp web:/etc/nginx/nginx.conf ./nginx.conf
# Now edit ./nginx.conf on your computer with your WebSocket config
# Then restart the container with the command above
2. The Port Change (Important!)
Your command maps port 8080 on your computer to port 80 inside the container.
Old way: You accessed
http://localhost(Port 80).New way: You must access
http://localhost:8080.
⚠️ Critical Warning for Node.js: In the NGINX config, you had proxy_pass http://127.0.0.1:5000.
Inside the Docker container,
127.0.0.1refers to the container itself, NOT your computer.Since your Node.js app is running on your computer (outside Docker), the container cannot reach
127.0.0.1:5000.
✅ The Fix: You have two options:
Option A: Use Docker Networking (Recommended for production) Run your Node.js app in a second container and link them.
Create a network:
docker network create my-app-netRun Node app:
docker run -d --name node-app --network my-app-net -p 5000:5000 your-node-imageChange NGINX config to:
proxy_pass http://node-app:5000;(Use the container namenode-appinstead of IP).
Option B: Use the Docker Host IP (Easiest for local dev) If your Node app is running directly on Windows (not in Docker), you need to tell the NGINX container how to reach your computer.
On Linux/Mac: Use
host.docker.internal.On Windows: Use
host.docker.internal(works in newer Docker Desktop versions) or your computer's local IP (e.g.,192.168.1.50).
Update your nginx.conf for Windows Docker:
upstream realtime_backend {
# Try this first. If it fails, use your computer's local IP (e.g., 192.168.1.10)
server host.docker.internal:5000;
}
If host.docker.internal doesn't work, find your Windows IP address (ipconfig in terminal) and use that IP instead.
3. The Steps to Run Everything
Here is the exact workflow using Docker:
Step 1: Prepare your Config
Create a file named
nginx.confin your project folder.Paste the WebSocket config you asked about earlier.
Change
server 127.0.0.1:5000;toserver host.docker.internal:5000;.
Step 2: Run Node.js (Your App) Make sure your Node app is running on port 5000 on your computer.
node cluster.js
Step 3: Run NGINX (The Proxy) Run the Docker command with the volume mount:
docker run -it --rm -d -p 8080:80 --name web -v ${PWD}/nginx.conf:/etc/nginx/nginx.conf:ro nginx
(Note: On Windows PowerShell, ${PWD} works. In CMD, use %CD%)
- CMD:
docker run ... -v %CD%/nginx.conf:/etc/nginx/nginx.conf:ro nginx
Step 4: Test Open your browser to: http://localhost:8080
Summary of Differences
| Feature | Standard Windows Install | Docker Install |
|---|---|---|
| Config Location | C:\nginx\conf\nginx.conf |
Inside container at /etc/nginx/nginx.conf |
| How to Edit | Edit file directly on disk | Edit file on disk + Mount volume (-v) |
| Accessing Local App | 127.0.0.1:5000 works |
host.docker.internal:5000 needed |
| Port to Open | http://localhost |
http://localhost:8080 |
| Cleanup | Stop service manually | docker stop web && docker rm web |
Which approach do you prefer?
Docker: Clean, isolated, but requires network config (
host.docker.internal).Standard Windows: Simpler networking (just
127.0.0.1), but you have to manage files and paths manually.
If you are a beginner and just want to test quickly on your own computer, Docker is still fine, just remember to use host.docker.internal in your config!