Hi! In this post I’d like to show you how to configure Nginx to have many websites using the same host.
Architecture
In reality we’d like to have 3 Docker containers with Nginx inside:
- website-a
- website-b
- reverse-proxy
Website Dockerfile
This is website Dockerfile:
FROM node:12-alpine as build
WORKDIR /app
COPY . .
FROM nginx:stable-alpine
COPY --from=build /app/public /bin/www
COPY --from=build /app/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD [ "nginx", "-g", "daemon off;" ]
In public directory is our website - HTML, CSS and JS files.
File called nginx.conf is a file in which Nginx configuration sits. Here is an example of such a file:
server {
listen 80;
location / {
root /bin/www/;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
Above configuration simply consists pointer to the root folder containing website files.
Based on this configuration we can create images of our two websites - website-a and website-b.
Reverse proxy Dockerfile
This is a reverse proxy Dockerfile:
FROM nginx:stable-alpine
COPY ./main.conf /etc/nginx/conf.d/default.conf
CMD [ "nginx", "-g", "daemon off;" ]
It’s much simpler than the previous Dockerfile. Apart from the parent image it only contains Nginx configuration.
Here is an example of Nginx configuration for HTTP:
server {
listen 80;
server_name a.com www.a.com;
location / {
proxy_pass http://website-a;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
server {
listen 80;
server_name b.com www.b.com;
location / {
proxy_pass http://website-b;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
This is a modified version for HTTPS:
server {
listen 80;
server_name a.com www.a.com;
return 301 https://$server_name$request_uri;
}
server {
listen 80;
server_name b.com www.b.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name a.com www.a.com;
ssl on;
ssl_certificate /certs/a.crt;
ssl_certificate_key /certs/a.key;
location / {
proxy_pass http://website-a;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
server {
listen 443 ssl;
server_name b.com www.b.com;
ssl on;
ssl_certificate /certs/b.crt;
ssl_certificate_key /certs/b.key;
location / {
proxy_pass http://website-b;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
To make it work we need to run containers. We achieve that using docker-compose:
version: '3'
services:
website-a:
image: website-a-image
website-b:
image: website-b-image
reverse-proxy:
image: reverse-proxy-image
ports:
- 80:80
- 443:443
volumes:
- ./certs:/certs
links:
- "website-a"
- "website-b"
In ./certs directory on host machine we need to provide certificates for a.com and b.com. For development purpose it’s recommended to create self-signed certificates using OpenSSL command tool. Additionally to test the whole setup it’s also useful is configure local DNS - hosts file so that we can map a.com and b.com to 127.0.0.1.
Hope you enjoyed!