Creating a test swarm - tooltwist/documentation GitHub Wiki

These steps are used to create a new test swarm on Digital Ocean.

Note 1 - that this is only required to create a completely new swarm

Note 2 - It is recommended that scripts are used to run all the commands shown here, so they can be rerun if there are ever any problems.

Step 1 - Protect sensitive information

It is critical that the information used to access the swarm is never saved to github. Hackers troll github and other public repositories looking for api keys that will allow them to access private servers.

cat >> .gitignore << END
DO_ACCESS_TOKEN
SWARM_TOKEN
END

Step 2 - Get an ACCESS_TOKEN from Digital Ocean

Log in to Digital Ocean, go to the API page and the Your Apps tab, and generate a new token. To remember this token - it isn't shown again - we'll save it to file. For example:

$ echo 12345b3e5c2abcda0242f28zyxwecf310098762f27ae1fabcdb1745accfdfbcb > DO_ACCESS_TOKEN

Step 3 - Register a new Swarm

This step is used to get a Swarm Token. This token is used by Docker machines to attach to the swarm, using a discovery service provided by Docker. To get a token, run the following command on any Docker machine.

$ docker run --rm swarm create
Unable to find image 'swarm:latest' locally
latest: Pulling from library/swarm
28d9e4361d1b: Pull complete  
...
library/swarm:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:1502dd0c1d778d4f5e75d47820dd858ac1f67aa59c178f3244de17ccbde0067f
Status: Downloaded newer image for swarm:latest
b7798763f46abcdef2fa750e0e1234cf

Take note of last line of the output and save it as a file.

$ echo b7798763f46abcdef2fa750e0e1234cf > SWARM_TOKEN

Note that this command does not run the discovery service - it simply contacts the discovery server to register a new swarm. There is no need to run this command where the swarm will be created (e.g. at DigitalOcean) - it's quite okay to run this on your own machine.

We'll also choose a name for the swarm so we can recognise the servers in the swarm. For example:

$ echo myswarm > SWARM_NAME

Step 4 - Create the Swarm Master

Here we create a new virtual machine running Docker at Digital Ocean, to run the Swarm Master. This machine will be part of the swarm, but will also run a Docker container responsible for monitoring the other nodes in the swarm. Create a file named createMaster.sh:

#!/bin/bash
#
# Create the swarm Master
#
DO_ACCESS_TOKEN=`cat DO_ACCESS_TOKEN`
SWARM_TOKEN=`cat SWARM_TOKEN`
SWARM_NAME=`cat SWARM_NAME`
REGION=sgp1
SIZE=4gb

SERVER_NAME=${SWARM_NAME}-master
docker-machine create --driver digitalocean \
	--digitalocean-access-token ${DO_ACCESS_TOKEN} \
	--digitalocean-region ${REGION} \
	--digitalocean-size ${SIZE} \
	--swarm \
	--swarm-master \
	--swarm-discovery token://${SWARM_TOKEN} \
	${SERVER_NAME}

Notice the SWARM_TOKEN must be replaced with the token you obtained in step 1.

You can find out the running machines at any time using:

docker-machine ls

Step 5 - Creating Swarm Nodes

A swarm node is created in the same way as the master, but without the --swarm-master parameter. Note that the server name is made unique by adding the current process ID as a suffix. This can be replaced with some other way of creating unique names if you prefer.

Create a file named createWorker.sh:

#!/bin/bash
#
# Create a swarm worker node
#
DO_ACCESS_TOKEN=`cat DO_ACCESS_TOKEN`
SWARM_TOKEN=`cat SWARM_TOKEN`
SWARM_NAME=`cat SWARM_NAME`
REGION=sgp1
SIZE=4gb

SERVER_NAME=${SWARM_NAME}-worker-$$
docker-machine create --driver digitalocean \
	--digitalocean-access-token ${DO_ACCESS_TOKEN} \
	--digitalocean-region ${REGION} \
	--digitalocean-size ${SIZE} \
	--swarm \
	--swarm-discovery token://${SWARM_TOKEN} \
	${SERVER_NAME}

Step 6

Once the swarm is running, check the state of the machines:

$ docker-machine ls
NAME                  ACTIVE   DRIVER         STATE     URL                          SWARM
phil-master                    digitalocean   Running   tcp://128.199.84.133:2376    phil-master (master)
phil-worker-23725     *        digitalocean   Running   tcp://188.166.245.99:2376    phil-master

We can take a look at the master machine (I've started a few application containers):

$ eval "$(docker-machine env phil-master)"

$ docker ps
CONTAINER ID        IMAGE                        COMMAND                CREATED             STATUS              PORTS                                        NAMES
6e30c7e1f424        tooltwist/ttsite:30sep2015   "/sbin/my_init"        3 hours ago         Up 3 hours          22/tcp, 39393/tcp, 0.0.0.0:32768->8080/tcp   swarm2_ttdemo_1      
1f97117847b8        swarm:latest                 "/swarm join --addr    6 hours ago         Up 6 hours          2375/tcp                                     swarm-agent          
f5221c2ef67a        swarm:latest                 "/swarm manage --tls   6 hours ago         Up 6 hours          2375/tcp, 0.0.0.0:3376->3376/tcp             swarm-agent-master   


$ docker info
Containers: 9
Images: 123
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 141
 Dirperm1 Supported: false
Execution Driver: native-0.2
Kernel Version: 3.13.0-57-generic
Operating System: Ubuntu 14.04.3 LTS
CPUs: 2
Total Memory: 3.861 GiB
Name: phil-master
ID: MF3M:U5UR:BT3U:G7QV:VDRA:X5DP:CN2F:CMES:7XNU:ZN4U:YPPV:KEUL
...

We can also look at the swarm. Notice the node prefix to the container names:

$ eval "$(docker-machine env --swarm phil-master)"

$ docker ps
CONTAINER ID        IMAGE                        COMMAND             CREATED             STATUS              PORTS                                               NAMES
6e30c7e1f424        tooltwist/ttsite:30sep2015   "/sbin/my_init"     3 hours ago         Up 3 hours          22/tcp, 39393/tcp, 128.199.84.133:32768->8080/tcp   phil-master/swarm2_ttdemo_1    
abeb3540d1b4        tooltwist/ttsite:30sep2015   "/sbin/my_init"     6 hours ago         Up 4 hours          22/tcp, 39393/tcp, 128.199.84.133:9080->8080/tcp    phil-worker-23725/ttsite-container       

$ docker info
Containers: 10
Images: 7
Storage Driver: 
Role: primary
Strategy: spread
Filters: affinity, health, constraint, port, dependency
Nodes: 2
 phil-master: 128.199.84.133:2376
  └ Containers: 8
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 4.054 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.13.0-57-generic, operatingsystem=Ubuntu 14.04.3 LTS, provider=digitalocean, storagedriver=aufs
 phil-worker-23725: 188.166.245.99:2376
  └ Containers: 2
  └ Reserved CPUs: 0 / 2
  └ Reserved Memory: 0 B / 4.054 GiB
  └ Labels: executiondriver=native-0.2, kernelversion=3.13.0-57-generic, operatingsystem=Ubuntu 14.04.3 LTS, provider=digitalocean, storagedriver=aufs
Execution Driver: 
Kernel Version: 
Operating System: 
CPUs: 4
Total Memory: 8.108 GiB
Name: f5221c2ef67a
...

At this stage we can start a container on the swarm, but we have no way to route requests to the server other than guessing it's IP address from docker-machine ls command and use the mapped port.

$ docker run -d -p 9080:8080 --name ttsite-container tooltwist/ttsite:30sep2015
dab942b78b129590ba0fce87f1f040fa59bfd1757e99826d8963c0596cf2ec85

$ docker ps
CONTAINER ID        IMAGE                        COMMAND                CREATED             STATUS              PORTS                                       NAMES
dab942b78b12        tooltwist/ttsite:30sep2015   "/sbin/my_init"        About an hour ago   Up 4 seconds        22/tcp, 39393/tcp, 0.0.0.0:9080->8080/tcp   ttsite-container     
1f97117847b8        swarm:latest                 "/swarm join --addr    2 hours ago         Up 2 hours          2375/tcp                                    swarm-agent          
f5221c2ef67a        swarm:latest                 "/swarm manage --tls   2 hours ago         Up 2 hours          2375/tcp, 0.0.0.0:3376->3376/tcp            swarm-agent-master   

$ curl http://188.166.245.99:9080
curl: (7) Failed connect to 188.166.245.99:9080; Connection refused

$ curl http://128.199.84.133:9080
<!DOCTYPE html>
<html lang="en">
    ...
</html>
⚠️ **GitHub.com Fallback** ⚠️