121 lines
4.4 KiB
Markdown
121 lines
4.4 KiB
Markdown
|
---
|
||
|
title: 'Run Pi-Hole as Docker Swarm Stack'
|
||
|
date: 2022-01-28T08:54:43+01:00
|
||
|
draft: false
|
||
|
# lastmod: 2022-01-28T08:54:43+01:00
|
||
|
# showDateUpdated: true
|
||
|
|
||
|
# custom overrides for pages
|
||
|
# showDate: false
|
||
|
# showAuthor: false
|
||
|
# showWordCount: false
|
||
|
# showReadingTime: false
|
||
|
# showEdit: false
|
||
|
# sharingLinks: [null]
|
||
|
---
|
||
|
|
||
|
## Intro
|
||
|
|
||
|
Many of you already know [Pi-Hole](https://pi-hole.net/) as a trusted DNS firewall solution in your home labs. But
|
||
|
what if your home lab should just provide containerized services? - I know, running Pi-Hole as a container isn't
|
||
|
new. In fact, the developer community already provides [official images](https://hub.docker.com/r/pihole/pihole).
|
||
|
|
||
|
In this post I want to show you why you should run Pi-Hole (or even every container) in a docker swarm configuration
|
||
|
as a defined stack.
|
||
|
|
||
|
So let's begin with some worts about the Docker Swarm Mode.
|
||
|
|
||
|
### What's Docker Swarm Mode ?
|
||
|
|
||
|
[Docker Swarm Mode](https://docs.docker.com/engine/swarm/) takes simply multiple Docker engines and creates a
|
||
|
cluster. On these docker nodes you can then run containers defined in a stack files. These stacks are written in the
|
||
|
same format as `docker-compose.yml` files. After deploying the stack the engine takes care about the deployment
|
||
|
on suitable nodes.
|
||
|
|
||
|
I think the best feature is that you can update your stacks and its container services. This makes updating your
|
||
|
containers much easier whenever there is a new image version available. Without this feature you needed to stop and
|
||
|
restart your containers with docker-compose.
|
||
|
|
||
|
{{< alert >}}
|
||
|
Don't expect to get a fully featured cluster management for container environments like
|
||
|
[Kubernetes](https://kubernetes.io/docs/concepts/overview/what-is-kubernetes/) with Docker Swarm
|
||
|
Mode. You still need to take care about key element by yourself. For example how to and how to sync volumes and
|
||
|
make them available on all nodes.
|
||
|
On the other hand, Kubernetes isn't always needed and comes not only with mor features - It also requires ab better
|
||
|
knowledge about the underlying techniques and faces you with much more challenges.
|
||
|
{{< /alert >}}
|
||
|
|
||
|
### Pi-Hole Stack
|
||
|
|
||
|
I use [traefik](https://traefik.io/traefik/) on my docker swarm clusters as reverse proxy. Like every reverse proxy
|
||
|
traefik handles the request and routes it to to the target service. It terminates the https traffic and manages the
|
||
|
certificates. You could also use something else like [Nginx Proxy Manager](https://nginxproxymanager.com/).
|
||
|
Just keep in mind, that the listed service labels are required for traefik to perform its dynamic config.
|
||
|
|
||
|
```yaml
|
||
|
version: '3.8'
|
||
|
|
||
|
# More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/
|
||
|
services:
|
||
|
pihole:
|
||
|
image: pihole/pihole:2022.01.1
|
||
|
ports:
|
||
|
- target: 53
|
||
|
published: 53
|
||
|
protocol: tcp
|
||
|
mode: host
|
||
|
- target: 53
|
||
|
published: 53
|
||
|
protocol: udp
|
||
|
mode: host
|
||
|
- target: 67
|
||
|
published: 67
|
||
|
protocol: udp
|
||
|
mode: host
|
||
|
environment:
|
||
|
TZ: 'Europe/Berlin'
|
||
|
WEBPASSWORD: 'foobar2000'
|
||
|
# Volumes store your data between container upgrades
|
||
|
volumes:
|
||
|
- /nfs-share/pihole/volumes/pihole-data:/etc/pihole/
|
||
|
- /nfs-share/pihole/volumes/pihole-dnsmasq:/etc/dnsmasq.d/
|
||
|
|
||
|
# Recommended but not required (DHCP needs NET_ADMIN)
|
||
|
# https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
|
||
|
#cap_add:
|
||
|
# - NET_ADMIN
|
||
|
networks:
|
||
|
- pihole
|
||
|
- traefik-public
|
||
|
deploy:
|
||
|
replicas: 1
|
||
|
labels:
|
||
|
- 'traefik.enable=true'
|
||
|
- 'traefik.docker.network=traefik-public'
|
||
|
- 'traefik.http.routers.pihole.rule=Host(`pihole.mydomain.io`)'
|
||
|
- 'traefik.http.routers.pihole.tls=true'
|
||
|
- 'traefik.http.routers.pihole.tls.certresolver=myresolver'
|
||
|
- 'traefik.http.services.pihole-srv.loadbalancer.server.port=80'
|
||
|
|
||
|
networks:
|
||
|
pihole:
|
||
|
traefik-public:
|
||
|
external: true
|
||
|
```
|
||
|
|
||
|
The special part here is the port config. Normally you would use this syntax to publish ports:
|
||
|
|
||
|
```yaml
|
||
|
ports:
|
||
|
- '53:53/tcp'
|
||
|
- '53:53/udp'
|
||
|
- '67:67/udp'
|
||
|
- '8080:80/tcp'
|
||
|
```
|
||
|
|
||
|
But this publishes the ports on the ingress / overlay network and causes pihole to show only the service ip on the
|
||
|
connected clients list. So we have to use the long format with the `mode` set to `host`. This of cause does only work
|
||
|
if there is no other process already using the listed ports.
|
||
|
|
||
|
Additionally you have to set `Permit all origins` option under `settings` -> `dns tab` -> `Interface settings`.
|