left-icon

Docker Succinctly®
by Elton Stoneman

Previous
Chapter

of
A
A
A

CHAPTER 8

Running Docker in the Cloud

Running Docker in the Cloud


Docker versus the cloud

A production setup for Docker makes very few demands from your infrastructure. You need only a few machines that can communicate with each other over a network—they can be physical machines connected with Ethernet or VMs connected in a virtual network. When you’re hosting in the cloud, Docker makes a very good case for using Infrastructure-as-a-Service (IaaS) over Platform-as-a-Service (PaaS).

Typically, PaaS is the preferred option because it removes the administrative burden of managing virtual machines, and cloud providers add value with their PaaS offerings, which makes it easy to deploy and manage applications. However, all the PaaS offerings are custom. If you build an app to run on Amazon’s Elastic Beanstalk, you can’t lift the app and deploy it on Microsoft Azure instead—the packaging, deployment, and management models are not compatible. That means on-premise environments can’t run the app on the same platform as production, which means that in development and testing you must run the app in a different way.

By packaging your app in Docker images, you can run the same images locally and in any cloud using basic IaaS services and without taking a dependency on a particular vendor’s platform. In this chapter, we’ll look at using Docker Machine to build a Docker swarm on the DigitalOcean cloud, we’ll cover the Docker for Azure product, and we’ll look at running a multicloud swarm.

Docker on DigitalOcean

DigitalOcean is a relatively new cloud provider. It initially made its name by providing fast SSD-backed Linux VMs at a much lower cost than AWS, Azure, and Google. Its services are mostly in the IaaS space, which means you can spin up VMs, connect them in a virtual network, and set up persistent storage, but there are no higher-level PaaS services such as a message queue or a managed database platform.

When you sign up for a DigitalOcean account, you can create an API access token, which you use with the do command-line tool to create and manage components in the cloud. You can manually create a VM, log in, and install Docker, but it’s easier to use the Docker Machine tool.

Docker Machine is an open-source tool that abstracts the creation of a VM running Docker. Docker Machine has drivers for VirtualBox, AWS, Azure, DigitalOcean, and more, so you can create VMs in the same way on different platforms on your machines or in the cloud.

Note: Docker Machine is bundled with the Docker for Mac, Docker for Windows, and Docker Toolbox suites, but not on Linux. If you’re running Linux, the Docker documentation covers how to Install Docker Machine.

The provider plugins for Docker Machine use the relevant authentication mechanism. In order to create a new VM (called a “droplet” in DigitalOcean), you can use the command in Code Listing 84 and supply your own access token.

Code Listing 84: Creating a Docker Host on DigitalOcean with Docker Machine

$ docker-machine create \

 --driver digitalocean \

 --digitalocean-access-token=[YOUR-API-TOKEN] \

 --digitalocean-region lon1 \

 --digitalocean-image ubuntu-16-04-x64 \

 do-node-01

Running pre-create checks...

Creating machine...

(do-node-01) Creating SSH key...

(do-node-01) Creating Digital Ocean droplet...

(do-node-01) Waiting for IP address to be assigned to the Droplet...

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...

When that completes, you’ll have a new VM in DigitalOcean that runs the latest version of Docker. There are lots of options that the create command accepts, and they’re flexible for different VM providers. For DigitalOcean, I’ve specified the London datacenter and the latest longterm support version of Ubuntu, 16.04, as the operating system image for the VM.

Docker Machine locally stores details for the nodes it creates, and you can view them with the docker-machine env command. The output of that command is structured so that you can run it and set environment variables for your local Docker CLI to communicate with the remote Docker Engine you’ve just created. In Code Listing 85, I do this to work with the DigitalOcean droplet.

Code Listing 85: Configuring Docker CLI to Manage Remote Hosts

$ docker-machine env do-node-01

export DOCKER_TLS_VERIFY="1"

export DOCKER_HOST="tcp://139.59.189.184:2376"

export DOCKER_CERT_PATH="/home/elton/.docker/machine/machines/do-node-01"

export DOCKER_MACHINE_NAME="do-node-01"

# Run this command to configure your shell:

# eval $(docker-machine env do-node-01)

$ eval $(docker-machine env do-node-01)

Docker CLI uses the DOCKER_HOST and other environment variables to connect to the Docker Engine server. With those values set, my local command line is working with the DigitalOcean VM, and I can use all the usual commands. In Code Listing 86, I check the Docker versions.

Code Listing 86: Checking Docker Engine Versions

$ docker version

Client:

 Version:      1.12.1

 API version:  1.24

 Go version:   go1.6.3

 Git commit:   23cf638

 Built:        Thu Aug 18 05:33:38 2016

 OS/Arch:      linux/amd64

Server:

 Version:      1.12.1

 API version:  1.24

 Go version:   go1.6.3

 Git commit:   23cf638

 Built:        Thu Aug 18 05:33:38 2016

 OS/Arch:      linux/amd64

I have the latest version of Docker on my local client and the remote machine, and I can use the normal Docker commands to administer the remote machine. Versions don’t need to match—you can use a newer client with an older engine, but not vice versa.

Tip: When you work with multiple Docker hosts, it’s easy to lose track and find yourself killing containers on remote hosts when you meant to work locally. The docker-machine env -u command shows you how to reset the environment variables and point the CLI back to the local host.

You can repeat the command to create more VMs running Docker, then use the Docker Machine ls command to view them all. In Code Listing 87, you can see I have created two more DigitalOcean droplets through Docker Machine.

Code Listing 87: Listing Docker Machine Hosts

$ docker-machine ls -q

do-node-01

do-node-02

do-node-03

I won’t use these hosts yet—we’ll see how to join them to a multicloud swarm later in the chapter.

Docker Machine is a good choice for creating virtual machines as hosts—the commands are fundamentally the same for different platforms with only the options changing to support different feature sets. For most providers, the options can be specified in environment variables instead of the command, which means your actual docker-machine commands can be generic. You can capture your entire host setup in one script and have another script to tear it down, letting you easily spin up and remove environments.

Because it’s focused at the host level, there are limitations with Docker Machine, which means you’ll need to fall back to the platform’s CLI if you want to create more complex IaaS environments with subnets in your virtual network or custom port configurations. Docker addresses the two main cloud providers with products that build out the entire infrastructure.

Docker for Azure

The “Docker for” products all follow the same basic principle—they create a consistent Docker environment using the correct tools for the platform. Docker for Mac runs a Linux VM using HyperKit and Docker for Windows runs a Linux VM using Hyper-V. The end-user experience for each is the same because Docker makes use of the native platform tools.

Docker for Azure creates a Docker swarm on Azure, and the deployment is based on an Azure Resource Management template. Like the other products, Docker for Azure makes best use of the platform. When you deploy the template, it creates a functional environment for the swarm to work in. This includes:

  • A top-level resource group.
  • A virtual network for all the nodes.
  • A single VM to be the manager node.
  • A Virtual Machine Scale Set for the worker nodes.
  • A Network Security Group to configure routing rules.
  • A load balancer sitting in front of the worker nodes.
  • Public IP addresses for the manager VM and the load balancer.

Note: With AWS, the approach is very similar. Docker for AWS provides a CloudFormation template that creates all the resources. Docker for GCP is the latest edition.

In the Azure Portal, you can vary parameters for the deployment—for example, the size of the VMs and the initial number of worker nodes in the VM scale set, as we see in Figure 13.

Creating a Swarm with Docker for Azure

Figure 13: Creating a Swarm with Docker for Azure

The deployment is secured in two ways: with an Azure Active Directory Service Principal, which Docker for Azure uses to work with the Azure APIs from your subscription, and a normal SSH key, which you use for connecting with the swarm from your client machine. The Docker for Azure documentation details how to set up the security.

When deployment completes, you can connect to the manager node by SSH. In the Azure Portal, the Output section specifies the SSH command, as in Figure 14.

Docker for Azure Output

Figure 14: Docker for Azure Output

Code Listing 88 shows the connection to the manager node, where we can run all the standard Docker commands, such as listing out the nodes in the swarm.

Code Listing 88: Connecting to the Docker for Azure Manager Node

$ ssh [email protected]

Welcome to Docker!

dockerswarm-manager0:~$ docker node ls

ID                           HOSTNAME                    STATUS  AVAILABILITY  MANAGER STATUS

17i6hbl89u3m4ridw9p6ykip6    _dockerswarm-worker-vmss_0  Ready   Active       

33xg9i02xukght2232l5iprtc *  _dockerswarm-manager0       Ready   Active        Leader

8q53wxmdo4umveppzazx0ntd7    _dockerswarm-worker-vmss_2  Ready   Active       

czocuohj8r06q9ge29x2lrfgy    _dockerswarm-worker-vmss_1  Ready   Active

Note: This is an Azure deployment, but the VMs are running Linux, not Windows. We can run any Linux x64-based container images on this swarm, but we can’t run Windows-based images. The Docker EE template on Azure Marketplace lets you create a hybrid swarm with Linux and Windows nodes.

VM Scale Sets in Azure can be configured to autoscale based on properties such as amount of CPU use. When a scaling event is triggered, a new VM is created from the same image as the other VMs. For example, in the case of Docker for Azure, a new VM would be created from the worker image and join the swarm. Currently, there is no functionality to rebalance the swarm when a new node joins, which means you’d need to manually scale services on the swarm to make use of the new node(s).

Multicloud Docker swarms

We touched on Docker networks in Chapter 5, Orchestrating Systems with Docker, but the functionality goes beyond creating a virtual network for machines that are already within the same physical network. You can create an overlay network that spans physical networks, which means you can create a Docker swarm with nodes running on different clouds.

Note: The fact that you can do this doesn’t mean that you should. Swarm nodes are chatty, sending regular heartbeat messages, and a high latency link between different datacenters, or even different continents, could cause problems if the manager thinks worker nodes have dropped out. In the worst case, you could have a network partition between clouds, which means manager nodes can’t reach each other and you’ll end up with different managers in different clouds. But with careful planning and testing, this architecture can be useful in certain scenarios.

I’ll illustrate this with a simple swarm. I have a VM running Ubuntu with Docker in Azure that has the firewall (“Network Security Group” in Azure terminology) set up to allow public Internet access to the swarm ports. I can create a swarm in the usual way, but I need to specify two IP addresses, as in Code Listing 89.

Code Listing 89: Initializing a Swarm with Two IP Addresses

$ docker swarm init --advertise-addr 13.74.254.111 --listen-addr 10.3.0.4

The --advertise-addr option specifies the public IP address that the manager should listen to for connections, but that’s a virtual IP address managed by Azure—the VM itself doesn’t know about the address. The --listen-addr option specifies the actual IP address the manager should listen on, which means the manager can bind to one IP address but advertise another.

I can now join one of my DigitalOcean droplets to the swarm using the same join command and by specifying the public virtual IP address of the Azure manager node, as seen in Code Listing 90.

Code Listing 90: Joining a Swarm from Another Cloud

$ docker swarm join --token SWMTKN-1-3jsfck3x9s9sme8rmtk31321z28qu46o66399c555x9hqewmvx-bfsgl92blu2rng12o5xdvli98  13.74.254.111:2377

This node joined a swarm as a worker.

This gives me a swarm with two nodes running in different countries on different clouds. Code Listing 91 shows the node listing from the Azure manager.

Code Listing 91: Listing the Nodes in a Multicloud Swarm

$ docker node ls

ID                           HOSTNAME    STATUS  AVAILABILITY  MANAGER STATUS

0ejba0pkdtkqjsqs5vkskvt9l    do-node-01  Ready   Active

47950fi8w0evsk20ypkj4adk9 *  node0-ub    Ready   Active        Leader

I can use this multicloud swarm like any other, creating services with many replicas that span across the nodes. In Code Listing 92, I create a network for containers to communicate in.

Code Listing 92: Creating an Overlay Network on the Swarm

$ docker network create -d overlay website-net

Note: The default network type is bridge, which is used for single hosts. For networks that span multiple hosts, Docker has the overlay network, which is what you need to use for Docker swarm networks.

The overlay network can be specified when a service is created, adding all the containers to the network. In Code Listing 93, I create the basic Nginx service with enough replicas to span both nodes, then I list out the service processes.

Code Listing 93: Creating a Service Using an Overlay Network

$ docker service create --name website --publish 80:80 --replicas 4 --network website-net nginx:alpine

$ docker service ps website

ID                         NAME           IMAGE         NODE        DESIRED STATE  CURRENT STATE            ERROR

aq1ug1p1zknrfn3ucawbcfxhh  website.1      nginx:alpine  node0-ub    Running        Running 13 seconds ago

1w7gpilweobxzjh8lc993ce8w  website.2      nginx:alpine  do-node-01  Running        Running 13 seconds ago

9b52hijql5ugd723rql21bvgd  website.3      nginx:alpine  node0-ub    Running        Running 13 seconds ago

5oiscpzz73secc7hpelbfdazg  website.4      nginx:alpine  do-node-01  Running        Running 13 seconds ago

We see that there are four containers running, two each on the manager in Azure and the worker in DigitalOcean. In order to verify that the website is running, I can make an HTTP GET request to the public IP addresses for the nodes, as in Code Listing 94.

Code Listing 94: Checking the Service with cURL

$ curl http://138.68.129.206/  #DigitalOcean

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

$ curl http://13.74.254.111/  #Azure

<!DOCTYPE html>

<html>

<head>

<title>Welcome to nginx!</title>

With a multicloud setup like this, you can load balance across the nodes using a DNS service configured to serve either the Azure or the DigitalOcean endpoints. With an advanced DNS system, such as Amazon’s Route 53, you can put a health check on each endpoint so that you can configure Azure as your primary endpoint but have traffic routing to DigitalOcean if Azure is unavailable or busy.

Multicloud swarms, or swarms that are a mixture of cloud and on-premise hosts, offer some very interesting opportunities. But you should be aware of the security implications and the potential performance issue with swarm heartbeats and control plane messages crossing datacenters.

Summary

Running Docker in the cloud gives you the benefit of huge scale on-tap, which means you can easily spin up new nodes and add them to your swarm. This is even easier in the Docker for AWS and Docker for Azure products, as the swarms make use of the native scaling options for each platform, such as VM Scale Sets in Azure.

Centralizing on Docker for your packaging model also isolates you from vendor lock-in in the cloud. Your infrastructure deployment scripts will be specific to whichever cloud you use, but your application packages will run the same way on any cloud. So, if you start with AWS but then cut a good deal with Azure, you can easily shift your whole workload without any application code changes.

This IaaS approach to the cloud means taking on the burden of administering a fleet of VMs, but there are products available that simplify the management and add additional layers of security to your application estate.

In the final chapter, we’ll look at the product suite from Docker, Inc., which is aimed at running safe and healthy production deployments of Docker, and we’ll see where to go next on our Docker journey.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.