Context
Based on my previous post about managing a local docker registry, as promised let’s use it to create a useful image and deploy it on my swarm cluster homelab.
For this example, I’ve decided to use the latest image I’ve created: gmnisrv.
Wait what? Gmnisrv running on a docker swarm? Why??
There are no real good reason to have the gemini server as a docker service… So why? Well the real reasons? Because: - I can :p; - I have this docker swarm working very smoothly, so let’s use it; - I could have just installed it directly on one of the node, but that made not much sens; - I can manage it as all the other services^^.
Last week, I made the change from the local installation on a test pi to the cluster, smoothly from what I’ve seen, without certificate change. But that’s not the point of this article^^ (and TBH, I failed1 the weekend before :D).
Installation
Creating the image for the cluster
So first thing first, we need to create the image on the registry before being able to use it on the cluster. Feel free to refer to my post about managing a local docker registry.
On the registry (in my case named freeza
), let’s create the image.
Let’s create a working directory:
mkdir ~/dockerfiles/gmnisrv && cd ~/dockerfiles/gmnisrv
Then, create the very simple Dockerfile
:
FROM alpine:3.12
RUN apk add --no-cache git make scdoc openssl-dev build-base mailcap && \
cd /tmp && \
git clone https://git.sr.ht/~sircmpwn/gmnisrv && \
cd gmnisrv && \
mkdir build && \
cd build && \
../configure --prefix=/usr && \
make && \
make install
VOLUME /certs
VOLUME /config
VOLUME /data
CMD ["gmnisrv", "-C", "/config/gmnisrv.ini"]
Very simple :-).
Then, let’s try and build the image:
docker build .
If this works correctly, you can tag the image (I always prefix their
name with b55-
):
docker build . -t registry.local:5000/b55-gmnisrv:latest
Adapt with your registry hostname and port.
Push the image to the directory:
docker push registry.local:5000/b55-gmnisrv:latest
To test the image, you can either use docker run
or docker-compose
.
Because I’m will use a docker-compose file on my cluster, I prefer
testing it with a docker-compose file, buit this doesn’t matter.
In my case, the local docker-compose.yml file is:
version: '3'
services:
gmnisrv:
image: registry.local:5000/b55-gmnisrv:latest
ports:
- 1965:1965
volumes:
- /path/to/testdir/gmnisrv/data/:/data
- /path/to/testdir/gmnisrv/config/:/config
- /path/to/testdir/gmnisrv/certs:/certs
Then the usual docker-compose up
to see if this works correctly (be
sure to create the volumes if you want to try with it).
If you want to run a full test before deploying on your cluster, you can create a simple .gmi file in the data directory, create a dev host in the gmnisrv config file (and edit your host file).
Deploying it to the cluster
If everything work, we can use it on the cluster. Adapt a bit the docker file to have:
version: '3'
services:
server:
image: registry.local:5000/b55-gmnisrv:latest
ports:
- "1965:1965"
deploy:
placement:
constraints:
- node.hostname == ptitcell2
volumes:
- /path/to/containers-data/gmnisrv/data/:/data
- /path/to/containers-data/gmnisrv/certs/:/certs
- /path/to/services-config/gmnisrv/config/:/config
Main difference the placement constraints to a specific node of the cluster. I could have use traefik for load balancing the entry like I do for all services… But I didn’t^^. I didn’t see the point of adding load to traefik and the node manager for gmnisrv that works on a port that will only be used by gmnisrv. Gmnisrv support multi hosts anyway if I want to add capsules in the future (I’m planing to have a feed type of capsule).
So, long story short, I force the container to only work on the
ptitcell2
node. And I forward the 1965 port on my router to the
ptitcell2
node. I thus save a bit on the manager.
If you don’t care by recreating new certs (if your capsule wasn’t live
yet), you can just start it like this, otherwise just copy/paste the
certificates in the right folder before starting the stack with
docker stack deploy gmnisrv -c /path/to/services-config/gmnisrv/docker-compose.yml
.
And voilà :] Granted that I have close to no reader on my capsule, I can still say it has worked perfectly since then!
-
In reality I failed for multiple reasons, but also discovered a bug in the latest version of gmnisrv. I fixed it with the help of Drew Devault. Since then my patch has been accepted so even if what I wrote was the simplest patch in the history of patch, I’m still happy about it^^. ↩︎