Once you get into web hosting, the chances are high that at some point you will be interested in hosting multiple websites on a single server. While the setup might be complex with LMDS you should get it going in a few minutes.
LMDS will allow you to launch a fully functional Web Server in one click and host as many websites as you like using NGINX Docker containers.
If you're not familiar with LMDS, please check out this article on LMDS overview first. If you're just looking to deploy it, follow this FAQ on how to do so. When deploying the LMDS system, the web server option is one of many choices available in the menu.
In this article, we will only look at the WebServer functionality of LMDS.
Currently WebServer Stack include:
The entire stack can be built with one selection in the LMDS menu. Scripts will create or update the existing docker-compose.yml
file, which will be used to build a WebServer Stack. Scripts will create a folder structure and place required config files in it - these config files can be later adjusted to meet your requirements.
The script will also install sftpd service (sFTP Server) so you can easily upload website projects into relevant Nginx instances.
The script will build two independent Nginx containers to run two independent websites on a single host. These Web Servers will be available on ports 60101 and 60102. Initial build will create the folder structure shown below, which can be later multiplied to run more Nginx servers if needed.volumes
└── WebServ
├── nginx01
│ ├── config
│ │ └── conf.d
│ │ └── site.conf
│ └── www
│ └── html
│ └── index.php
├── nginx02
│ ├── config
│ │ └── conf.d
│ │ └── site.conf
│ └── www
│ └── html
│ └── index.php
The server has been completely configured to execute PHP code of version 8.2 through FastCGI.
Web Server deployment also includes a Docker container for MariaDB and phpMyAdmin to manage this database using a browser.
You do not need to change any config files after initial deployment. LMDS WebServer is ready to go immediately after being created.
Just paste LMDS WebServer IP address in to a browser, followed by one of two port (60101 and 60102), and if all went well, you should see similar result to what you see below:
If you see above, LMDS WebServer is ready to host your projects. All what you have to do now, is to copy your project files in to it:
Locations:
~/LMDS/volumes/WebServ/nginx01/www/html/
~/LMDS/volumes/WebServ/nginx02/www/html/
I suggest you use WinSCP to transfer your files in to the server.
After completing the steps in part one, you should have two separate Docker containers running web servers independently.
To create additional Nginx containers and host more websites, follow instructions below.
Duplicate nginx01
folder by making a copy of it with a different name i.e. nginx03
cp -r ~/LMDS/volumes/WebServ/nginx01 ~/LMDS/volumes/WebServ/nginx03
From having below.
volumes
└── WebServ
├── nginx01
│ ├── config
│ │ └── conf.d
│ │ └── site.conf
│ └── www
│ └── html
│ └── index.php
├── nginx02
│ ├── config
│ │ └── conf.d
│ │ └── site.conf
│ └── www
│ └── html
│ └── index.php
We should end up with this.
volumes
└── WebServ
├── nginx01
│ ├── config
│ │ └── conf.d
│ │ └── site.conf
│ └── www
│ └── html
│ └── index.php
├── nginx02
│ ├── config
│ │ └── conf.d
│ │ └── site.conf
│ └── www
│ └── html
│ └── index.php
├── nginx03
│ ├── config
│ │ └── conf.d
│ │ └── site.conf
│ └── www
│ └── html
│ └── index.php
In order for our new web server to work correctly, we have to change its configuration file located in:: ~LMDS/volumes/WebServ/nginx03/config/conf.d/site.conf
.
nano volumes/WebServ/nginx03/config/conf.d/site.conf
Replace nginx01
in two places with the name of the duplicated folder (in my case, nginx03
), and save the file.
server {
listen 80;
server_name nginx03; # <- here
# Log files for Debug
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
# web root directory
root /var/www/html/nginx03; # <- and here
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
# Nginx Pass requests to PHP-FPM
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php-fpm8:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
client_max_body_size 256M;
}
}
docker-compose.yml
Now add another Nginx container declaration to docker-compose.yml
file.
nano ~/LMDS/docker-compose.yml
docker-compose.yml
file and duplicate the container declaration by copying and pasting it below in the same file.nginx01
with a name you gave to the folder while duplicating it above, in my case it will be nginx03
.container_name
by giving it a distinct name for me next server container will be called Web-Serv3
, then change a port number to any you like, which will be used later to communicate with the Nginx container, in my case I used port 60103
. See the example below.from:
#######################################
# NGINX Servers (WebServ NPMP)
nginx01:
image: nginx:latest
container_name: Web-Serv1
restart: unless-stopped
tty: true
ports:
- 60101:80
volumes:
- ./volumes/WebServ/nginx01/www/html/:/var/www/html/nginx01
- ./volumes/WebServ/nginx01/config/conf.d/:/etc/nginx/conf.d
links:
- php-fpm8
depends_on:
- php-fpm8
to:
#######################################
# NGINX Servers (WebServ NPMP)
nginx01:
image: nginx:latest
container_name: Web-Serv1
restart: unless-stopped
tty: true
ports:
- 60101:80
volumes:
- ./volumes/WebServ/nginx01/www/html/:/var/www/html/nginx01
- ./volumes/WebServ/nginx01/config/conf.d/:/etc/nginx/conf.d
links:
- php-fpm8
depends_on:
- php-fpm8
nginx03:
image: nginx:latest
container_name: Web-Serv3
restart: unless-stopped
tty: true
ports:
- 60103:80
volumes:
- ./volumes/WebServ/nginx03/www/html/:/var/www/html/nginx03
- ./volumes/WebServ/nginx03/config/conf.d/:/etc/nginx/conf.d
links:
- php-fpm8
depends_on:
- php-fpm8
docker-compose.yml
file and add another volume path into our PHP-8-FPM
container.
# PHP8 FPN (WebServ NPMP)
php-fpm8:
image: php:8.2-fpm
container_name: PHP-8-FPM
restart: unless-stopped
volumes:
- ./volumes/WebServ/nginx01/www/html/:/var/www/html/nginx01
- ./volumes/WebServ/nginx02/www/html/:/var/www/html/nginx02
# PHP8 FPN (WebServ NPMP)
php-fpm8:
image: php:8.2-fpm
container_name: PHP-8-FPM
restart: unless-stopped
volumes:
- ./volumes/WebServ/nginx01/www/html/:/var/www/html/nginx01
- ./volumes/WebServ/nginx02/www/html/:/var/www/html/nginx02
- ./volumes/WebServ/nginx03/www/html/:/var/www/html/nginx03
Save the file and exit, then run:
docker-compose up -d --remove-orphans
If all went well you should see another WebServer being created.
pi@raspberrypi:~/LMDS $ docker-compose up -d --remove-orphans
MariaDB is up-to-date
Recreating PHP-8-FPM ...
portainer is up-to-date
Recreating PHP-8-FPM ... done
Recreating Web-Serv2 ... done
Recreating Web-Serv1 ... done
Creating Web-Serv3 ... done
After configuring your new Web Server, you can access it by pointing your browser to the IP address of your host followed by the port number you declared. In my case, it will be http://ip:60103
.
If you need to manage multiple websites, you can create separate Nginx containers for production, development, testing, and more. You don't have to run all the containers at once. Instead, you can spin up the one you need and shut it down when you're done, or keep them running 24/7. This should help you manage your resources efficiently and ensures that your websites are separated and working optimally.
At this point, you have successfully set up all the Web Servers in separate containers. However, each of them has a different port number, which could be a problem while exposing them to the Internet. If you want to make these servers accessible through the Internet, you will need a domain name and a proxy container like Traefik. Traefik will route each specific domain to a specific container and port number, but setting this up is more advanced task. If you are interested in trying this out, you can check out my other article in the FAQ section titled How to setup Traefik 2 on Docker with Cloudflare and Let's Encrypt.
With your support anything is possible