Author: Ahmed Rauf
In this project we are using Terraform to create an AWS infrastructure and initializing a bash script on an EC2 instance to run multiple Docker containers behind a web server that takes care of load-balancing and TLS certificates. I've introduced two types -
- Type 1: Executing Terraform manually from OS which follows the bash scripts within it's .tf file
- Type 2: Running a job on Jenkins, which pulls the updated repository from Github, updates the web app on remote server and executes the .tf script in the pipeline.
Computing and Open-source tools used in the project -
- AWS - Utilized VPC, Security Group, Routing tables, Elastic IP and EC2
- Terraform - IAAC tool to create, change, and modify AWS resources.
- Git - Pull update code from Git repo.
- Node.js - Run express.js with ejs to serve static html pages on dynamic routes.
- Caddy - Web server with an automatic TLS for https (used instead of Nginx because certbot requires an existing domain name and I am using just the public IP).
- Nip.io - Wildcard DNS for any IP address, which allows any IP address to be mapped on a hostname without a name.
- Docker - PAAS for OS virtualization with containers running a Node.js web server.
- Jenkins - Automation server to build, test and deploy software.
- Install Terraform on your OS
- Clone the existing repository on to your OS.
- Add a variables.tf file with existing server and access keys fetched from AWS.
- Run 'terraform plan' in terminal to understand what all resources will be created, modified or deleted from AWS.
- Run 'terraform apply' in terminal to execute the actions proposed in terraform plan.
- Wait approximately a minute for instance to be launched and initialized (also because of sleep command in the bash script of instance)
- Terraform outputs the public IP of the instance. Append .nip.io to the IP and type it any address bar, which will redirect to the deployed web app.
- Visit the currently deployed web server - https://44.208.7.171.nip.io/
- Once the page is refreshed, Caddy web server will follow its round robin - load balance policy and thus forward the request to the other container.
- Go to Jenkins URL .
- A user with read and build jobs only permissions has been created username - test and password - test123 for testing purposes.
- Once signed in, check in 'Status' to view all logs per stage in pipeline.
- We are also doing a git pull on the web app directory, and re-adding the docker containers.
- Same .tf file will be executed so downtime will be around 1 minute.
- Since we are running Jenkins on a differenct OS, another AWS instance will be created whose IP is https://3.209.230.120.nip.io/
- Installing all packages (Docker & Caddy)
- Cloning repository
- Creating log files and Caddy's config file to reverse proxy and load balance
- Starting Caddy
- Tool installation (Terraform)
- Cloning repository
- Initializing terraform
- Applying terraform's plan to production
- Updating web servers on remote server after a git pull
In the Type 1 deployment, we are utilizing bash scripts working with Terraform, this is a manual process and thus we have to execute the bash script on the OS. This is a one-time process and thus we have to wait for the instance to be launched and initialized. Once the instance is up and running, we can access the web app by appending .nip.io to the public IP of the instance.
When talking about the Type 2 deployment, it utilizes Jenkins to automate the process. We have to run the pipeline once and Jenkins will take care of the rest. It will pull the updated repository from Github, update the web app on remote server and execute the .tf script in the pipeline. This is a continuous process and thus we don't have to wait for the instance to be launched and initialized. Jekins also logs any existing error that occurs withing a stage of a pipeline. Once the pipeline is executed, we can access the web app by appending .nip.io to the public IP of the instance.
- Use Nginx (with a domain name) instead of Caddy as it's comparatively faster.
- Split and architect the bash script added in user-data of Terraform's EC2 resource into a pipeline