START/STOP AWS Instance Using AWS-CLI, Docker, Docker-Compose and Bash Script

Using Docker Compose, create a service for the aws-cli and make sure to add stdin_open:true, tty:true and command:help to be able to prevent an immediate exit.

docker-compose.yml
services:
  aws:
    container_name: 'sample-aws'
    image: amazon/aws-cli:latest
    stdin_open: true # = -i
    tty: true        # = -t
    command: help
    volumes:
      - ./.aws:/root/.aws
    ports:
      - "8080:80"

Go inside the container and configure the aws by adding your credentials. It should create the directory .aws/. To make this tutorial simpler, I opted to configure it inside the container rather than making an environment variable.

Bash
docker exec -it sample-aws bash

Note: Make sure your instances have a tag like this to be able to identify them without entering the instance ID.

Create a bash script file named change-instance-state.sh and put it inside .aws/ directory.

Create a function to be re-used when starting and stopping an instance.

Bash
#!/bin/bash

change_instance_state() {
    action='.StartingInstances[0]';
    status='stopped'
    instances='start-instances'

    if [ $1 == "STOP" ]; then
        action='.StoppingInstances[0]';
        status='running'
        instances='stop-instances'
    fi

    # Get all instances with status of stopped or running with Tag Value of PRODUCTION. Lastly, get the instance-id and change the state
    aws ec2 describe-instances --query 'Reservations[*].Instances[*].[State.Name, InstanceId, Tags[0].Value]' --output text |
    grep ${status} |
    grep PRODUCTION |
    awk '{print $2}' |
    while read line; do 
        result=$(aws ec2 ${instances} --instance-ids $line)
        current_state=$(echo "$result" | jq -r "$action.CurrentState.Name")
        previous_state=$(echo "$result" | jq -r "$action.PreviousState.Name")
        echo "Previous State is: ${previous_state} and Current State is: ${current_state}"
    done
}

In my example, I used the command aws ec2 describe-instances to list all ec2 instances. I filtered them out using grep and awk to target only the PRODUCTION instance.

How did I get the result (previous and current state)? Install jq and you can parse the result of this $(aws ec2 ${instances} –instance-ids $line) line. You can skip this as I added it so that I can see the previous and current states of the instance.

Ask the users if they want to start or stop. Assign it to the variable USER_OPTION

Bash
read -p 'Do you want to START or STOP the production instance? ' USER_OPTION;

Write an if/else statement that decides the value of the USER_OPTION variable, then pass that value to the change_instance_state function. The double carets ^^ are just used to convert input to uppercase.

Bash
if [[ ${USER_OPTION^^} == "START" ]]; then
    echo 'STARTING THE PRODUCTION SERVER...'
    change_instance_state "START"
else
    change_instance_state "STOP"
fi

Lastly, to be able to execute this script outside of the container,

Bash
docker exec -it sample-aws /root/.aws/change-instance-state.sh

The output should look like this

Console Output
Do you want to START or STOP the production instance? start
STARTING THE PRODUCTION SERVER...
Previous State is: stopped and Current State is: pending

View gist here: https://gist.github.com/rinavillaruz/0443633aec8f189b044b0ad7febc4735

Leave a Reply