How to Set Up Nginx Reverse Proxy with Docker Containers for Multiple Applications
Learning how to set up Nginx reverse proxy with Docker containers for multiple applications is essential for modern web development. This configuration allows you to run multiple web services on a single server while maintaining clean URL routing and efficient resource management. You’ll discover how to create a scalable infrastructure that can handle different applications simultaneously.
This tutorial covers the complete process of configuring Nginx as a reverse proxy using Docker containers. You’ll learn to create a network architecture that routes traffic to different applications based on domain names or paths. The setup includes container orchestration, SSL certificate management, and load balancing capabilities.
By the end of this guide, you’ll have a fully functional reverse proxy system. This setup is perfect for hosting multiple websites, APIs, or web applications on one server. The containerized approach ensures easy deployment, scaling, and maintenance of your services.
Prerequisites and Requirements for Nginx Reverse Proxy with Docker Setup
Before starting this tutorial, ensure you have the necessary tools and knowledge. You’ll need a Linux server with root access and at least 2GB of RAM. Ubuntu 20.04 or newer is recommended for optimal compatibility.
Install Docker and Docker Compose on your system. These tools are essential for container management and orchestration. You should have basic familiarity with command-line operations and text editing using nano or vim.
Reserve at least 2 hours for completing this tutorial. The process involves multiple configuration steps and testing phases. Having domain names ready for testing will help you verify the setup properly.
Your server should have ports 80 and 443 available for HTTP and HTTPS traffic. Basic understanding of networking concepts like DNS and port forwarding will be helpful. Ensure you have sudo privileges to install packages and modify system configurations.
Step-by-Step Guide to Set Up Nginx Reverse Proxy with Docker Containers
For more strange history, see: How to Configure Nginx with Let’s Encrypt Ssl Certificate Using Certbot on Ubuntu
Step 1: Install Docker and Docker Compose
Start by updating your system packages and installing Docker. This foundation is crucial for container management throughout the tutorial.
sudo apt update
sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose -y
Add your user to the docker group to run commands without sudo. This step improves workflow efficiency and security practices.
sudo usermod -aG docker $USER
newgrp docker
Step 2: Create Project Directory Structure
Organize your project files in a logical directory structure. This organization makes maintenance and troubleshooting much easier.
mkdir ~/nginx-reverse-proxy
cd ~/nginx-reverse-proxy
mkdir nginx apps ssl logs
Create subdirectories for each application you plan to host. This example sets up directories for two sample applications.
mkdir apps/app1 apps/app2
mkdir nginx/conf.d
Step 3: Configure Nginx Reverse Proxy Settings
Create the main Nginx configuration file that will handle reverse proxy functionality. This file defines how traffic gets routed to different containers.
nano nginx/nginx.conf
Add the following configuration to establish the reverse proxy foundation:
events {
worker_connections 1024;
}
http {
upstream app1 {
server app1:3000;
}
upstream app2 {
server app2:4000;
}
server {
listen 80;
server_name app1.yourdomain.com;
location / {
proxy_pass http://app1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name app2.yourdomain.com;
location / {
proxy_pass http://app2;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Step 4: Create Sample Applications
Build simple Node.js applications for testing the reverse proxy setup. These applications will help verify that routing works correctly.
Create the first application:
nano apps/app1/package.json
{
"name": "app1",
"version": "1.0.0",
"main": "server.js",
"dependencies": {
"express": "^4.18.0"
}
}
nano apps/app1/server.js
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello from Application 1!');
});
app.listen(port, '0.0.0.0', () => {
console.log(`App1 listening on port ${port}`);
});
Create the Dockerfile for the first application:
nano apps/app1/Dockerfile
FROM node:16-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Repeat the process for the second application with different content and port 4000.
Step 5: Create Docker Compose Configuration
The Docker Compose file orchestrates all containers and manages networking between them. This configuration is central to how to set up Nginx reverse proxy with Docker containers for multiple applications.
nano docker-compose.yml
version: '3.8'
services:
nginx:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
- ./logs:/var/log/nginx
depends_on:
- app1
- app2
networks:
- proxy-network
app1:
build: ./apps/app1
container_name: app1
networks:
- proxy-network
app2:
build: ./apps/app2
container_name: app2
networks:
- proxy-network
networks:
proxy-network:
driver: bridge
Step 6: Launch and Test the Configuration
Start all containers using Docker Compose. This command builds the applications and starts the entire stack.
docker-compose up -d
Verify that all containers are running properly:
docker-compose ps
Check the Nginx logs to ensure there are no configuration errors:
docker-compose logs nginx
Test the setup by accessing your applications through the configured domain names. You can use curl for initial testing:
curl -H "Host: app1.yourdomain.com" http://localhost
curl -H "Host: app2.yourdomain.com" http://localhost
Troubleshooting Common Nginx Reverse Proxy Docker Issues
When containers fail to communicate, check the network configuration first. Ensure all services are connected to the same Docker network. Use docker network ls to verify network creation and docker network inspect proxy-network to check container connections.
DNS resolution problems often occur when container names don’t match upstream definitions. Verify that upstream server names in nginx.conf match the service names in docker-compose.yml exactly. Container names are case-sensitive and must be identical.
Port binding conflicts happen when multiple services try to use the same host ports. Check for existing services using sudo netstat -tulpn | grep :80 and stop conflicting services. Ensure your Docker Compose port mappings don’t conflict with system services.
Permission issues with mounted volumes can prevent Nginx from reading configuration files. Use sudo chown -R $USER:$USER ~/nginx-reverse-proxy to fix ownership problems. Check file permissions with ls -la to ensure read access.
Log analysis helps identify configuration problems quickly. Monitor real-time logs with docker-compose logs -f nginx and check application logs using docker-compose logs app1. The official Nginx documentation provides detailed troubleshooting guidance for complex issues.
Advanced Configuration and Security Considerations
SSL certificate integration enhances security for production deployments. Use Let’s Encrypt with Certbot to obtain free SSL certificates. Mount certificate directories into the Nginx container and update configuration to handle HTTPS traffic.
Load balancing capabilities can be added by defining multiple upstream servers for each application. This approach distributes traffic across multiple container instances and improves reliability. Configure health checks to automatically remove failed containers from the rotation.
Environment-specific configurations help manage different deployment scenarios. Use Docker Compose override files for development, staging, and production environments. The <a href="https://docs.docker.com/compose/" target="_blank
