About 2 years ago I started using AWS ElasticBeanstalk more. Not coincidentally, this is when AWS added Docker container support for Elastic Beanstalk.

First, Elastic Beanstalk is AWS's PaaS offering that provides an easy-to-use service for deploying and scaling web applications. This is sort of AWS's version of heroku, at least it is in the same space. Once code is uploaded to Elastic Beanstalk, it automatically handles capacity provisioning, load balancing, auto-scaling, and health monitoring for the application. At the same time, developers retain control over the underlying AWS resources that support their applications.

With all PaaS offerings like Elastic Beanstalk there is usually an official supported list of languages. Elastic Beanstalk official supports: Go, Java SE, Java with Tomcat, .NET on Windows Server with IIS, Node.js, PHP, Python, Ruby.

With Docker support though, Elastic Beanstalk provides a way for developers to use whatever programming language and application server they desire for their service. Developers are empowered to configure the Docker container and install extra packages and libraries that are needed without having to customize the server itself. Elastic Beanstalk handles deploying the Docker container for them.

As with most AWS services, Elastic Beanstalk is great and simply require some tooling on top of the service to speed up the flow. This post covers the jack tool that be use to quickly create and manage Elastic Beanstalk environments.

Jack and the Elastic Beanstalk

I'll go over some short example of the jack tool's capabilities. More details can be found on the README.

Creating Environments

First, it is very easy to create new EB environment with jack. Normally with EB, you need to first create the "EB Application" first and then you can created the "EB Environment". Jack automatically creates the application for you as part of the environment creation. Here is an example to show how it works.

$ git clone https://github.com/tongueroo/sinatra
$ cd sinatra
$ jack create hi-web-stag-1
Running: eb init -r us-east-1 -p "64bit Amazon Linux 2016.03 v2.1.0 running Docker 1.9.1" "hi"

Running: eb create --sample --nohang --keyname "default" --platform "64bit Amazon Linux 2016.03 v2.1.0 running Docker 1.9.1" --cname hi-web-stag-1 hi-web-stag-1
Environment details for: hi-web-stag-1
  Application name: hi
  Region: us-east-1
  Deployed Version: Sample Application
  Environment ID: e-3kqcygpdmb
  Platform: 64bit Amazon Linux 2016.03 v2.1.0 running Docker 1.9.1
  Tier: WebServer-Standard
  CNAME: hi-web-stag-1.us-east-1.elasticbeanstalk.com
  Updated: 2016-11-30 04:04:56.608000+00:00
Alert: An update to the EB CLI is available. Run "pip install --upgrade awsebcli" to get the latest version.
$ eb deploy # to deploy fresh code now

The hi application is automatically created and the the hi-web-stag-1 environment is created. The default EB sample app is initially uploaded to the environment so you can test the environment to make sure everything works. You can grab the dns endpoint from the EB Console and test that it works.

EB DNS endpoint

Here is the curl command to test if the app is returning a 200 response:

$ curl -svo /dev/null hi-web-stag-1.us-east-1.elasticbeanstalk.com 2>&1 | grep '< HTTP'
< HTTP/1.1 200 OK

Create Multiple EB Environments

Creating 1 environment and having the application being created is not that big of a deal though. What is cool is that jack can download an existing environment configuration and you can use that to recreate more environments quickly. EB has a clone feature that does this also, but if you have slightly different configurations between the environments you can quickly edit the downloaded config and create a new environment from it with a text editor. I've found this flow can be faster.

Since jack downloads the entire config, it also allows you to "rename" an EB Application. The EB clone feature understandably only works within an Application. With jack you can download the configuration from an Environment in any Application and recreate it entirely under a new Application. Here is an example:

$ jack config download hi-web-stag-1 -c hiworld-web-stag-1 # saves jack/cfg/hiworld-web-stag-1.cfg.yml
$ jack create hiworld-web-stag-1 # creates an hiworld app using jack/cfg/hiworld-web-stag-1.cfg.yml
$ eb deploy # deploys fresh code

Comparing Multiple EB Environments

Another trick you can do with jack is to quickly compare for differences between EB environments. You can loop through multiple environments, download all the configs and quickly compare their differences. Let's say you have created 2 staging environments: hi-web-stag-1 and hi-web-stag-2. Now you want to compare the 2 environment for any differences. This can happen if someone updates one of the environment with the EB Console. And usually this is reported as, "one of the environments is broken". Here is an example of a quick compare.

$ for i in {1..2} ; do jack config download hi-web-stag-$i ; done
$ colordiff jack/cfg/hi-web-stag-{1,2}.cfg.yml

If you have 3 staging environments:

$ for i in {1..3} ; do jack config download hi-web-stag-$i ; done
$ colordiff jack/cfg/hi-web-stag-{1,2}.cfg.yml
$ colordiff jack/cfg/hi-web-stag-{1,3}.cfg.yml
$ colordiff jack/cfg/hi-web-stag-{2,3}.cfg.yml

This is a very quick way to check for differences between environments and helps with debugging when someone says the "environment is down".

Useful Config Diff

Another useful jack feature worth highlighting is that it will diff the config before uploading it to verify that you are not accidentally stomping over previously made changes. It is pretty awesome that Elastic Beanstalk makes it so easy for developers to use the EB Console GUI to update the environment. However, this can sometimes lead to a member of the team making changes that others are not aware of. To help with this, the jack tool will first download the current EB config and then do a diff on the config you are uploading showing you the difference. This is extremely helpful to avoid wiping out config changes accidentally.

Here is an example where the instance type is changed from a t2.micro to a t2.small.

$ jack config upload hi-web-stag-1
Downloading config file...
Running: eb config save --cfg current-2016-11-29_22-19-27 hi-web-stag-1

Configuration saved at: /Users/tung/src/tongueroo/sinatra/.elasticbeanstalk/saved_configs/current-2016-11-29_22-19-27.cfg.yml
Comparing ./.elasticbeanstalk/saved_configs/current-2016-11-29_22-19-27.cfg.yml and jack/cfg/hi-web-stag-1.cfg.yml
<     InstanceType: t2.micro
>     InstanceType: t2.small

Are you sure you want to update the environment with your the new config ?
If the difference is not what you expected, you should say no.
A blank newline indicates that there was no difference.
If you want to download the config from the environment and
overwrite your jack/cfg/hi-web-stag-1.cfg.yml instead, you can use this command:
$ jack config download hi-web-stag-1
$ jack config help download # for more info
yes/no? [no] yes
Copying jack/cfg/hi-web-stag-1.cfg.yml to ./.elasticbeanstalk/saved_configs/hi-web-stag-1-2016-11-29_22-19-27.cfg.yml for the upload
Running: eb config put hi-web-stag-1-2016-11-29_22-19-27

Updating environment hi-web-stag-1 with template hi-web-stag-1-2016-11-29_22-19-27


Jack is a very simple tool and provides some additional useful commands on top the eb command like jack create and jack config. I hope that others find this tool useful too!

Jack is really cool and useful while also making it so easy to start using EB. Thank you for updating the build and for the detailed instructions, it just took me under 10 minutes to set everything up initially for it- I’m shocked at how simple it was. — Benjamin Kanter of Tuli.