Docker Swarm solves one of the fundamental limitations of Docker where the containers could only run on a single Docker host. Docker Swarm is native clustering for Docker. It turns a pool of Docker hosts into a single, virtual host.
Swarm Manager: Docker Swarm has a Master or Manager, that is a pre-defined Docker Host, and is a single point for all administration. Currently only a single instance of manager is allowed in the cluster. This is a SPOF for high availability architectures and additional managers will be allowed in a future version of Swarm with #598. TODO: ADD LINK.
Swarm Nodes: The containers are deployed on Nodes that are additional Docker Hosts. Each Swarm Node must be accessible by the manager, each node must listen to the same network interface (TCP port). Each node runs a node agent that registers the referenced Docker daemon, monitors it, and updates the discovery backend with the node’s status. The containers run on a node.
Scheduler Strategy: Different scheduler strategies (binpack'', spread'' (default), and ``random'') can be applied to pick the best node to run your container. The default strategy optimizes the node for least number of running containers. There are multiple kinds of filters, such as constraints and affinity. This should allow for a decent scheduling algorithm.
Node Discovery Service: By default, Swarm uses hosted discovery service, based on Docker Hub, using tokens to discover nodes that are part of a cluster. However etcd, consul, and zookeeper can be also be used for service discovery as well. This is particularly useful if there is no access to Internet, or you are running the setup in a closed network. A new discovery backend can be created as explained here. It would be useful to have the hosted Discovery Service inside the firewall and #660 will discuss this.
Standard Docker API: Docker Swarm serves the standard Docker API and thus any tool that talks to a single Docker host will seamlessly scale to multiple hosts now. That means if you were using shell scripts using Docker CLI to configure multiple Docker hosts, the same CLI would can now talk to Swarm cluster and Docker Swarm will then act as proxy and run it on the cluster.
There are lots of other concepts but these are the main ones.
-
Create a Swarm cluster. The easiest way of using Swarm is, by using the official Docker image:
docker run swarm createThis command returns a <TOKEN> and is the unique cluster id. It will be used when creating master and nodes later. This cluster id is returned by the hosted discovery service on Docker Hub.
NoteMake sure to note this cluster id now as there is no means to list it later. -
Swarm is fully integrated with Docker Machine, and so is the easiest way to get started. Let’s create a Swarm Master next:
docker-machine create -d virtualbox --swarm --swarm-master --swarm-discovery token://<TOKEN> swarm-masterReplace
<TOKEN>with the cluster id obtained in the previous step.--swarmconfigures the machine with Swarm,--swarm-masterconfigures the created machine to be Swarm master. Swarm master creation talks to the hosted service on Docker Hub and informs that a master is created in the cluster. -
Connect to this newly created master and find some more information about it:
eval "$(docker-machine env swarm-master)" docker infoNoteIf you’re on Windows, use the docker-machine env swarm-mastercommand only and copy the output into an editor to replace all appearances of EXPORT with SET and issue the three commands at your command prompt, remove the quotes and all duplicate appearences of "/".This will show the output as:
> docker info Containers: 2 Images: 7 Storage Driver: aufs Root Dir: /mnt/sda1/var/lib/docker/aufs Backing Filesystem: extfs Dirs: 11 Dirperm1 Supported: true Execution Driver: native-0.2 Kernel Version: 4.0.3-boot2docker Operating System: Boot2Docker 1.6.2 (TCL 5.4); master : 4534e65 - Wed May 13 21:24:28 UTC 2015 CPUs: 1 Total Memory: 998.1 MiB Name: swarm-master ID: USSA:35LS:WVRN:GKAZ:MLD4:XMQF:P7PL:VQ5D:7V4K:2QAH:5D2L:HC4K Debug mode (server): true Debug mode (client): false Fds: 24 Goroutines: 37 System Time: Wed Jun 10 03:40:00 UTC 2015 EventsListeners: 1 Init SHA1: 7f9c6798b022e64f04d2aff8c75cbf38a2779493 Init Path: /usr/local/bin/docker Docker Root Dir: /mnt/sda1/var/lib/docker Username: arungupta Registry: [https://index.docker.io/v1/] Labels: provider=virtualbox -
Create Swarm nodes.
docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-01Replace
<TOKEN>with the cluster id obtained in the previous step.Node creation talks to the hosted service at Docker Hub and joins the previously created cluster. This is specified by
--swarm-discovery token://…and specifying the cluster id obtained earlier. -
To make it a real cluster, let’s create a second node:
docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> swarm-node-02Replace
<TOKEN>with the cluster id obtained in the previous step. -
List all the nodes / Docker machines, that has been created so far.
docker-machine lsThis shows the output as:
NAME ACTIVE DRIVER STATE URL SWARM lab virtualbox Running tcp://192.168.99.103:2376 swarm-master * virtualbox Running tcp://192.168.99.107:2376 swarm-master (master) swarm-node-01 virtualbox Running tcp://192.168.99.108:2376 swarm-master swarm-node-02 virtualbox Running tcp://192.168.99.109:2376 swarm-masterThe machines that are part of the cluster have the cluster’s name in the SWARM column, blank otherwise. For example,
lab'' is a standalone machine where as all other machines are part of theswarm-master'' cluster. The Swarm master is also identified by (master) in the SWARM column. -
Connect to the Swarm cluster and find some information about it:
eval "$(docker-machine env --swarm swarm-master)" docker infoThis shows the output as:
> docker info Containers: 4 Strategy: spread Filters: affinity, health, constraint, port, dependency Nodes: 3 swarm-master: 192.168.99.107:2376 └ Containers: 2 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.023 GiB swarm-node-01: 192.168.99.108:2376 └ Containers: 1 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.023 GiB swarm-node-02: 192.168.99.109:2376 └ Containers: 1 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.023 GiBThere are 3 nodes – one Swarm master and 2 Swarm nodes. There is a total of 4 containers running in this cluster – one Swarm agent on master and each node, and there is an additional swarm-agent-master running on the master. This can be verified by connecting to the master and listing all the containers:
-
List nodes in the cluster with the following command:
docker run swarm list token://<TOKEN>This shows the output as:
> docker run swarm list token://b9d9da9198c0facbeeae302242fb65a5 192.168.99.109:2376 192.168.99.108:2376 192.168.99.107:2376
The complete cluster is in place now, and we need to deploy the Java EE application to it.
Swarm takes care for the distribution of the deployments across the nodes. The only thing, we need to do is to deploy the application as already explained in [JavaEE7_Container_Linking].
-
Start MySQL server as:
docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql-edefine environment variables that are read by the database at startup and allow us to access the database with this user and password. -
Start WildFly and deploy Java EE 7 application as:
docker run -d --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7This is using the Docker Container Linking explained earlier.
-
Check the state of the cluster as:
> docker info Containers: 7 Strategy: spread Filters: affinity, health, constraint, port, dependency Nodes: 3 swarm-master: 192.168.99.107:2376 └ Containers: 2 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.023 GiB swarm-node-01: 192.168.99.108:2376 └ Containers: 2 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.023 GiB swarm-node-02: 192.168.99.109:2376 └ Containers: 3 └ Reserved CPUs: 0 / 1 └ Reserved Memory: 0 B / 1.023 GiB``swarm-node-02'' is running three containers and so lets look at the list of containers running there:
> eval "$(docker-machine env swarm-node-02)" > docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f8022254703d arungupta/wildfly-mysql-javaee7:latest "/opt/jboss/wildfly/ About a minute ago Up About a minute 0.0.0.0:8080->8080/tcp mywildfly 7b6e9324c735 mysql:latest "/entrypoint.sh mysq 7 minutes ago Up 7 minutes 0.0.0.0:3306->3306/tcp mysqldb 6ed4c35c943b swarm:latest "/swarm join --addr 12 minutes ago Up 12 minutes 2375/tcp swarm-agent -
Access the application as:
curl http://$(docker-machine ip swarm-node-02):8080/employees/resources/employeesto see the output as:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>
TODO: arun-gupta#55
