Vous consultez actuellement Installer Pi-hole sur un NAS UGREEN via Docker : le guide (avec tous les pièges évités)

Installer Pi-hole sur un NAS UGREEN via Docker : le guide (avec tous les pièges évités)

  • Auteur/autrice de la publication :
  • Catégorie de la publication :Jeedom

Installer Pi-hole sur un NAS UGREEN via Docker : le guide (avec tous les pièges évités)

Pi-hole est un bloqueur de publicités et de trackers qui agit au niveau DNS pour tout votre réseau domestique. L’installer sur un NAS via Docker semble simple sur le papier, mais plusieurs pièges classiques peuvent transformer une install de 10 minutes en dépannage de plusieurs heures. Voici le retour d’expérience complet, avec chaque blocage rencontré et sa solution.

Pourquoi Pi-hole et pourquoi sur un NAS

Plutôt que d’installer Pi-hole sur un Raspberry Pi dédié, l’héberger sur un NAS déjà allumé (UGREEN DXP2800 dans ce cas) évite d’ajouter un appareil supplémentaire. Le NAS tourne déjà Docker pour d’autres services (Jellyfin, Ollama, Frigate, Portainer), Pi-hole vient s’ajouter à cet écosystème.

Étape 1 : le mode réseau « host » pose problème

Premier réflexe naturel : lancer le conteneur en mode réseau host, recommandé dans beaucoup de tutoriels car il simplifie la gestion des ports DNS. Sauf que sur un NAS UGREEN (UGOS), un service dnsmasq système tourne déjà en interne pour la résolution locale. Résultat : conflit immédiat sur le port 53, le webserver de Pi-hole refusant même de démarrer faute de ports web configurés.

Solution retenue : basculer en mode réseau bridge, avec un mapping de ports explicite plutôt que de partager la pile réseau du NAS.

Étape 2 : le port 53 « déjà utilisé » alors qu’il ne l’est pas vraiment

En bridge, l’interface graphique de Container Manager refuse le mapping du port 53, avec le message « Numéro de port déjà utilisé ». Vérification en SSH :

sudo netstat -tulpn | grep :53

Le dnsmasq système écoute bien sur le port 53, mais uniquement sur 127.0.0.1 (loopback) et deux IP internes Docker (192.100.x.1). Techniquement, le port 53 est donc libre sur l’IP LAN réelle du NAS. Mais l’interface graphique de Container Manager ne fait pas cette distinction fine et bloque tout mapping du port 53, quelle que soit l’IP.

Solution : sortir de l’UI graphique et passer par docker run en ligne de commande, qui permet de spécifier explicitement l’IP du NAS dans le mapping :

sudo docker run -d \
  --name pihole \
  --network bridge \
  -p 192.168.2.101:53:53/tcp \
  -p 192.168.2.101:53:53/udp \
  -p 8080:80/tcp \
  -p 8443:443/tcp \
  -e TZ=Europe/Paris \
  --cap-add=NET_ADMIN \
  --cap-add=NET_RAW \
  --cap-add=SYS_NICE \
  --cap-add=SYS_TIME \
  -v /volume1/docker/pihole/etc-pihole:/etc/pihole \
  -v /volume1/docker/pihole/etc-dnsmasq:/etc/dnsmasq.d \
  --restart unless-stopped \
  pihole/pihole:latest

En forçant le bind sur 192.168.2.101 plutôt que 0.0.0.0, Docker n’entre plus en conflit avec le dnsmasq système lié au loopback.

Étape 3 : le routeur pointe vers Pi-hole, mais aucune requête n’arrive

Une fois Pi-hole lancé et le mot de passe web configuré, direction le routeur (un Asus RT-AC88U ici) pour changer le serveur DNS distribué en DHCP vers l’IP du Pi-hole. Logique simple : les appareils du réseau reçoivent alors ce DNS et devraient interroger Pi-hole.

Sauf que le dashboard reste désespérément vide, plusieurs heures après le changement. Test en local avec nslookup :

nslookup google.com 192.168.2.101
DNS request timed out.

Aucune réponse. Les logs du conteneur donnent l’explication :

WARNING: dnsmasq: ignoring query from non-local network 192.168.2.226 (logged only once)

Pi-hole, en mode réseau bridge, considère par défaut que le réseau LAN (192.168.2.x) est un réseau « externe » par rapport à son propre sous-réseau Docker interne. Il rejette donc silencieusement toutes les requêtes venant du LAN — comportement de sécurité par défaut (dns.listeningMode = LOCAL), pertinent en mode host mais pénalisant en bridge.

Solution :

sudo docker exec -it pihole pihole-FTL --config dns.listeningMode ALL

Une fois basculé sur ALL, les requêtes DNS commencent immédiatement à apparaître dans le tableau de bord.

Étape 4 : les ports disparaissent après chaque redémarrage du NAS

Le NAS étant éteint chaque nuit puis rallumé, un nouveau problème est apparu : après reboot, le conteneur redémarre bien (grâce à --restart unless-stopped et au démarrage automatique de Container Manager activé dans UGOS Pro), mais sans aucun port mappé. docker ps affiche le conteneur « healthy », mais la colonne PORTS est vide : ni le DNS ni l’interface web ne répondent.

Le lancement via docker run en une commande manuelle s’est révélé fragile face aux redémarrages orchestrés par UGOS. Solution : migrer vers un fichier docker-compose.yml, plus stable et reproductible :

services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    network_mode: bridge
    ports:
      - "192.168.2.101:53:53/tcp"
      - "192.168.2.101:53:53/udp"
      - "0.0.0.0:8080:80/tcp"
      - "0.0.0.0:8443:443/tcp"
    environment:
      - TZ=Europe/Paris
    cap_add:
      - NET_ADMIN
      - NET_RAW
      - SYS_NICE
      - SYS_TIME
    volumes:
      - /volume1/docker/pihole/etc-pihole:/etc/pihole
      - /volume1/docker/pihole/etc-dnsmasq:/etc/dnsmasq.d
    restart: unless-stopped

Point d’attention repéré en inspectant la configuration (docker inspect pihole --format '{{.HostConfig.PortBindings}}') : sans IP explicite sur les lignes des ports 80 et 443, Docker peut afficher un binding « invalid IP » au lieu de 0.0.0.0. Préciser 0.0.0.0:8080:80/tcp plutôt que simplement 8080:80/tcp règle ce souci.

Étape 5 : le conteneur démarre sans interface réseau

Dernier symptôme rencontré, distinct des précédents : après un redémarrage, Pi-hole tourne (statut « healthy »), mais impossible de joindre l’extérieur — ni ping, ni résolution DNS :

WARNING: Connection error (8.8.8.8#53): failed to send UDP request (Network unreachable)

Vérification à l’intérieur du conteneur :

sudo docker exec pihole ip addr

Seule l’interface loopback (127.0.0.1) apparaît — aucune interface eth0. Le conteneur n’était tout simplement pas rattaché au réseau bridge Docker (confirmé par docker network inspect bridge, qui ne le listait pas parmi les conteneurs attachés).

Solution : un simple restart ne suffit pas, il faut recréer complètement le conteneur pour forcer un nouvel attachement réseau :

sudo docker compose down
sudo docker compose up -d

Après cette manipulation, ip addr affiche bien une interface eth0 avec une adresse 172.17.0.x, et la connectivité est restaurée.

Étape 6 : le problème d’attachement réseau revient malgré Compose

Même après être passé à docker-compose.yml, le problème de l’étape 5 (conteneur « healthy » mais sans interface réseau) s’est reproduit à plusieurs reprises, plusieurs jours après la migration. Autre observation troublante : un jour, le conteneur n’a pas redémarré tout de suite après le reboot du NAS, mais seulement plus de 2 heures plus tard, sans action manuelle de notre part.

Comparaison des horodatages sur ce cas précis :

Boot du NAS      : 07:08:27
Docker actif     : 07:09:05
Conteneur pihole : 09:40:57  (2h31 après)

Vérification côté Docker :

sudo docker inspect pihole --format 'RestartCount: {{.RestartCount}} | FinishedAt: {{.State.FinishedAt}}'

Résultat : RestartCount: 0, aucune tentative de redémarrage automatique enregistrée. Le conteneur n’a donc pas été relancé par le mécanisme restart: unless-stopped de Docker — quelque chose d’autre l’a démarré, avec un délai important. Recherche infructueuse du côté des logs système (journalctl) et des événements Docker (docker events) : rien de concluant n’apparaît à l’heure exacte du démarrage.

L’hypothèse la plus probable, sans certitude confirmée, est que Container Manager (UGOS) gère lui-même le cycle de vie des conteneurs définis via Compose, avec un comportement de démarrage différé et parfois défaillant sur l’attachement réseau — indépendamment du mécanisme natif restart de Docker.

Contournement mis en place : plutôt que de continuer à chercher une cause introuvable côté UGOS, une tâche cron force un redémarrage propre et complet du conteneur peu après chaque boot du NAS :

sudo crontab -e

Ajouter :

@reboot sleep 300 && cd /volume1/docker/pihole && docker compose down && docker compose up -d

Le délai de 5 minutes (sleep 300) laisse le temps au réseau du NAS de se stabiliser avant de forcer un down/up complet, qui recrée le conteneur avec un nouvel attachement réseau — contrairement à un simple restart, insuffisant pour résoudre ce type d’anomalie.

Point important : dans ce cas précis, les logs internes de Pi-hole (FTL) ne montrent strictement rien d’anormal — le service démarre proprement, importe ses requêtes DNS historiques, ouvre ses ports. Le défaut se situe entièrement au niveau de la couche réseau Docker, invisible depuis l’intérieur du conteneur applicatif.

Ce qu’il faut retenir

  • Mode bridge plutôt que host sur un NAS qui fait déjà tourner des services DNS système.
  • Mapper le port 53 sur l’IP LAN explicite du NAS, pas sur 0.0.0.0, pour éviter les faux conflits avec l’interface graphique.
  • Vérifier dns.listeningMode : en bridge, il doit être sur ALL pour accepter les requêtes venant du LAN.
  • Préférer docker-compose.yml à une commande docker run ponctuelle pour la stabilité au fil des redémarrages.
  • Toujours spécifier l’IP explicitement (0.0.0.0:port:port) dans les mappings de ports du compose.
  • En cas de conteneur « healthy » mais injoignable, penser à vérifier l’attachement réseau lui-même (ip addr dans le conteneur) — un down/up complet répare ce type d’anomalie, contrairement à un simple restart.
  • Si le problème revient malgré Compose, une tâche cron @reboot forçant un down/up quelques minutes après le boot du NAS est un contournement fiable, même sans avoir identifié la cause exacte côté Container Manager.

Au final, Pi-hole tourne de façon stable sur le NAS, avec plus de 150 000 requêtes DNS traitées et plusieurs centaines de domaines bloqués quotidiennement.

Xiao Nico

Je suis l'erreur 404 du domaine de l'informatique, je recherchais une alarme suite à un cambriolage et je me suis retrouvé avec une alarme Xiaomi dans les mains. J'ai aimé, je me suis fait plein de copains et on s'éclate ! Mon but est de partager un max et surtout expliquer et aider les débutants comme je l'ai été. Donc toi qui ne comprends rien aujourdh'hui, ne t'inquiète pas j'étais comme toi ;) Me payer un café https://www.paypal.me/XiaoNico