Docker Swarm

From Wildsong
Revision as of 19:44, 21 April 2023 by Brian Wilson (talk | contribs)
Jump to navigationJump to search

Docker Swarm is an orchestrator and so is Kubernetes.

Kubernetes is breathing down my neck too and today I am thinking, "What the hell, go for it! Why NOT run a single node with Kubernetes?" I spent an hour looking at it and it just adds more complexity.

Some day I will spin up some IoT and Edge nodes for buzzword compliance but for now it's just one node. Bellman

Note, it made me pick an ethernet address.

bellman> docker swarm init --advertise-addr 192.168.123.2
Swarm initialized: current node (isk0jocx0rb37yonoafstyvoj) is now a manager.

To add a worker to this swarm, run the following command:

   docker swarm join --token SWMTKN-1-5b81dywl9xkis6769fxnsvjahfy361w2kxkz69nc35bz3nxt6s-43jxeopl6inw8xur1vpcl23w7 192.168.123.2:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

I can add a node on another machine using that token. I won't be doing this today. It would look like this.

tern> docker swarm join --token SWMTKN-1-5b81dywl9xkis6769fxnsvjahfy361w2kxkz69nc35bz3nxt6s-43jxeopl6inw8xur1vpcl23w7 192.168.123.2:2377
This node joined a swarm as a worker.
bellman> docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE  VERSION
isk0jocx0rb37yonoafstyvoj *   bellman             Ready               Active              Leader              19.03.5
vjbx2h8n8280ecib2btzkwcxw     tern                Ready               Active                                  18.09.1
bellman> docker network create -d overlay --attachable testing
shaboxhgakqer14j1ve7zyysj

The "attachable" option is for containers not yet running in swarm. I will need that soon, when I run bash in Debian for tests.

Now ordinarily I'd use Docker Compose to start a reverse proxy (my favorite today is Varnish).

Before worrying about Varnish though I will spin up simple web server on just the one existing node. If I add tern it will spread them over the two nodes. I want it to use that "testing" network.

docker service create --name web --replicas 4 -p 80:80 --network testing --detach nginx:latest

Now I have 4 copies of nginx running. I can see that they were published on port 80 but that's inside the funny swarm network, how to see them? They are on localhost, I can do this "curl http://localhost". I can get the id (or just use the name "web") and then kill them off,

docker service ls
docker service rm pmbrvm6wow7q
curl http://localhost

When I do the "curl" with the nginx replicas shut down, I see the page served by Varnish (still running in Compose), it's the Home Assistant instance. So I guess the swarm takes precedence over whatever is running in Compose.

I skipped the "--network testing" parameter and everything still worked. I think maybe that's just so I can attach more services later?? Like this. This looks the way I expected.

docker run -it --rm --network testing debian:bullseye bash
# apt update
# apt install -y bind9-dnsutils
# nslookup web
Server:         127.0.0.11
Address:        127.0.0.11#53

Non-authoritative answer:
Name:   web
Address: 10.0.1.27
# apt install -y curl
# curl http://10.0.1.27
# curl http://web/

The standard nginx page is returned from curl both times, so I know it's hitting a replica and running under the name "web", which is what I assigned. Inside the container I can see my local LAN too, for example from the Debian instance I can "curl http://bellman.wildsong.biz:8123/" and get the Home Assistant page. So far, easy easy.

That healthcheck thing

It's not too soon to think about it. ;-)

With nginx I can create my own Docker image and build the healthcheck right into the image.

Yes I know "curl" is not the answer. https://blog.sixeyed.com/docker-healthchecks-why-not-to-use-curl-or-iwr/ but for now it's what I am using! In my Dockerfile,

FROM nginx:latest
HEALTHCHECK CMD curl --fail http://localhost || exit 1
$ docker build -t wildsong/nginx .
$ docker service rm web
$ docker service create --name web --replicas 1 -p 80:80 --network testing --detach wildsong/nginx
$ docker ps | grep web
01a3f36f7580   wildsong/nginx:latest                                      "/docker-entrypoint.…"   About a minute ago   Up About a minute (healthy)   80/tcp   web.1.ssssfmwmwp8je7g1dnsabevew

When I create the service, I will get a warning because I have not pushed that image (wildsong/nginx) to a registry, but it still works because I am running only one node for now. When I do the "docker ps" I can see that the container is marked as "healthy".

LUNCH BREAK NOW.

How do volumes work in a swarm?

docker service create --name proxy \
 -p 80:80 -p 443:443 \
 -e DHPARAM_GENERATION="false" \
 -v /var/run/docker.sock:/tmp/docker.sock:ro \
 -v ./network_internal.conf:/etc/nginx/network_internal.conf \
 -v ./vhost.d:/etc/nginx/vhost.d \
 -v proxy_html:/usr/share/nginx/html \
 -v proxy_dhparam:/etc/nginx/dhparam \
 -v proxy_certs:/etc/nginx/certs:ro \
 jwilder/nginx-proxy:alpine

Bring in Compose

By that I mean I want to deploy a stack of containers using a docker-compose.yml file as the configuration. So far I have not needed it, if I start just one container per project then "docker service" commands are fine.