2016-10-06 13:48:23 +00:00
# Docker Swarm (mode) cluster
2018-10-17 14:24:04 +00:00
This section explains how to create a multi-host docker cluster with swarm mode using [docker-machine ](https://docs.docker.com/machine ) and how to deploy Traefik on it.
2016-10-06 13:48:23 +00:00
2016-11-05 22:02:43 +00:00
The cluster consists of:
2016-10-06 13:48:23 +00:00
- 3 servers
- 1 manager
- 2 workers
2017-09-22 15:22:03 +00:00
- 1 [overlay ](https://docs.docker.com/engine/userguide/networking/dockernetworks/#an-overlay-network ) network (multi-host networking)
2016-10-06 13:48:23 +00:00
## Prerequisites
1. You will need to install [docker-machine ](https://docs.docker.com/machine/ )
2. You will need the latest [VirtualBox ](https://www.virtualbox.org/wiki/Downloads )
2017-09-22 15:22:03 +00:00
2016-10-06 13:48:23 +00:00
## Cluster provisioning
2017-09-11 17:10:04 +00:00
First, let's create all the required nodes.
It's a shorter version of the [swarm tutorial ](https://docs.docker.com/engine/swarm/swarm-tutorial/ ).
2016-10-06 13:48:23 +00:00
2017-04-30 18:17:57 +00:00
```shell
2016-10-06 13:48:23 +00:00
docker-machine create -d virtualbox manager
docker-machine create -d virtualbox worker1
docker-machine create -d virtualbox worker2
```
2017-09-22 15:22:03 +00:00
Then, let's setup the cluster, in order:
2016-10-06 13:48:23 +00:00
1. initialize the cluster
2017-09-11 17:10:04 +00:00
1. get the token for other host to join
1. on both workers, join the cluster with the token
2016-10-06 13:48:23 +00:00
2017-04-30 18:17:57 +00:00
```shell
2016-10-06 13:48:23 +00:00
docker-machine ssh manager "docker swarm init \
--listen-addr $(docker-machine ip manager) \
--advertise-addr $(docker-machine ip manager)"
export worker_token=$(docker-machine ssh manager "docker swarm \
join-token worker -q")
docker-machine ssh worker1 "docker swarm join \
--token=${worker_token} \
--listen-addr $(docker-machine ip worker1) \
--advertise-addr $(docker-machine ip worker1) \
$(docker-machine ip manager)"
2017-01-07 08:20:52 +00:00
2016-10-06 13:48:23 +00:00
docker-machine ssh worker2 "docker swarm join \
--token=${worker_token} \
--listen-addr $(docker-machine ip worker2) \
--advertise-addr $(docker-machine ip worker2) \
$(docker-machine ip manager)"
```
Let's validate the cluster is up and running.
2017-04-30 18:17:57 +00:00
```shell
2016-10-06 13:48:23 +00:00
docker-machine ssh manager docker node ls
2017-09-05 13:58:03 +00:00
```
```
2016-10-06 13:48:23 +00:00
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
2017-09-22 15:22:03 +00:00
013v16l1sbuwjqcn7ucbu4jwt worker1 Ready Active
8buzkquycd17jqjber0mo2gn8 worker2 Ready Active
fnpj8ozfc85zvahx2r540xfcf * manager Ready Active Leader
2016-10-06 13:48:23 +00:00
```
2018-10-17 14:24:04 +00:00
Finally, let's create a network for Traefik to use.
2016-10-06 13:48:23 +00:00
2017-04-30 18:17:57 +00:00
```shell
2016-10-06 13:48:23 +00:00
docker-machine ssh manager "docker network create --driver=overlay traefik-net"
```
2017-09-22 15:22:03 +00:00
2018-10-17 14:24:04 +00:00
## Deploy Traefik
2016-10-06 13:48:23 +00:00
2018-10-17 14:24:04 +00:00
Let's deploy Traefik as a docker service in our cluster.
The only requirement for Traefik to work with swarm mode is that it needs to run on a manager node - we are going to use a [constraint ](https://docs.docker.com/engine/reference/commandline/service_create/#/specify-service-constraints-constraint ) for that.
2016-10-06 13:48:23 +00:00
2017-04-30 18:17:57 +00:00
```shell
2016-10-06 13:48:23 +00:00
docker-machine ssh manager "docker service create \
--name traefik \
--constraint=node.role==manager \
--publish 80:80 --publish 8080:8080 \
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
--network traefik-net \
traefik \
--docker \
2018-04-06 07:38:03 +00:00
--docker.swarmMode \
2016-10-06 13:48:23 +00:00
--docker.domain=traefik \
--docker.watch \
2018-01-11 08:46:03 +00:00
--api"
2016-10-06 13:48:23 +00:00
```
Let's explain this command:
2017-09-11 17:10:04 +00:00
| Option | Description |
|-----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------|
| `--publish 80:80 --publish 8080:8080` | we publish port `80` and `8080` on the cluster. |
2018-10-17 14:24:04 +00:00
| `--constraint=node.role==manager` | we ask docker to schedule Traefik on a manager node. |
| `--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock` | we bind mount the docker socket where Traefik is scheduled to be able to speak to the daemon. |
| `--network traefik-net` | we attach the Traefik service (and thus the underlying container) to the `traefik-net` network. |
| `--docker` | enable docker provider, and `--docker.swarmMode` to enable the swarm mode on Traefik. |
2018-06-29 15:02:03 +00:00
| `--api` | activate the webUI on port 8080 |
2016-10-06 13:48:23 +00:00
2017-09-22 15:22:03 +00:00
2016-10-06 13:48:23 +00:00
## Deploy your apps
2018-10-25 15:04:03 +00:00
We can now deploy our app on the cluster, here [whoami ](https://github.com/containous/whoami ), a simple web server in Go.
2017-09-11 17:10:04 +00:00
We start 2 services, on the `traefik-net` network.
2016-10-06 13:48:23 +00:00
2017-04-30 18:17:57 +00:00
```shell
2016-10-06 13:48:23 +00:00
docker-machine ssh manager "docker service create \
--name whoami0 \
--label traefik.port=80 \
--network traefik-net \
2018-10-25 15:04:03 +00:00
containous/whoami"
2017-01-07 08:20:52 +00:00
2016-10-06 13:48:23 +00:00
docker-machine ssh manager "docker service create \
--name whoami1 \
--label traefik.port=80 \
--network traefik-net \
2017-01-07 08:20:52 +00:00
--label traefik.backend.loadbalancer.sticky=true \
2018-10-25 15:04:03 +00:00
containous/whoami"
2016-10-06 13:48:23 +00:00
```
2017-09-11 17:10:04 +00:00
!!! note
2017-10-10 13:24:03 +00:00
We set `whoami1` to use sticky sessions (`--label traefik.backend.loadbalancer.stickiness=true`).
2017-09-11 17:10:04 +00:00
We'll demonstrate that later.
2017-08-22 08:56:03 +00:00
2017-09-11 17:10:04 +00:00
!!! note
If using `docker stack deploy` , there is [a specific way that the labels must be defined in the docker-compose file ](https://github.com/containous/traefik/issues/994#issuecomment-269095109 ).
2017-01-17 06:38:56 +00:00
2016-10-06 13:48:23 +00:00
Check that everything is scheduled and started:
2017-04-30 18:17:57 +00:00
```shell
2016-10-06 13:48:23 +00:00
docker-machine ssh manager "docker service ls"
2017-09-05 13:58:03 +00:00
```
```
2017-09-22 15:22:03 +00:00
ID NAME MODE REPLICAS IMAGE PORTS
moq3dq4xqv6t traefik replicated 1/1 traefik:latest *:80->80/tcp,* :8080->8080/tcp
2018-10-25 15:04:03 +00:00
ysil6oto1wim whoami0 replicated 1/1 containous/whoami:latest
z9re2mnl34k4 whoami1 replicated 1/1 containous/whoami:latest
2016-10-06 13:48:23 +00:00
```
2017-09-22 15:22:03 +00:00
2018-10-17 14:24:04 +00:00
## Access to your apps through Traefik
2016-10-06 13:48:23 +00:00
2017-04-30 18:17:57 +00:00
```shell
2016-10-06 13:48:23 +00:00
curl -H Host:whoami0.traefik http://$(docker-machine ip manager)
2017-09-05 13:58:03 +00:00
```
```yaml
2017-09-22 15:22:03 +00:00
Hostname: 5b0b3d148359
2016-10-06 13:48:23 +00:00
IP: 127.0.0.1
2017-09-22 15:22:03 +00:00
IP: 10.0.0.8
IP: 10.0.0.4
IP: 172.18.0.5
2016-10-06 13:48:23 +00:00
GET / HTTP/1.1
2017-09-22 15:22:03 +00:00
Host: whoami0.traefik
User-Agent: curl/7.55.1
2016-10-06 13:48:23 +00:00
Accept: */*
Accept-Encoding: gzip
2017-09-22 15:22:03 +00:00
X-Forwarded-For: 10.255.0.2
X-Forwarded-Host: whoami0.traefik
2016-10-06 13:48:23 +00:00
X-Forwarded-Proto: http
2017-09-22 15:22:03 +00:00
X-Forwarded-Server: 77fc29c69fe4
2017-09-05 13:58:03 +00:00
```
```shell
2016-10-06 13:48:23 +00:00
curl -H Host:whoami1.traefik http://$(docker-machine ip manager)
2017-09-05 13:58:03 +00:00
```
```yaml
2017-09-22 15:22:03 +00:00
Hostname: 3633163970f6
2016-10-06 13:48:23 +00:00
IP: 127.0.0.1
2017-09-22 15:22:03 +00:00
IP: 10.0.0.14
IP: 10.0.0.6
IP: 172.18.0.5
2016-10-06 13:48:23 +00:00
GET / HTTP/1.1
2017-09-22 15:22:03 +00:00
Host: whoami1.traefik
User-Agent: curl/7.55.1
2016-10-06 13:48:23 +00:00
Accept: */*
Accept-Encoding: gzip
2017-09-22 15:22:03 +00:00
X-Forwarded-For: 10.255.0.2
X-Forwarded-Host: whoami1.traefik
2016-10-06 13:48:23 +00:00
X-Forwarded-Proto: http
2017-09-22 15:22:03 +00:00
X-Forwarded-Server: 77fc29c69fe4
2016-10-06 13:48:23 +00:00
```
2017-09-11 17:10:04 +00:00
!!! note
2018-10-17 14:24:04 +00:00
As Traefik is published, you can access it from any machine and not only the manager.
2016-10-06 13:48:23 +00:00
2017-04-30 18:17:57 +00:00
```shell
2016-10-06 13:48:23 +00:00
curl -H Host:whoami0.traefik http://$(docker-machine ip worker1)
2017-09-05 13:58:03 +00:00
```
```yaml
2017-09-22 15:22:03 +00:00
Hostname: 5b0b3d148359
2016-10-06 13:48:23 +00:00
IP: 127.0.0.1
2017-09-22 15:22:03 +00:00
IP: 10.0.0.8
IP: 10.0.0.4
IP: 172.18.0.5
2016-10-06 13:48:23 +00:00
GET / HTTP/1.1
2017-09-22 15:22:03 +00:00
Host: whoami0.traefik
User-Agent: curl/7.55.1
2016-10-06 13:48:23 +00:00
Accept: */*
Accept-Encoding: gzip
2017-09-22 15:22:03 +00:00
X-Forwarded-For: 10.255.0.3
X-Forwarded-Host: whoami0.traefik
2016-10-06 13:48:23 +00:00
X-Forwarded-Proto: http
2017-09-22 15:22:03 +00:00
X-Forwarded-Server: 77fc29c69fe4
2017-09-05 13:58:03 +00:00
```
```shell
2016-10-06 13:48:23 +00:00
curl -H Host:whoami1.traefik http://$(docker-machine ip worker2)
2017-09-05 13:58:03 +00:00
```
```yaml
2017-09-22 15:22:03 +00:00
Hostname: 3633163970f6
2016-10-06 13:48:23 +00:00
IP: 127.0.0.1
2017-09-22 15:22:03 +00:00
IP: 10.0.0.14
IP: 10.0.0.6
IP: 172.18.0.5
2016-10-06 13:48:23 +00:00
GET / HTTP/1.1
2017-09-22 15:22:03 +00:00
Host: whoami1.traefik
User-Agent: curl/7.55.1
2016-10-06 13:48:23 +00:00
Accept: */*
Accept-Encoding: gzip
2017-09-22 15:22:03 +00:00
X-Forwarded-For: 10.255.0.4
X-Forwarded-Host: whoami1.traefik
2016-10-06 13:48:23 +00:00
X-Forwarded-Proto: http
2017-09-22 15:22:03 +00:00
X-Forwarded-Server: 77fc29c69fe4
2016-10-06 13:48:23 +00:00
```
2017-01-07 08:20:52 +00:00
## Scale both services
2017-04-30 18:17:57 +00:00
```shell
2017-01-07 08:20:52 +00:00
docker-machine ssh manager "docker service scale whoami0=5"
docker-machine ssh manager "docker service scale whoami1=5"
```
Check that we now have 5 replicas of each `whoami` service:
2017-04-30 18:17:57 +00:00
```shell
2017-01-07 08:20:52 +00:00
docker-machine ssh manager "docker service ls"
2017-09-05 13:58:03 +00:00
```
```
2017-09-22 15:22:03 +00:00
ID NAME MODE REPLICAS IMAGE PORTS
moq3dq4xqv6t traefik replicated 1/1 traefik:latest *:80->80/tcp,* :8080->8080/tcp
2018-10-25 15:04:03 +00:00
ysil6oto1wim whoami0 replicated 5/5 containous/whoami:latest
z9re2mnl34k4 whoami1 replicated 5/5 containous/whoami:latest
2017-01-07 08:20:52 +00:00
```
2017-09-22 15:22:03 +00:00
2018-10-17 14:24:04 +00:00
## Access to your `whoami0` through Traefik multiple times.
2017-01-07 08:20:52 +00:00
2017-08-26 10:12:44 +00:00
Repeat the following command multiple times and note that the Hostname changes each time as Traefik load balances each request against the 5 tasks:
2017-04-30 18:17:57 +00:00
```shell
2017-01-07 08:20:52 +00:00
curl -H Host:whoami0.traefik http://$(docker-machine ip manager)
2017-09-05 13:58:03 +00:00
```
```yaml
2017-09-22 15:22:03 +00:00
Hostname: f3138d15b567
2017-01-07 08:20:52 +00:00
IP: 127.0.0.1
2017-09-22 15:22:03 +00:00
IP: 10.0.0.5
IP: 10.0.0.4
2017-01-07 08:20:52 +00:00
IP: 172.18.0.3
GET / HTTP/1.1
2017-09-22 15:22:03 +00:00
Host: whoami0.traefik
User-Agent: curl/7.55.1
2017-01-07 08:20:52 +00:00
Accept: */*
Accept-Encoding: gzip
2017-09-22 15:22:03 +00:00
X-Forwarded-For: 10.255.0.2
X-Forwarded-Host: whoami0.traefik
2017-01-07 08:20:52 +00:00
X-Forwarded-Proto: http
2017-09-22 15:22:03 +00:00
X-Forwarded-Server: 77fc29c69fe4
2017-01-07 08:20:52 +00:00
```
2017-09-22 15:22:03 +00:00
Do the same against `whoami1` :
2017-08-26 10:12:44 +00:00
2017-04-30 18:17:57 +00:00
```shell
2017-09-22 15:22:03 +00:00
curl -c cookies.txt -H Host:whoami1.traefik http://$(docker-machine ip manager)
2017-09-05 13:58:03 +00:00
```
```yaml
2017-09-22 15:22:03 +00:00
Hostname: 348e2f7bf432
2017-01-07 08:20:52 +00:00
IP: 127.0.0.1
2017-09-22 15:22:03 +00:00
IP: 10.0.0.15
IP: 10.0.0.6
IP: 172.18.0.6
2017-01-07 08:20:52 +00:00
GET / HTTP/1.1
2017-09-22 15:22:03 +00:00
Host: whoami1.traefik
User-Agent: curl/7.55.1
2017-01-07 08:20:52 +00:00
Accept: */*
Accept-Encoding: gzip
2017-09-22 15:22:03 +00:00
X-Forwarded-For: 10.255.0.2
X-Forwarded-Host: whoami1.traefik
2017-01-07 08:20:52 +00:00
X-Forwarded-Proto: http
2017-09-22 15:22:03 +00:00
X-Forwarded-Server: 77fc29c69fe4
2017-01-07 08:20:52 +00:00
```
2017-09-11 17:10:04 +00:00
2017-09-22 15:22:03 +00:00
Because the sticky sessions require cookies to work, we used the `-c cookies.txt` option to store the cookie into a file.
The cookie contains the IP of the container to which the session sticks:
2017-08-26 10:12:44 +00:00
2017-09-05 13:58:03 +00:00
```shell
2017-09-22 15:22:03 +00:00
cat ./cookies.txt
```
```
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
whoami1.traefik FALSE / FALSE 0 _TRAEFIK_BACKEND http://10.0.0.15:80
2017-01-07 08:20:52 +00:00
```
2017-10-03 08:22:03 +00:00
If you load the cookies file (`-b cookies.txt`) for the next request, you will see that stickiness is maintained:
2017-01-07 08:20:52 +00:00
2017-09-22 15:22:03 +00:00
```shell
curl -b cookies.txt -H Host:whoami1.traefik http://$(docker-machine ip manager)
```
```yaml
Hostname: 348e2f7bf432
IP: 127.0.0.1
IP: 10.0.0.15
IP: 10.0.0.6
IP: 172.18.0.6
GET / HTTP/1.1
Host: whoami1.traefik
User-Agent: curl/7.55.1
Accept: */*
Accept-Encoding: gzip
Cookie: _TRAEFIK_BACKEND=http://10.0.0.15:80
X-Forwarded-For: 10.255.0.2
X-Forwarded-Host: whoami1.traefik
X-Forwarded-Proto: http
X-Forwarded-Server: 77fc29c69fe4
```
2017-01-07 08:20:52 +00:00
2018-07-12 16:26:03 +00:00
![GIF Magica ](https://i.giphy.com/ujUdrdpX7Ok5W.gif )