Docker containers and AWS Auto-scaling – Hand in Hand

14 / Sep / 2015 by Ranvijay Jamwal 0 comments

In my previous blog, I talked about setting up sendmail inside a Docker container. In this blog, we will talk about how to make your Docker containers come up during Auto-scaling of AWS servers, start, and use a service like sendmail inside them. You can make changes to scripts based on your use-case. I just want to make the logic clear.

cicd-with-docker-on-aws-1-638


Use-case 

I had a PHP application running inside my Docker container (CentOS 7 based), being served by httpd (Apache2). This was single container running on a host machine. A use-case arose when I thought of what would happen when the traffic to my website increased or the CPU utilization went high etc. . I would have to scale my containers i.e. launch a new server and run a container inside that. Also, what I needed to do is keep the containers isolated & check whether the container has come up in auto-scaling or not. So, that is what the blog is about. So, I have made a script which you can add to user data in Launch Configuration.

Prerequisites 

What I will assume is that  you already have a Docker container running (CentOS 7 based), and it is serving some PHP application through httpd.
Also, what more you need is :-

  1. An Auto-scaling group & Launch Configuration in your AWS account.
  2. Your host machine’s AMI added to the Launch Configuration.
  3. Latest image of your running container committed to Docker Hub or you may locally commit the container image & create an AMI from that and add to Launch Configuration group.
  4. Host machine may be Amazon Linux or CentOS/RedHat. ( Even Ubuntu, but commands may slightly differ)
  5. sendmail service installed & running on host machine. (This will be used to send an email when Docker container comes up)

How to implement it

Explanation : Lets talk about the scripts. As we know every time a new container starts the entry in /etc/hosts changes to default with the new container ID. As sendmail requires a domain name to work, we will be using 2 scripts for sendmail about which we talked about in the previous blog, first being dockerscriptetchosts.sh and the other being startsendmail.sh. Let us go through them one by one before we come to our main script autodeploy.sh

So, the first script for sendmail is dockerscriptetchosts.sh

#!/bin/bash

line=$(head -n 1 /etc/hosts) 
line2=$(echo $line | awk '{print $2}')

echo "$line $line2.localdomain" >> /etc/hosts

The above script has already been added to the image using ADD in Dockerfile. It makes the necessary entry to /etc/hosts of the Docker container which are as follows :-

container_IP container_id container_id.localdomain

Next script is startsendmail.sh.

#!/bin/bash
sudo docker exec -itd $1 bash /home/dockerscriptetchosts.sh
sudo docker exec -itd $1 /etc/init.d/sendmail start
sudo docker exec -itd $1 /usr/sbin/httpd -k restart

This script is present on the host machine & takes one parameter input (container_id) to execute which we will pass in the main script. It firstly runs docker exec command which in turn runs the command bash /home/dockerscriptetchosts.sh inside the Docker container and in turn the next commands. The last command restarts httpd.

The main script autodeploy.sh is below. Just go through it and I will explain the script just after that. You will need to put this bash script in the user-data.

[js]#!/bin/bash
sudo docker pull ranvijayj/prod:latest #this is if you want to pull from Docker Hub

container_id=$(docker run -idt -p 80:80 –restart="always" -v /mnt/code:/opt/code prod:latest)

#check whether container is running or not

sleep 5

if [ `docker inspect -f {{.State.Running}} $container_id` == "true" ]; then

echo "Container has restarted .. Volume mounted" | sendmail -s " Container has come up in autoscaling" ranvijay.jamwal@tothenew.com
sleep 20
http_status=$(curl -Is localhost:80 | head -n 1 | awk ‘{ print $2}’)

if [ $http_status == 200 ]; then

echo "Container is SERVING the website" | sendmail -s " Container is serving the website" ranvijay.jamwal@tothenew.com

#once the container has started we need to start the sendmail service
#startsendmail can be present in any directory of AMI
bash /home/ec2-user/startsendmail.sh

else
echo "Container has FAILED to serve the website.. http_status= $http_status" | sendmail -s " Container is NOT SERVING at port 80" ranvijay.jamwal@tothenew.com
fi

else
echo "Container has not restarted/started" | sendmail -s " Container has failed to come up in autoscaling & is NOT serving the website" ranvijay.jamwal@tothenew.com

fi [/js]

 

So, what the script is doing, is the following & we will understand it line by line :-

  1. Using the Docker image we have defined it launches a container in detached mode
  2. It also exposes port 80 to the outside world, mounts directory /mnt/code from host machine to /opt/code using -v switch,  sets the variable —restart to “always” for the container & the container ID is stored in the variable container_id. Inside /mnt/code is your PHP code. The httpd service will start on its own as I already added a CMD via Dockerfile i.e.
    ENTRYPOINT [“/usr/sbin/httpd”]
    CMD [“-D”,”FOREGROUND”,”-k”,”start”]
    or you can use Nginx etc. You might have done this already
  3. Sleep for 5 seconds
  4. The first if statement checks if the container has started & then sends an email to the specified email address according to the result. We are checking that using the command docker inspect -f {{.State.Running}} $container_id` & it should return a string “true”. Add a sleep of 20 seconds
  5. Next is checking if the container is serving the website on 80 port. For that we curl localhost:80. If it returns 200 then the website is working else it is not serving the website
  6. Now, since that is working, next is getting sendmail up & running. For that execute the dockersendmail.sh script. This will work as we discussed above.

Now, everything should be working fine & your docker container will start when your servers auto-scale.

FOUND THIS USEFUL? SHARE IT

Leave a Reply

Your email address will not be published. Required fields are marked *