Amazon and Docker — The Dockzon!

Christoph Bühler
smartive
4 min readMar 1, 2017

--

First of all, a little disclaimer: This post was originally written and published on November 23rd, 2015 and has been migrated to medium.

Docker is an upcoming technology to “dockerize” your applications. You don’t have to install the whole technology stack on your server to run a specific application. Need Elasticsearch? No problem: docker run -d --name=myFancyES elasticsearch. Done.

With that power, we can run more complex scenarios on every machine we desire to start our app.

Amazon

As soon as Docker hit a stable state, the big three cloud companies (Microsoft, Google, Amazon) tried to acquire the new dynamic way of running applications. We had the chance at smartive to use Docker with the Amazon AWS cloud. Now we’d like to share our first impressions with you.

EC2 on steroids

ECS — the Elastic Container Service — is the core of using Docker on Amazon. But before you can use ECS, you need an instance to run your cluster on. Those instances are simple EC2 (Elastic Compute Cloud) instances with a specialized AMI (Amazon Machine Image). Those images contain the normal docker installation and a special amazon ecs-service that — dockerized by itself — manages the cluster and the images of the instance. You can configure your service with the following configuration file: /etc/ecs/ecs.config. There you can configure the docker.io authentication - so you can pull private images - and other stuff like to which cluster the instance belongs to.

ECS_CLUSTER=myCluster ECS_ENGINE_AUTH_TYPE=dockercfg ECS_ENGINE_AUTH_DATA={"https://index.docker.io/v1/": {"auth": "FOO_MYAUTHKEY_BAR","email": "deployme@demo.test"}} ECS_DISABLE_METRICS=true

Note: ECS_DISABLE_METRICS=true is used to disable the cluster metrics, they fail if the cluster is not default or if you mess up with the port configurations.

ECS

Once you got your instance up and running, and the instance is registered in an ECS cluster, you can start to use Docker… Not. First you need to register a “task definition” in the ECS administration menu. Once you decided, which image with how much CPU and memory resources should run, you are good to go. Select a cluster, run a new service, select your task definition and decide, how many of them should run. Your instance(s) will now download the specified Docker image and start it with certain parameters.

What a task definition could look like:

{ "containerDefinitions": [ { "volumesFrom": [], "portMappings": [ { "hostPort": 80, "containerPort": 80, "protocol": "tcp" } ], "command": [], "environment": [], "essential": true, "entryPoint": [], "links": [], "mountPoints": [], "memory": 512, "name": "nginx-demo", "cpu": 256, "image": "nginx" } ], "volumes": [], "family": "nginx-demo-task" }

You need to be careful when you use port bindings. Well, nearly every useful service needs some TCP or UDP ports to communicate with the open world. The problem is, ECS can’t handle the dynamic ports of Docker. So if you want your service to run on port 80, and the service should run twice, you need more than one instance to fully support your cluster. Amazon handles port conflicts by separating same ports to different machines.

If you need to update your service, you can shutdown the service and update the definition. Well, the problem is, ECS is not able to perform a rolling update. Amazon needs four instances to update a service which should run twice. ECS tries to run your updated tasks first, before shutting down the old ones. This results in more port conflicts, which leads ECS to use other instances.

For example: You have a nginx on port 80 and you need to update to a new version. Your nginx runs on two machines, because load balancing can happen ;-). ECS tries to start two updated versions of your nginx task before shutting down the old ones. Now as we have two EC2 instances registered in our cluster, it’s impossible to run more nginx, since we use port 80.

If you need to perform a rolling update, here’s how we achieved that:

  1. Define multiple clusters (at least more than one)
  2. Configure your instances to run in either the prod1 or prod2 cluster (or prodN)
  3. To perform an update, shut the service down on prod1, update and restart it.
  4. Continue this shutdown — update — restart routine for all other clusters

With this technique, you can perform a rolling update on your application, without having a downtime. Well, an essential part was missing in this explanation. You need an ELB (Elastic Load Balancing) to assist you with handling the connections.

If you are willing to pay the price for Amazon, it’s truly a comfortable environment. You can scale all your services with one click and after you managed to configure AWS, it’s kind of boring because AWS manages itself. If Amazon manages to register dynamic ports from Docker images — as they posted to be implemented soon™ when the community needs this feature — so you can scale multiple container instances with the same image ports on the same machine — that would be pretty useful. One thing amazon needs to improve is their UI. I’m not a design expert, but the AWS management UI has some major design flaws. Right now, I feel safer when I configure AWS with the command shell instead of the web UI.

I’d use it again if I have the chance. No system can provide every feature a developer wishes for, but Amazon delivers a whole bunch of stuff.

--

--

Christoph Bühler
smartive

Code hero @smartive. Technology enthusiast, web engineer, Lindy Hop dancer and much more.