Docker-Machine and AWS

Quick note: the original post dates from 14-04-2016 but got updated at 01-05-2020 with latest versions and it was essentially written from scratch again.

Introduction

In this post, we experimented a bit with Docker Machine and Virtualbox. We were able to successfully launch a docker host on Virtualbox. It would be interesting to try this now also on AWS. Note that for this post, I’m assuming you already have an AWS account.

Getting all info from AWS

You will need to gather some information from AWS:

  • your AWS Access Key ID
  • your AWS Secret Access Key
  • your region in which you want to launch your instance
  • your VPC id for that region
Getting AWS Access Key and Secret Access Key

In your AWS console, go to ‘Identity & Access Management’, then either create a user or click on an existing user.

aws

As we gave the user programmatic access, they will show up in the last screen. You can download them (they will only be displayed once).

aws

Then, go to your local machine (in my case the MAC) and create a file ~/.aws/credentials with the following content:

[default]
    aws_access_key_id = <access_key>
    aws_secret_access_key = <secret_key>

Of course, change the placeholders with the value of your own credentials.

Getting your AWS region

By default, the AWS driver creates new instances in region us-east-1 (North Virginia). As I live in Europe, I prefer something closer. You can do this by specifying a different region by using the –amazonec2-region flag. For that, you will need to know the official name for your region. The easiest is to go to here and check under ‘Available Regions’

Getting your AWS VPC ID

AWS creates your EC2 instances (by default) in a default VPC. So you will also need that one. To do so, go to your region (in my case Ireland (eu-west-1) and go to the VPC dashboard. Click on the VPC and take a note of the VPC-ID. Again, you will need this one later on.

Using Docker Machine

We did quite some preparation work, time has come now to get started with the docker-machine command. We will create an docker ready EC2 instance in the Ireland region. Do this as follows:

wauterw@WAUTERW-M-65P7 ~ % docker-machine create --driver amazonec2 --amazonec2-vpc-id vpc-6d351c0b --amazonec2-region eu-west-1 aws-docker1
Running pre-create checks...
Creating machine...
(aws-docker1) Launching instance...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with ubuntu(systemd)...
Installing Docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env aws-docker1

Wait about a minute or 2 and you will see that an EC2 instance with name aws-docker1 is spawning on AWS. Let me show a screenshot:

aws

The whole process takes about a minute or 5 before the docker-machine command is finished completely installing docker on the host, etc…

Experimenting with Docker Machine

wauterw@WAUTERW-M-65P7 ~ % docker-machine ls
NAME                     ACTIVE   DRIVER         STATE     URL                         SWARM   DOCKER     ERRORS
aws-docker1              -        amazonec2      Running   tcp://54.77.9.141:2376              v19.03.8
docker-host-virtualbox   -        virtualbox     Running   tcp://192.168.99.100:2376           v19.03.5
wauterw@WAUTERW-M-65P7 ~ %

When you create a new machine, your command shell automatically connects to it. In case this is not so, you’ll have to run eval $(docker-machine env aws-docker1). How I got that one? See below…

wauterw@WAUTERW-M-65P7 ~ % docker-machine env aws-docker1
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://54.77.9.141:2376"
export DOCKER_CERT_PATH="/Users/wauterw/.docker/machine/machines/aws-docker1"
export DOCKER_MACHINE_NAME="aws-docker1"
# Run this command to configure your shell:
# eval $(docker-machine env aws-docker1)
wauterw@WAUTERW-M-65P7 ~ % eval $(docker-machine env aws-docker1)

From now on, every docker command you will supply is running on the AWS host called ‘aws-docker1’. Let’s try things a bit…:

wauterw@WAUTERW-M-65P7 ~ % docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:8e3114318a995a1ee497790535e7b88365222a21771ae7e53687ad76563e8e76
Status: Downloaded newer image for hello-world:latest

Hello from Docker!

Let’s now see if the container has run. From your local MAC, do the following:

wauterw@WAUTERW-M-65P7 ~ % docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
eb2b6924759a        hello-world         "/hello"            34 seconds ago      Exited (0) 32 seconds ago                       friendly_hodgkin

This works from our local machine but how can we be sure that we are running the above docker command against the AWS docker host (and not our local machine). Therefore, we need to login to our docker host on AWS through SSH.

SSH into the AWS instance

If you look at the AWS console, you will see that the instance aws-docker1 has a keypair called ‘aws-docker1’. The issue is that you cannot download it. If you browse through keypairs, it’s clear that there is no option to download keypairs that have been generated previously. So how to get into the instance then? Luckily docker-machine has an ‘ssh’ subcommand that allows us to get access to the instance.

wauterw@WAUTERW-M-65P7 ~ % docker-machine ssh aws-docker1
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-1052-aws x86_64)
ubuntu@aws-docker1:~$ sudo su
root@aws-docker1:/home/ubuntu# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
root@aws-docker1:/home/ubuntu# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
eb2b6924759a        hello-world         "/hello"            2 minutes ago       Exited (0) 2 minutes ago                       friendly_hodgkin

You’ll see that this output is exactly the same as the output from our local machine in the previous section. Pretty neat, no?

Control host via docker-machine

Let’s begin with listing all machines under control of docker-machine:

wauterw@WAUTERW-M-65P7 ~ % docker-machine ls
NAME                     ACTIVE   DRIVER         STATE     URL                         SWARM   DOCKER     ERRORS
aws-docker1              *        amazonec2      Running   tcp://54.77.9.141:2376              v19.03.8
docker-host-virtualbox   -        virtualbox     Running   tcp://192.168.99.100:2376           v19.03.5

Next, let’s stop the docker host on AWS.

wauterw@WAUTERW-M-65P7 ~ % docker-machine stop aws-docker1
Stopping "aws-docker1"...
Machine "aws-docker1" was stopped.

If you then go to your AWS console, you’ll see the instance was stopped.

aws

Obviously, we’re also able to remove a remote docker host. Do the following:

wauterw@WAUTERW-M-65P7 ~ % docker-machine rm aws-docker1
About to remove aws-docker1
WARNING: This action will delete both local reference and remote instance.
Are you sure? (y/n): y
Successfully removed aws-docker1

You will then see that the ‘aws-docker1’ host on AWS is in terminated state (and will soon disappear):

aws