This article provides a template to easily configure the deployment of multiple websites on one server IP or on one droplet from digitalocean. Reverse-proxy, nginx configuration files and SSL certificate are created automatically for each website running in a Docker container.
Contents:
Prerequisites
Required tools and create domain names
- Git, docker and docker-compose are installed on your server
- Several websites run inside Docker containers on a single server. (Each one could either be a static files server, or WordPress running on Apache, etc.
- The domain name for each website is configured to point to the IP of the server. Your host must be publicly reachable on both port
80
and443
. Check your firewall rules to make sure that these ports are open. - Create a website directory and set up proper permissions. In this tutorial, we’ll assume that the web directory is at
/srv/www
Step 1: Create websites directories
Read more: Create a website directory and set up proper permissions
# 0. settings
web_dir=/srv/www
myusername=kassambara
# 1. Create the website directory
sudo mkdir -p $web_dir
# 2. set your user as the owner
sudo chown -R $myusername $web_dir
# 3. set the web server as the group owner
sudo chgrp -R www-data $web_dir
# 4. 755 permissions for everything
sudo chmod -R 755 $web_dir
# 5. New files and folders inherit
# group ownership from the parent folder
chmod g+s $web_dir
Step 2: Download a template
Download a template into your website directories www
web_dir=/srv/www
git clone https://github.com/kassambara/nginx-multiple-https-websites-on-one-server $web_dir
Step 3: Inspect the project structure and configuration files
Project Structure
www
├── README.Rmd
├── README.md
├── nginx-proxy
│ ├── certs
│ ├── conf.d
│ ├── docker-compose.yml
│ ├── html
│ ├── nginx.tmpl
│ └── vhost.d
├── your-website-one.com
│ ├── docker-compose.yml
│ └── index.html
└── your-website-two.com
├── docker-compose.yml
└── index.html
Inside /nginx-proxy
, there are four empty directories: conf.d
, vhost.d
, html
and certs
. These are used to store the nginx and the Let’s Encrypt configuration files.
Inspect the docker-compose.yml configuration file
Inside /nginx-proxy/
, there is a docker-compose.yml file with this content:
version: '3.6'
services:
nginx:
image: nginx
labels:
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
container_name: nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./vhost.d:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs:ro
nginx-gen:
image: jwilder/docker-gen
command: -notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
container_name: nginx-gen
restart: unless-stopped
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./vhost.d:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs:ro
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
nginx-letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion
container_name: nginx-letsencrypt
restart: unless-stopped
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./vhost.d:/etc/nginx/vhost.d
- ./html:/usr/share/nginx/html
- ./certs:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
NGINX_DOCKER_GEN_CONTAINER: "nginx-gen"
NGINX_PROXY_CONTAINER: "nginx"
networks:
default:
external:
name: nginx-proxy
This will launch three services:
nginx
: the nginx-reverse proxy, uses the default nginx image. The label is needed so that the letsencrypt container knows which nginx proxy container to use.nginx-gen
: uses the jwilder/docker-gen image. Its command instruction will render a nginx configuration (based on nginx.tmpl) for each website / container added to the network.nginx-letsencrypt
: generates and renew the HTTPS certificates.
All these services are bound to the nginx-proxy
network.
Update nginx.tmpl: Nginx configuration file template
Inside /nginx-proxy/
, there is a nginx.tmpl file. This is the used by the nginx-gen
container to create the nginx configuration file for each website / container added to the network.
Download the latest updated version from Github here:
# Remove old version
rm -rf $web_dir/nginx-proxy/nginx.tmpl
# Download new version
curl -s https://raw.githubusercontent.com/jwilder/nginx-proxy/master/nginx.tmpl> $web_dir/nginx-proxy/nginx.tmpl
Step 4: Run the nginx reverse proxy
# 1. Create the docker network
docker network create nginx-proxy
# 2. Create the reverse proxy with the
# nginx, nginx-gen and nginx-letsencrypt containers
cd /srv/www/nginx-proxy/
docker-compose up -d
Step 5: Link a website to the running nginx-proxy
The docker-compose.yml
file of the website, you want to link, should include the following instructions provided in the template available in the folder your-website-one.com
(not the one from nginx-proxy above). The content of the template looks like this:
version: '3.6'
services:
my-app:
image: nginx
restart: always
environment:
# NGINX-PROXY ENVIRONMENT VARIABLES: UPDATE ME
- VIRTUAL_HOST=your-website-one.com
- VIRTUAL_PORT=80
- LETSENCRYPT_HOST=your-website-one.com
- LETSENCRYPT_EMAIL=your.email@domain.com
# END NGINX-PROXY ENVIRONMENT VARIABLES
expose:
- 80
networks:
default:
external:
name: nginx-proxy
- Environment variables:
VIRTUAL_HOST
: your domain name, used in the nginx configuration.VIRTUAL_PORT
: (optional) the port your website is listening to (default to 80).LETSENCRYPT_HOST
: your domain name, used in the Let’s Encrypt configuration.LETSENCRYPT_EMAIL
: your email, used in the Let’s Encrypt configuration.
- Ports:
- the exposed port (here 80) should be the same as the
VIRTUAL_PORT
above.
- the exposed port (here 80) should be the same as the
- Network:
- your website container should be linked to the external docker network named
nginx-proxy
- your website container should be linked to the external docker network named
Once the update of the docker-compose.yml
file is done, you can start the website with:
cd /srv/www/your-website-one.com
docker-compose up -d
The website is automatically detected by the reverse proxy, has a HTTPS certificate and is visible at https://your-website-one.com.
You can repeat this last step for any other container you want to proxy
Frequently asked question
How to redirect from http non-www to https www?
If you have control of the DNS record, the best practice is to take care it with an ALIAS ( or CNAME). See discussion.
Solution 1. Use redirect container. Catch all http redirect, useful for http -> https redirects. Insanely fast and small! Based on alpine and nginx. Source: cusspvz/redirect.docker
version: '3.6'
services:
www.omicstudio.com:
image: nginx
restart: always
volumes:
- "./:/usr/share/nginx/html"
environment:
- VIRTUAL_HOST=www.omicstudio.com
- VIRTUAL_PORT=80
- LETSENCRYPT_HOST=www.omicstudio.com
- LETSENCRYPT_EMAIL=alboukadel.kassambara@gmail.com
# redirect omicstudio.com to www.omicstudio.com
omicstudio.com:
image: cusspvz/redirect
restart: always
environment:
- VIRTUAL_HOST=omicstudio.com
- VIRTUAL_PORT=80
- HTTPS_METHOD=noredirect
- LETSENCRYPT_HOST=omicstudio.com
- REDIRECT=https://www.omicstudio.com
# See available redirect parameters: https://github.com/cusspvz/redirect.docker
- WORKER_CONNECTIONS=1024
networks:
default:
external:
name: nginx-proxy
Solution 2. see this merge request: Added VIRTUAL_HOST_ALIAS support
Recommended for you
This section contains best data science and self-development resources to help you on your path.
Books - Data Science
Our Books
- Practical Guide to Cluster Analysis in R by A. Kassambara (Datanovia)
- Practical Guide To Principal Component Methods in R by A. Kassambara (Datanovia)
- Machine Learning Essentials: Practical Guide in R by A. Kassambara (Datanovia)
- R Graphics Essentials for Great Data Visualization by A. Kassambara (Datanovia)
- GGPlot2 Essentials for Great Data Visualization in R by A. Kassambara (Datanovia)
- Network Analysis and Visualization in R by A. Kassambara (Datanovia)
- Practical Statistics in R for Comparing Groups: Numerical Variables by A. Kassambara (Datanovia)
- Inter-Rater Reliability Essentials: Practical Guide in R by A. Kassambara (Datanovia)
Others
- R for Data Science: Import, Tidy, Transform, Visualize, and Model Data by Hadley Wickham & Garrett Grolemund
- Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow: Concepts, Tools, and Techniques to Build Intelligent Systems by Aurelien Géron
- Practical Statistics for Data Scientists: 50 Essential Concepts by Peter Bruce & Andrew Bruce
- Hands-On Programming with R: Write Your Own Functions And Simulations by Garrett Grolemund & Hadley Wickham
- An Introduction to Statistical Learning: with Applications in R by Gareth James et al.
- Deep Learning with R by François Chollet & J.J. Allaire
- Deep Learning with Python by François Chollet
Version: Français
`chmod g+s $web_dir` is not working. You should use `sudo chmod g+s $web_dir`
There has been an update to the nginx-letsencrypt docker: it is essential now to also mount volume ./acme:/etc/acme.sh, or else the docker image will fetch a new certificate from letsencrypt on every restart – and that will quickly exceed the allowed 5 certs/week.
Thank you for your valuable comment. We’ll update ASAP.