Docker swarm mode

From WikiOD

A swarm is a number of Docker Engines (or nodes) that deploy services collectively. Swarm is used to distribute processing across many physical, virtual or cloud machines.

Syntax[edit | edit source]

Remarks[edit | edit source]

Swarm mode implements the following features:

  • Cluster management integrated with Docker Engine
  • Decentralized design
  • Declarative service model
  • Scaling
  • Desired state reconciliation
  • Multi-host networking
  • Service discovery
  • Load balancing
  • Secure design by default
  • Rolling updates

For more official Docker documentation regarding Swarm visit: Swarm mode overview

Swarm Mode CLI Commands[edit | edit source]

Click on commands description for documentation

Initialize a swarm

docker swarm init [OPTIONS]

Join a swarm as a node and/or manager

docker swarm join [OPTIONS] HOST:PORT

Create a new service

docker service create [OPTIONS] IMAGE [COMMAND] [ARG...]

Display detailed information on one or more services

docker service inspect [OPTIONS] SERVICE [SERVICE...]

List services

docker service ls [OPTIONS]

Remove one or more services

docker service rm SERVICE [SERVICE...]

Scale one or multiple replicated services

docker service scale SERVICE=REPLICAS [SERVICE=REPLICAS...]

List the tasks of one or more services

docker service ps [OPTIONS] SERVICE [SERVICE...]

Update a service

docker service update [OPTIONS] SERVICE

Create a swarm on Linux using docker-machine and VirtualBox[edit | edit source]

# Create the nodes
# In a real world scenario we would use at least 3 managers to cover the fail of one manager.
docker*machine create -d virtualbox manager
docker*machine create -d virtualbox worker1

# Create the swarm
# It is possible to define a port for the *advertise-addr* and *listen-addr*, if none is defined the default port 2377 will be used.
docker*machine ssh manager \
    docker swarm init \
    --advertise-addr $(docker-machine ip manager)
    --listen-addr $(docker-machine ip manager)

# Extract the Tokens for joining the Swarm
# There are 2 different Tokens for joining the swarm.
MANAGER_TOKEN=$(docker*machine ssh manager docker swarm join-token manager --quiet)
WORKER_TOKEN=$(docker*machine ssh manager docker swarm join-token worker --quiet)

# Join a worker node with the worker token
docker*machine ssh worker1 \
    docker swarm join \
    --token $WORKER_TOKEN \
    --listen-addr $(docker-machine ip worker1) \
    $(docker-machine ip manager):2377

Node Availablility[edit | edit source]

Swarm Mode Node Availability:

  • Active means that the scheduler can assign tasks to a node.
  • Pause means the scheduler doesn’t assign new tasks to the node, but existing tasks remain running.
  • Drain means the scheduler doesn’t assign new tasks to the node. The scheduler shuts down any existing tasks and schedules them on an available node.

To change Mode Availability:

#Following commands can be used on swarm manager(s)
docker node update --availability drain node-1
#to verify:
docker node ls

Promote or Demote Swarm Nodes[edit | edit source]

To promote a node or set of nodes, run docker node promote from a manager node:

docker node promote node-3 node-2

Node node-3 promoted to a manager in the swarm.
Node node-2 promoted to a manager in the swarm.

To demote a node or set of nodes, run docker node demote from a manager node:

docker node demote node-3 node-2

Manager node-3 demoted in the swarm.
Manager node-2 demoted in the swarm.

Find out worker and manager join token[edit | edit source]

When automating the provisioning of new nodes to a swarm, you need to know what the right join token is for the swarm as well as the advertised address of the manager. You can find this out by running the following commands on any of the existing manager nodes:

# grab the ipaddress:port of the manager (second last line minus the whitespace)
export MANAGER_ADDRESS=$(docker swarm join-token worker | tail -n 2 |  tr -d '[[:space:]]')

# grab the manager and worker token
export MANAGER_TOKEN=$(docker swarm join-token manager -q)
export WORKER_TOKEN=$(docker swarm join-token worker -q)

The -q option outputs only the token. Without this option you get the full command for registering to a swarm.

Then on newly provisioned nodes, you can join the swarm using.

docker swarm join --token $WORKER_TOKEN $MANAGER_ADDRESS

Hello world application[edit | edit source]

Usually you'd want to create a stack of services to form a replicated and orchestrated application.

A typical modern web application consists of a database, api, frontend and reverse proxy.

Persistence

Database needs persistence, so we need some filesystem which is shared across all the nodes in a swarm. It can be NAS, NFS server, GFS2 or anything else. Setting it up is out of scope here. Currently Docker doesn't contain and doesn't manage persistence in a swarm. This example assumes that there's /nfs/ shared location mounted across all nodes.

Network

To be able to communicate with each other, services in a swarm need to be on the same network.

Choose an IP range (here 10.0.9.0/24) and network name (hello-network) and run a command:

docker network create \
  --driver overlay \
  --subnet 10.0.9.0/24 \
  --opt encrypted \
  hello-network

Database

The first service we need is a database. Let's use postgresql as an example. Create a folder for a database in nfs/postgres and run this:

docker service create --replicas 1 --name hello-db \
       --network hello-network -e PGDATA=/var/lib/postgresql/data \
       --mount type=bind,src=/nfs/postgres,dst=/var/lib/postgresql/data \
       kiasaki/alpine-postgres:9.5

Notice that we've used --network hello-network and --mount options.

API

Creating API is out of scope of this example, so let's pretend you have an API image under username/hello-api.

docker service create --replicas 1 --name hello-api \
       --network hello-network \
       -e NODE_ENV=production -e PORT=80 -e POSTGRESQL_HOST=hello-db \
       username/hello-api

Notice that we passed a name of our database service. Docker swarm has an embedded round-robin DNS server, so API will be able to connect to database by using its DNS name.

Reverse proxy

Let's create nginx service to serve our API to an outer world. Create nginx config files in a shared location and run this:

docker service create --replicas 1 --name hello-load-balancer \
       --network hello-network \
       --mount type=bind,src=/nfs/nginx/nginx.conf,dst=/etc/nginx/nginx.conf \
       -p 80:80 \
       nginx:1.10-alpine

Notice that we've used -p option to publish a port. This port would be available to any node in a swarm.

Leaving the Swarm[edit | edit source]

Worker Node:

#Run the following on the worker node to leave the swarm.

docker swarm leave
Node left the swarm.

If the node has the Manager role, you will get a warning about maintaining the quorum of Managers. You can use --force to leave on the manager node:

#Manager Node

docker swarm leave --force
Node left the swarm.

Nodes that left the Swarm will still show up in docker node ls output.

To remove nodes from the list:

docker node rm node-2

node-2

Credit:Stack_Overflow_Documentation