Raspberry-Pi

Docker 容器 DNS 無法與 pihole 一起使用

  • May 21, 2021

我目前正在做一個小型家庭項目,我通過 docker 在樹莓派 4 上託管各種服務。在從事這個項目時,我現在遇到了一個我無法真正理解的 dns 問題。我在容器內託管 pihole 並將其配置為使用我的路由器作為上游 dns 伺服器。在我的路由器上,我已將樹莓派配置為本地 dns 伺服器,並添加了其他一些上游 dns 伺服器。據我了解,這將導致所有 dns 請求通過我的樹莓派上的 pihole 容器路由,然後返回到我的路由器以解決問題。到目前為止,此設置適用於我本地網路上的所有設備,包括樹莓派本身。

我現在遇到的唯一問題是同一個樹莓派上的其他容器在與 pihole 相同和/或不同的網路中。他們似乎都有解決 dns 查詢的問題。例如:我有一個 phpmyadmin 計數器連接到與 pihole 容器相同的 docker 網路。如果我現在 ssh 進入 phpmyadmin 容器並想要執行“ping google.com”或“apt-get update”,由於 dns 失敗,它將無法執行這些命令。

我已經檢查過的內容:

  • 我查看了 phpmyadmin 容器的 /etc/resolv.conf =>它包括 127.0.0.11 - 我的知識是正確的
  • 我查看了主機的 /etc/resolv.conf =>它包括我的樹莓派的實際 ip(不是 127.0.0.1)。我不明白為什麼它在這裡使用實際 ip 而不是 localhost 但它確實可以工作
  • 我重新啟動了 docker 守護程序
  • 我重新創建了 docker-compose.yml 中包含的網路
  • 我重新創建了 phpmyadmin 容器

到目前為止,上述步驟都沒有解決問題。

出於好奇,我在主機上的 /etc/dhcpcd.conf 中將路由器的 ip 設置為靜態名稱伺服器,並重新載入了 dhcpcd 和 docker 守護程序。如果我現在 ssh 進入我的 phpmyadmin 容器 dns 突然起作用了。我再次排除了我的路由器 ip 以驗證我的問題,並且 dns 立即停止工作。這使我得出結論,我的所有 docker 容器(不包括 pihole - 因為我為此容器指定了 dns 127.0.0.1)似乎在將我的主機 IP 地址用於 dns 時存在問題。

我目前的 docker-compose.yml:

version: '3'

services:
 portainer:
   image: portainer/portainer-ce:linux-arm
   container_name: portainer
   restart: unless-stopped
   environment:
     TZ: Europe/Berlin
   networks:
     - frontend
   volumes:
     - /etc/localtime:/etc/localtime:ro
     - /var/run/docker.sock:/var/run/docker.sock
     - portainer_data:/data
   labels:
     - traefik.enable=true
     - traefik.docker.network=compose_frontend
     - traefik.http.routers.portainer.entrypoints=web_tcp
     - traefik.http.routers.portainer.rule=Host(`portainer.mydomain`)
     - traefik.http.services.portainer.loadbalancer.server.port=9000


 traefik:
   image: traefik:latest
   container_name: traefik
   restart: unless-stopped
   environment:
     TZ: Europe/Berlin
   networks:
     - frontend
   ports:
     - 80:80
   volumes:
     - /etc/localtime:/etc/localtime:ro
     - /var/run/docker.sock:/var/run/docker.sock:ro
     - /home/farmadmin/config/traefik:/etc/traefik
   labels:
     - traefik.enable=true
     - traefik.docker.network=compose_frontend
     - traefik.http.routers.traefik.entrypoints=web_tcp
     - traefik.http.routers.traefik.rule=Host(`traefik.mydomain`)
     - traefik.http.services.traefik.loadbalancer.server.port=8080

 pihole:
   image: pihole/pihole:latest
   container_name: pihole
   restart: unless-stopped
   environment:
     TZ: Europe/Berlin
   networks:
     - frontend
   dns:
     - 127.0.0.1
   ports:
     - 53:53/tcp
     - 53:53/udp
   volumes:
     - /etc/localtime:/etc/localtime:ro
     - etc-pihole:/etc/pihole/
     - etc-dnsmasq.d:/etc/dnsmasq.d/
   labels:
     - traefik.enable=true
     - traefik.docker.network=compose_frontend
     - traefik.http.routers.pihole.entrypoints=web_tcp
     - traefik.http.routers.pihole.rule=Host(`pihole.mydomain`)
     - traefik.http.routers.pihole.middlewares=dashboard_prefix
     - traefik.http.middlewares.dashboard_prefix.addprefix.prefix=/admin
     - traefik.http.services.pihole.loadbalancer.server.port=80

 mariadb:
   image: linuxserver/mariadb:latest
   container_name: mariadb
   restart: unless-stopped
   environment:
     - TZ=Europe/Berlin
     - PUID=1000
     - PGID=1000
   networks:
     - backend
   volumes:
     - mariadb_data:/config

 phpmyadmin:
   image: phpmyadmin:latest
   container_name: phpmyadmin
   restart: unless-stopped
   environment:
     - TZ=Europe/Berlin
     - PMA_HOST=mariadb
     - PMA_PORT=3306
   networks:
     - frontend
     - backend
   labels:
     - traefik.enable=true
     - traefik.docker.network=compose_frontend
     - traefik.http.routers.phpmyadmin.entrypoints=web_tcp
     - traefik.http.routers.phpmyadmin.rule=Host(`phpmyadmin.mydomain`)
     - traefik.http.services.phpmyadmin.loadbalancer.server.port=80

networks:
 frontend:
 backend:
   internal: true

volumes:
 # Persistent Portainer Data
 portainer_data:
 
 # Persistent Pihole Data
 etc-pihole:
 etc-dnsmasq.d:

 # Persistent MariaDB Data
 mariadb_data:

所以我的問題是:為什麼主機 resolv.conf 包含它自己的完整 ip 而不是 localhost?為什麼我的主機能夠使用自己的 ip 解析 dns 查詢,但我的 docker 容器卻不能?如果不將主機名稱伺服器設置為我的路由器,如何解決此問題?

因此,進一步深入研究這個問題(我在其中一個 Pis 上遇到了同樣的問題),我發現如果你在該伺服器上執行本地 DNS 解析器,並且你希望 Docker 的 DNS 能夠正常工作,你需要確保 Pi 的/etc/resolv.conf文件具有名稱伺服器127.0.0.1(如您所述)。

為了使更改生效,您應該編輯/etc/resolvconf.conf文件並取消註釋該行:

# If you run a local name server, you should uncomment the below line and
# configure your subscribers configuration files below.
name_servers=127.0.0.1

之後,您可以立即重新啟動或重新生成文件sudo resolvconf -u

至於為什麼在預設情況下resolvconf將 Pi 的 IP 地址放入其中/etc/resolv.conf- 我相信除非您覆蓋name_servers或在 中自定義內容/etc/network/interfaces,否則它通常會放入您的路由器提供的 DNS 伺服器的 IP 中 - 這將是你的 Pi 的 IP 地址!(Catch 22 ……但調試起來很棘手,因為除了 Docker 之外的許多東西都可以在該設置下正常工作!)。

引用自:https://unix.stackexchange.com/questions/647996