我目前正在开发一个小型家庭项目,其中我通过 docker 在树莓派 4 上托管各种服务。在从事这个项目时,我现在遇到了一个 dns 问题,我无法真正解决这个问题。我在容器内托管 pihole 并将其配置为使用我的路由器作为上游 DNS 服务器。在我的路由器上,我已将树莓派配置为本地 dns 服务器,并添加了其他一些上游 dns 服务器。根据我的理解,这将导致所有 dns 请求通过我的树莓派上的 pihole 容器进行路由,然后返回到我的路由器以解决它。到目前为止,此设置适用于我本地网络上的所有设备,包括树莓派本身。
我现在遇到的唯一问题是同一个树莓派上的其他容器与 pihole 位于相同和/或不同的网络中。他们似乎都在解析 dns 查询时遇到问题。例如:我有一个 phpmyadmin countainer 连接到与 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 容器却不能?在不将主机名称服务器设置到路由器的情况下,如何解决此问题?
答案1
因此,进一步深入研究这个问题(我有我的一个 Pi 上也有同样的问题),我发现如果您在该服务器上运行本地 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 地址放入- 我相信除非你覆盖或在 中进行了自定义,否则它通常会放入你的路由器提供的 DNS 服务器的 IP - 这将是你的 Pi 的 IP 地址! (第 22 条规则...但是调试起来很棘手,因为除了 Docker 之外的许多东西都可以在该设置下正常工作!)。/etc/resolv.conf
name_servers
/etc/network/interfaces
答案2
Pi-hole
+wg-easy
内部泊坞窗
我试图在 RPi 4 上的 docker 下运行pi-hole
和wg-easy
(wireguard VPN)。问题是,将eth0
RPi 的 IP 地址设置为客户端中的 DNS 服务器wg-easy
不起作用 - Chrome 中的页面卡在“正在加载”。设置它1.1.1.1
使其工作,但我失去了对本地本地主机名的访问(显然)。类似OP描述的那样。
灵感来自
- @geerlingguy 这里
- https://stackoverflow.com/a/24326540/1310733
- 看着
pihole.log
包含query[HTTPS] google.com from 172.18.0.1
我尝试使用该docker0
IP地址作为DNS服务器IP。它成功了!
我所做的步骤:
- 获取接口上 RPi 的 IP 地址
docker0
(输出取自上面链接的 SO 答案)
$ sudo ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
inet 172.17.42.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::5484:7aff:fefe:9799/64 scope link
valid_lft forever preferred_lft forever
- 将 IP 地址设置
172.17.42.1
为名称服务器/etc/resolvconf.conf
# Configuration for resolvconf(8)
# See resolvconf.conf(5) for details
resolv_conf=/etc/resolv.conf
# If you run a local name server, you should uncomment the below line and
# configure your subscribers configuration files below.
# docker0 interface with running pi-hole
name_servers=172.17.42.1
- 更新
resolvconf
sudo resolvconf -u
- 检查 是否
name_servers=172.17.42.1
是 中的唯一条目/etc/resolv.conf
。如果没有,请编辑该文件(我不确定这一步,我正在摆弄它,现在它可以工作了,我不想碰它