|
Container Orchestration with Docker Swarm |
|
================================================== |
|
|
|
Key concepts quick review |
|
-------------------------------------------------- |
|
|
|
+ Images |
|
+ Dockerfile |
|
+ Docker Hub |
|
+ Host |
|
+ Container |
|
+ Swarm |
|
|
|
The tools |
|
-------------------------------------------------- |
|
|
|
+ [Docker Toolbox for Windows](https://www.docker.com/docker-toolbox) |
|
* Docker client |
|
* docker-machine |
|
+ [Compose for Windows (RC)](https://github.com/docker/compose/releases/tag/1.5.0rc3) |
|
|
|
The project |
|
-------------------------------------------------- |
|
|
|
![Diagrama](https://s3-us-west-2.amazonaws.com/ciberado/docker-swarm-demo-haproxy.png) |
|
|
|
|
|
Setting up the Swarm registry |
|
-------------------------------------------------- |
|
|
|
```bash |
|
docker-machine create -d virtualbox keystore |
|
docker-machine env keystore --shell cmd |
|
FOR /f "tokens=*" %i IN ('docker-machine env keystore --shell cmd') DO %i |
|
docker run -d -p 8500:8500 -h consul progrium/consul -server -bootstrap |
|
docker-machine ip keystore |
|
for /f "delims=" %a in ('docker-machine ip keystore') do @set consul_ip=%a |
|
echo Consul IP: %consul_ip% |
|
``` |
|
|
|
Creating the Swarm master node |
|
-------------------------------------------------- |
|
|
|
```bash |
|
docker-machine create ^ |
|
-d virtualbox ^ |
|
--swarm --swarm-master ^ |
|
--swarm-discovery="consul://%consul_ip%:8500" ^ |
|
--engine-opt="cluster-store=consul://%consul_ip%:8500" ^ |
|
--engine-opt="cluster-advertise=eth1:2376" ^ |
|
swarm-master |
|
``` |
|
|
|
Starting the worker nodes: EDGE |
|
--------------------------------------------------- |
|
|
|
```bash |
|
docker-machine create -d virtualbox ^ |
|
--swarm ^ |
|
--swarm-discovery="consul://%consul_ip%:8500" ^ |
|
--engine-opt="cluster-store=consul://%consul_ip%:8500" ^ |
|
--engine-opt="cluster-advertise=eth1:2376" ^ |
|
--engine-label noderole=edge ^ |
|
cluster-node-0 |
|
``` |
|
|
|
Starting the worker nodes: API |
|
--------------------------------------------------- |
|
|
|
```bash |
|
docker-machine create -d virtualbox ^ |
|
--swarm ^ |
|
--swarm-discovery="consul://%consul_ip%:8500" ^ |
|
--engine-opt="cluster-store=consul://%consul_ip%:8500" ^ |
|
--engine-opt="cluster-advertise=eth1:2376" ^ |
|
--engine-label noderole=api ^ |
|
cluster-node-1 |
|
``` |
|
|
|
Starting the worker nodes: DATABASE |
|
--------------------------------------------------- |
|
|
|
```bash |
|
docker-machine create -d virtualbox ^ |
|
--swarm ^ |
|
--swarm-discovery="consul://%consul_ip%:8500" ^ |
|
--engine-opt="cluster-store=consul://%consul_ip%:8500" ^ |
|
--engine-opt="cluster-advertise=eth1:2376" ^ |
|
--engine-label noderole=db ^ |
|
cluster-node-2 |
|
``` |
|
|
|
Checking the cluster nodes |
|
--------------------------------------------------- |
|
|
|
[speaker notes]: <> (Open on new tabs and keep them for later) |
|
|
|
```bash |
|
docker-machine env --shell cmd swarm-master |
|
docker ps --format "{{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Command}}" |
|
docker run swarm list consul://%consul_ip%:8500 |
|
``` |
|
|
|
```bash |
|
docker-machine env --shell cmd cluster-node-0 |
|
docker ps --format "{{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Command}}" |
|
``` |
|
|
|
Connecting to the Swarm |
|
--------------------------------------------------- |
|
|
|
[speaker notes]: <> (On the main tab) |
|
|
|
```bash |
|
docker-machine env --shell cmd --swarm swarm-master |
|
FOR /f "tokens=*" %i IN ('docker-machine env --shell cmd --swarm swarm-master') DO %i |
|
docker ps --format "{{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Command}}" |
|
docker ps --all --format "{{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Command}}" |
|
docker info |
|
``` |
|
|
|
Launching containers with constraints |
|
--------------------------------------------------- |
|
|
|
[speaker notes]: <> (On the main tab) |
|
|
|
```bash |
|
start docker run -it --rm --name shell_0 ^ |
|
--env "constraint:noderole==api" ^ |
|
alpine:latest /bin/sh |
|
docker ps --format "{{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Command}}" |
|
``` |
|
|
|
[speaker notes]: <> (On the api aka cluster-node-0 tab) |
|
```bash |
|
docker ps --format "{{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Command}}" |
|
``` |
|
|
|
Launching containers with affinities |
|
--------------------------------------------------- |
|
|
|
[speaker notes]: <> (Remark the fact the shells are created in different hosts) |
|
|
|
```bash |
|
start docker run -it --rm --name shell_1 ^ |
|
--env "affinity:container!=shell*" ^ |
|
alpine:latest /bin/sh |
|
docker ps --format "{{.ID}}\t{{.Image}}\t{{.Names}}\t{{.Command}}" |
|
``` |
|
|
|
[speaker notes]: <> (Close the shell containers) |
|
|
|
Creating the network |
|
--------------------------------------------------- |
|
|
|
```bash |
|
docker network create --driver overlay demonetwork |
|
docker network ls |
|
``` |
|
|
|
[speaker notes]: <> (Repeat the ls command on the hosts tabs) |
|
|
|
Testing the network routing |
|
--------------------------------------------------- |
|
|
|
```bash |
|
start docker run -it --rm --name shell_0 ^ |
|
--env "constraint:node==cluster-node-0" ^ |
|
--net demonetwork alpine:latest /bin/sh |
|
start docker run -it --rm --name shell_1 ^ |
|
--env "constraint:node==cluster-node-1" ^ |
|
--net demonetwork alpine:latest /bin/sh |
|
``` |
|
|
|
[speaker notes]: <> (From shell_0, the second command doesn't works) |
|
|
|
```bash |
|
ping shell_1 |
|
ping shell_0 |
|
``` |
|
|
|
[speaker notes]: <> (Close both shells) |
|
|
|
Resolving the own dns name |
|
--------------------------------------------------- |
|
|
|
```bash |
|
start docker run -it --rm --name shell ^ |
|
--hostname shell ^ |
|
--env "constraint:node==cluster-node-0" ^ |
|
--net demonetwork alpine:latest /bin/sh |
|
``` |
|
|
|
[speaker notes]: <> (On the shell tab) |
|
|
|
```bash |
|
ping shell |
|
export mysqlip=$(getent hosts mysql | awk '{ print $1 }') |
|
``` |
|
|
|
[speaker notes]: <> (Close the tab) |
|
|
|
Manually launching the database |
|
--------------------------------------------------- |
|
|
|
[speaker notes]: <> (Remark this is a read-only db) |
|
|
|
```bash |
|
start docker run --name mysql -it --rm ^ |
|
--env "constraint:noderole==db" ^ |
|
--net demonetwork ^ |
|
capside/footballmatchdb |
|
``` |
|
|
|
Manually launching the API |
|
--------------------------------------------------- |
|
|
|
```bash |
|
start docker run -it --rm --name footballmatch ^ |
|
--env "constraint:noderole==api" ^ |
|
--net demonetwork ^ |
|
capside/footballmatch |
|
``` |
|
|
|
Manually launching the proxy |
|
--------------------------------------------------- |
|
|
|
```bash |
|
start docker run -it --rm --name haproxy ^ |
|
--env "constraint:noderole==edge" ^ |
|
--net demonetwork ^ |
|
--publish 80:80 ^ |
|
capside/footballmatchlb /bin/sh |
|
``` |
|
|
|
Checking the deployment |
|
--------------------------------------------------- |
|
|
|
```bash |
|
docker-machine ips cluster-node-0 |
|
for /f "delims=" %a in ('docker-machine ip cluster-node-0') do @set edge_ip=%a |
|
start http://%edge_ip%/index.html |
|
``` |
|
|
|
[speaker notes]: <> (Close all the containers) |
|
|
|
|
|
|
|
|