Web Server Deployment using Nginx and Docker
Before we start, there are definitely some prerequisites regarding this.
Prerequisites
An Ubuntu 20.04 server
-
Firewall rules allowing ssh on port 22, HTTP on port 80 and HTTPS on port 443 access
-
A static Public IP for the server
-
Ability to SSH into the server
-
A root password for the server as it will be needed in few steps
- (If you use an Private Key (.pem file) to SSH into the server, SSH into the server and use
sudo passwd <YOUR USERNAME>
to create a new password)
- (If you use an Private Key (.pem file) to SSH into the server, SSH into the server and use
-
An Account on Docker Hub with a private repository created (You can use any registry, just look up the instructions to do
docker login
.
SSH Into the Server
Install Docker
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
sudo apt update
Update the package database for Docker and Make sure you are about to install from the Docker repo instead of the default Ubuntu repo
apt-cache policy docker-ce
Finally install and check if Docker daemon is running
sudo apt install docker-ce
sudo systemctl status docker
Give docker command sudo privileges
sudo usermod -aG docker ${USER}
su - ${USER} # Password will be needed in this step
Confirm that you're in the docker group
id -nG
References: DigitalOcean
Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
References: DigitalOcean
Get access token from Docker Hub
-
Login to Docker Hub
-
Go to Account Settings
-
Go to Security
-
Click on New Access Token
-
Give your token a name
-
Generate new token and copy it somewhere safe and accessible and close the dialog box.
Login to Docker Hub
Login to Docker Hub on your server
docker --login username <USERNAME> # Replace <USERNAME> with your Docker Hub username
Make the docker-compose.yml file
cd ~
touch docker-compose.yml
nano docker-compose.yml
Paste the Following
Do note that you can change the number of services according to your preference
version: "3"
services:
frontend:
image: dockerhubusername/webapp:frontend # Docker Image of Frontend App
container_name: frontend
ports:
- "8000:80" # Replace 80 with your container port
backend:
image: dockerhubusername/webapp:backend # Docker Image of Backend App
container_name: backend
ports:
- "9000:80" # Replace 80 with your container port
Setup Nginx
Install Nginx
sudo apt update
sudo apt install nginx
Start and Enable Nginx
sudo systemctl start nginx
sudo systemctl enable nginx
Edit conf file for basic http server
sudo rm /etc/nginx/nginx.conf
sudo touch /etc/nginx/nginx.conf
sudo nano /etc/nginx/nginx.conf
Paste the following Configuration
Here also you've to keep the number of services in mind. If you're using only one container, remove the /api
block
worker_processes 1;
events {
worker_connections 1024;
}
http {
client_max_body_size 10M; # Maximum size a request can have
server {
client_max_body_size 10M; # Configure both values according to your application
server_name subdomain.domain.com; # Domain name for the server
# Pass all /api calls to backend
location /api {
client_max_body_size 10M;
proxy_pass http://localhost:9000;
}
location / {
client_max_body_size 10M;
proxy_pass http://localhost:8000;
}
}
}
Restart Nginx
sudo systemctl restart nginx
Starting the HTTP Server
docker-compose pull && docker-compose up -d
Setup your Domain
Enter the Public IP of your server in the DNS records of your Domain name as A Record, and your website should be up and running with HTTP on the domain.
Setting Up HTTPS and SSL with LetsEncrypt and CertBot
Install Prerequisites
sudo snap install certbot
Install CertBot
sudo certbot --nginx -d subdomain.domain.com
Enter all the follow up inputs required while generating certificate.
Test Automatic Renewal
sudo certbot renew --dry-run
Confirm that HTTPS is active now
Go to the your domain in your browser, and click on the Padlock to verify that the certificate issued is by LetsEncrypt.
References: Certbot
I have also written a followup post showing how you can setup an automatic Continuous Deployment (CD) environment setup for this deployment using Github Actions.