4 Important Services Everyone Should Deploy In A Docker Swarm
Paul Knulst
Posted on July 29, 2023
Enhance your Docker Swarm with four important services that you will love: Traefik, Portainer, Registry, FTP
In a previous article, I showed how a Docker Swarm is set up in ~15 minutes.
Remember: Whenever you read “Docker Swarm” we are talking about “Docker in Docker Swarm mode”
Within this article, I will show and explain four services everyone should use in their Docker Swarm: traefik, Portainer, Docker-Registry, FTP.
Traefik
Makes Networking Boring
Cloud-Native Networking Stack That Just Works.
One important service in any Docker Swarm is traefik. I use this for assigning domains/subdomains to every docker service. A simple docker-compose.yml can be found on my FTP here. To use this file it is necessary to update the labels for your docker swarm by executing:
export NODE_ID=$(docker info -f '{{.Swarm.NodeID}}')
docker node update --label-add traefik-public.traefik-public-certificates=true $NODE_ID
These two commands assume that you want to have traefik on your manager node! To understand what a manager node have a look at the docker documentation.
Another VERY important step is creating a file named acme.json
within the folder where the docker-compose will be stored and do:
chmod 600 acme.json
Furthermore, you have to define a TRAEFIK_USERNAME
, TRAEFIK_HASHED_PASSWORD
, TRAEFIK_DOMAIN
and TRAEFIK_SSLEMAIL
:
export TRAEFIK_USERNAME=admin
export TRAEFIK_HASHED_PASSWORD=$(openssl passwd -apr1 testpassword)
export TRAEFIK_DOMAIN=dashboard.YOUR_DOMAIN.tld
export TRAEFIK_SSLEMAIL=your_email@address.de
The last command which has to be executed before you can deploy the service is creating the traefik-public
network which will be used across all containers:
docker network create --driver=overlay traefik-public
After this is done it is possible to deploy traefik to your docker swarm:
docker stack deploy -c docker-compose.traefik.yml
Just test it by launching https://dashboard.YOUR_DOMAIN.tld
. This domain will use an SSL certificate and you can log in with admin/testpassword if you followed the above instructions.
Portainer
Portainer is a powerful, GUI-based Container-as-a-Service solution that helps organizations manage and deploy cloud-native applications easily and securely.
My docker-compose.yml for Portainer is not special. You can find it here if you need it. Normally there are no differences between my and the one you find if you google for Portainer service.
If you use mine you have to *add a label to your manager!* *This is very important* because Portainer needs a connection to your docker socket. You can add the label with these commands:
export NODE_ID=$(docker info -f '{{.Swarm.NodeID}}')
docker node update --label-add portainer.portainer-data=true $NODE_ID
Furthermore declare the PORTAINER_DOMAIN
which will be used.
export PORTAINER_DOMAIN=portainer.$PRIMARY_DOMAIN
After you have done this you can deploy Portainer:
docker stack deploy -c docker-compose.portainer.yml portainer
Timing Note: Make sure you log in and create your credentials soon after Portainer is ready, or it will automatically shut down itself for security. If you didn’t create the credentials on time and it shut down itself automatically, you can force it to restart with:
docker service update portainer_portainer --force
Docker Registry
The Registry is a stateless, highly scalable server side application that stores and lets you distribute Docker images. The Registry is open-source, under the permissive Apache license.
The docker registry is important to have in a swarm environment if you don't want to upload your code/data to a public registry. If you don't have any private registry for yourself you have to upload the resulting image to docker-hub each time you extend an official image with your application code. While this is great if you only want to extend functionality in a general way it is not advisable if you copy your website with your closed source code into the image.
Imagine you have a modified Nginx image where the HTML folder is copied into the image:
FROM nginx
COPY html /usr/share/nginx/html
In many cases the html
folder will contain your website which you don't want someone to use. If you have a private registry you can build the image and upload it but if you don't have one you have to use a public registry.
That's why I think that every swarm needs to have access to a private registry. And that's why I created one. Normally you can set up a registry with a simple docker run
command but I wanted to have a registry that can be reached from everywhere. Because of that, I created a registry that could be accessed by username and password.
My personal docker-compose.yml
can be downloaded here. It will run within my Traefik environment and create a new registry that I can use from every node in my swarm. To deploy the service you have to declare some environment variables which are used while deploying: REGISTRY_USERNAME
, REGISTRY_HASHED_PASSWORD
and REGISTRY_HOST
:
export REGISTRY_USERNAME=reg_adm
export REGISTRY_HASHED_PASSWORD=$(openssl passwd -apr1 regsupersecret)
export REGISTRY_HOST=reg.YOUR_DOMAIN.tld
With these variables you can deploy the service:
docker stack deploy -c docker-compose.registry.yml registry
To use the registry you have to do two more things. The first thing is a quality of life feature to easily change the domain of the registry without affecting every container which uses an image from the private registry. *Add DOCKER_REGISTRY to .profile for* ****root****
*or whatever user you are using so it is known if docker-compose files should be pushed/downloaded*. The second task is very important. You have to execute docker login
on every node of your swarm so that every node is allowed to pull images.
Now you can start using your private registry in docker-compose.yml. If you created a DOCKER_REGISTRY
environment variable you can use it like this in your docker-compose.yml:
myapp:
image: ${DOCKER_REGISTRY}/simple-app
build:
context: ./
dockerfile: Dockerfile
If you want to deploy a service that contains the above part you have to build and push your image to deploy it correctly:
docker-compose build
docker-compose push
docker stack deploy -c docker-compose.yml www
If you only build and deploy it other nodes in your swarm cannot pull the image and so the service cannot be deployed.
FTP
Another important service is an FTP server for saving files you want to use anywhere in any app or service you create while working with the swarm.
I decided to use “pure-ftp” because it was the one I found while googling for a nice FTP server that runs within a docker environment. Because I want to keep it simple I created an FTP server without any traefik
configuration. BUT I did a simple trick in putting the FTP server together with a website in a docker-compose.yml. I have done this because I want to have the possibility to download files from the server over https
which I uploaded with ftp
.
After configuration, I came up with this docker-compose.yml. Within the file, you can see that I use a custom Dockerfile for the web service which contains:
FROM nginx
COPY html /usr/share/nginx/html
The trick I describe is just the defined volume within the docker-compose.yml
. As you can see I defined data in both services. Within web-service
I just have an extra folder within the Nginx HTML folder so that I can access it from the web. And within the ftp-service
I define data as the place where user can upload their data.
Before it is possible to deploy this service you have to declare environment variables: FTP_USERNAME
, FTP_PASSWORD
, FTP_DOMAIN_FOR_CERT
, FTP_ORG_FOR_CERT
, FTP_COUNTRYCODE_FOR_CERT
and WEBSERVICE_DOMAIN
:
export WEBSERVICE_DOMAIN=www.MYDOMAIN.tld
export FTP_USERNAME=SUPERUSER
export FTP_PASSWORD=clearTextPW
export FTP_DOMAIN_FOR_CERT=$WEBSERVICE_DOMAIN
export FTP_ORG_FOR_CERT=mybusiness
export FTP_COUNTRYCODE_FOR_CERT=DE
Furthermore, you have to add a label to any node of your swarm. To achieve this use docker node ls
to find out the ID from every node and execute:
docker node update --label-add www.ftp-data=true ID_OF_NODE_TO_USE
After this is done you can safely deploy your website with enabled FTP
docker stack deploy -c docker-compose.web.yml webandftp
Now it is possible to connect with an FTP client to your WEBSERVICE_DOMAIN
and upload a file (test.txt
) which then can be accessed by this URL: WEBSERVICE_DOMAIN/data/test.txt
The whole FTP docker service can be downloaded from my GitHub:
https://github.com/paulscode-de/ftp-server
It is very important to say that you only can connect with your WEBSERVICE_DOMAIN if this domain also has an A record to your manager node!
5. Closing Notes
I hope you find this article helpful and can use my provided files to set up these services within your own Docker Swarm.
In my humble opinion, these four services should be present in every Docker Swarm environment because they are mandatory (or exchanged with function-like services).
This article was originally published on my blog at https://www.paulsblog.dev/services-you-want-to-have-in-a-swarm-environment/
Feel free to connect with me on my blog, Medium, LinkedIn, Twitter, and GitHub.
🙌 Support this content
If you like this content, please consider supporting me. You can share it on social media or buy me a coffee! Any support helps!
Furthermore, you can sign up for my newsletter to show your contribution to my content. See the contribute page for all (free or paid) ways to say thank you!
Thanks! 🥰
Photo by frank mckenna / Unsplash
Posted on July 29, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.