ruk·si

AWS
Setup EB + Docker

Updated at 2015-10-06 20:02

This is a simple guide how to run generic Docker container in Elastic Beanstalk, behind load balancer and optional auto-scaling.

You need to have Docker Toolbox, Go, Python and AWS command line tools installed.

pip install awscli awsebcli

# list available elastic beanstalk platform in a region
eb platform list -r us-west-2
# we are going to use the docker-1.7.1

Write the Application

# example project name is `gurgle`
mkdir gurgle
cd gurgle
touch Dockerfile
touch Dockerrun.aws.json    # extra attributes for EB
FROM ubuntu:trusty
RUN apt-get update
RUN apt-get install -y nginx
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
EXPOSE 80
CMD ["/usr/sbin/nginx", "-c", "/etc/nginx/nginx.conf"]

Dockerrun.aws.json has stuff like logging path, S3 credentials where to pull optional Docker image, optionally specify Docker image if not using a Dockerfile, define volumes,

{
  "AWSEBDockerrunVersion": "1",
  "Logging": "/var/eb-log"
}
# Run locally with
eb local run

## OR, USE DOCKER COMMANDS...

# Create a new image using the Dockerfile, for local testing.
docker build -t gurgle-img .

# Run container based on that image.
docker run -i -t --net=host --rm --name=gurgle-run gurgle-img
# You should now be able to access nginx at http://dockerhost
curl dockerhost

# SSH into the running container.
docker exec -i -t gurgle-run /bin/bash

Defining the Elastic Beanstalk application

Create new key pair. EC2 > Key Pairs > Create Key Pair. Name it eb-gurgle. Move it to ~/.ssh and execute chmod 0600 eb-gurgle.pem on it.

Create service-role-trust.json.

{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "1",
        "Effect": "Allow",
        "Principal": {
          "Service": "elasticbeanstalk.amazonaws.com"
        },
        "Action": "sts:AssumeRole",
        "Condition": {
          "StringEquals": {
            "sts:ExternalId": "elasticbeanstalk"
          }
        }
      }
    ]
}

Create instance-profile-trust.json.

{
    "Version" : "2012-10-17",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

Create a new role eb-service-role-gurgle. This is assigned to the Elastic Beanstalk manager. Use the managed policy: AWSElasticBeanstalkFullAccess and add the following trust relationship to the role.

aws iam create-role \
    --role-name eb-service-role-gurgle \
    --assume-role-policy-document file://./service-role-trust.json

aws iam attach-role-policy \
    --role-name eb-service-role-gurgle \
    --policy-arn arn:aws:iam::aws:policy/AWSElasticBeanstalkFullAccess

Create a new role eb-instance-role-gurgle. This is assigned to each individual instance.

aws iam create-role \
    --role-name eb-instance-role-gurgle \
    --assume-role-policy-document file://./instance-profile-trust.json

aws iam create-instance-profile \
    --instance-profile-name eb-instance-profile-gurgle

aws iam add-role-to-instance-profile \
    --instance-profile-name eb-instance-profile-gurgle \
    --role-name eb-instance-role-gurgle
# creates the app specification to AWS and `.elasticbeanstalk` directory
# note that these are just defaults, `create` can overwrite any of these
eb init \
    --platform docker-1.7.1 \
    --region us-west-2 \
    --keyname eb-gurgle

# each app has multiple app environments e.g. staging and prodution
# WebServer-Standard or Worker, serving or consumes queues?
# create the role first
# instance name is the same as environment name so include the app name
eb create \
    --service-role eb-service-role-gurgle \
    --instance_profile eb-instance-profile-gurgle \
    --instance_type t1.micro \
    --tier "WebServer-Standard" \
    --cname gurgle-staging-emerald \
    --scale 1 \
    gurgle-staging-emerald

Deployment

# To open the application in browser
eb open

# If there were errors or nothing shows up, check:
eb logs         # usually /var/log/eb-activity.log section has the problem
eb printenv
# Sometimes docker containers are not removed if deployment fails,
# so you could also try just deploying again.

# To update the servers after changes:
eb deploy gurgle-staging-emerald

Sources