Docker Swarm with Traefik + Prometheus + Grafana for local development

Containerization is one of todays must have knowledge for all developers. I guess that during a time it will be more and more important. I am using Docker for local development already for many years and I can see only benefits from that. Todays most favorite choice for containerization is kubernetes that offers variety of possibilities, but before I will post something about Kubernetes I would like to present my old good friend Docker Swarm - that can be easily used also in production for some smaller private clusters.

Docker Swarm, Traefik, Prometheus and Grafana

Example Docker Swarm repository

I've prepared small repository that should be simple starting point to play with Docker Swarm locally.

You don't need to install any technology locally if you are using Docker.

Init your docker swarm mode

If you decide to play with this stack you can have at least basic knowledge of using docker compose tool. You will recycle that knowledge here.

You should enable you docker swarm mode with simple command:

docker swarm init

Like this you initialized your computer as cluster manager. Console output will contain also your connection that you can play around with that with other computers in your local network or even with anyone else if you have public address.

Init networking

I am using two overlay networks for most of my projects. One is for public containers and second is only for persistence purpose.

docker network create --driver overlay --attachable inbound 
docker network create --driver overlay --attachable persistence

This networks are created as --attachable which will allow you to join network also with docker run ... command.

Repository directory structure

I am using simple separation concern of dividing stack of my local development with dividing each stack to specific folder. This method allows me to imitate something like namespaces for stacks.

I think that most important folders traefik and persistence - which contains more all you need to start to build some web project.

Inside each folder you will find YAML definition for specific service.

So in persistence folder you find YAML configs for databases. Surprise! :)

persistence
├── elasticsearch.yml
├── kibana.yml
├── mongodb.yml
├── mysql.yml
├── osrm.yml
├── rabbitmq.yml
├── redis.yml
└── volumes
    ├── elasticsearch
    └── ...

Init Traefik, Prometheus and Grafana

Let's start to create some container in our cluster. I would start with some reverse proxy server that will allow me to use localhost domains for all of my projects. Means domains like martinkrizan.localhost or api.martinkrizan.localhost.

For this purpose I am using Traefik proxy that is one of the most used application in container world and for me it is better alternative that Nginx, that can be also used.

# in traefik dictionary
docker stack deploy -c localhost.yml traefik

Where traefik is defining name of our stack. This will try to use port :80 and also :8080 of your computer and will start 3 services - Traefik, Prometheus and Grafana. How to use them is a bit wider topic which worth to be described in separate articles.

You can check if your traefik stack runs with:

docker service ls | grep traefik

And see that all three service are running. If yes, then you can visit http://localhost:8080/dashboard/#/ and see Traefik dashboard.

Create persistence services

To be able to use some database in your stack - you will probably need some persistence storage for your. We will leave aside question if it is good or bad to use Docker for running database instances because in local environment it's completely fine.

Like this you can start Redis and MySQL in your persistence stack.

# in /persistence directory
docker stack deploy -c redis.yml peristence
docker stack deploy -c mysql.yml persistence

Now we have a working cluster with web proxy for our application containers and also persistence instances ready. Let's build some app.

Use it with your application

I've prepared demonstration PHP app that we will use now. The most important file from repository is YAML configuration for our cluster.

version: '3.7'

services:
  example-php-app:
    image: krizius/php:8.1-apache
    volumes:
      - .:/var/www
    networks:
      - inbound
      - persistence
    deploy:
      labels:
        - traefik.enable=true
        - traefik.docker.network=inbound
        - traefik.http.routers.example-php-app.rule=Host(`example-php-app.localhost`)
        - traefik.http.routers.example-php-app.entrypoints=web
        - traefik.http.routers.example-php-app.service=example-php-app
        - traefik.http.services.example-php-app.loadbalancer.server.port=80
      restart_policy:
        condition: on-failure

networks:
  inbound:
    external: true
  persistence:
    external: true

As you should notice it's in fact standard docker-compose.yml file except few tweaks.

We will concentrate on deploy section where are config labels for Traefik. This labels are telling how we want to route our application and what port should be proxied. If you will with that a bit - search example-php-app in that file and replace this string with definition of your app service.

You can run this app with:

docker stack deploy -c localhost.yml martinkrizan

In conclusion

This is very brief intro how to run my personal dev stack that I am using every day and also using bit-more extended version also on production for smaller projects. I also tested with few colleagues that it is also good starting point to start to play with Docker Swarm in practical way. If you will try that journey - I wish you good luck!

Tags: #docker , Created: 12. 8. 2022
Created by Martin Krizan (2022)