允许外部通过容器名解析至 Docker
Docker
之前做好了 给 Docker 配置完整的 IPv6 macvlan 网络环境,局域网内可以直接通过路由器访问到容器网段,下一步便是让容器外也能直接 DNS 解析容器名,当然仅对加入到特定网络的容器生效。
相同的想法早有人实现了,这里照搬验证
首先创建网络,注意这里创建的网络名可以当做后缀来访问,比如这个网络可以解析 coredns.docker 这个域名到名为 coredns 的容器。
docker network create -d macvlan --ipv6 \
-o parent=ens19 \
--subnet=192.168.2.0/24 --gateway=192.168.2.1 \
--ip-range=192.168.2.128/25 docker然后创建 CoreDNS 配置文件,这里的 /etc/resolv.conf 其实就是 127.0.0.11 是 Docker Engine 的内置 DNS 服务器地址。在容器中查看该文件能发现这一点 從 KIND 環境中學到的 DNS 小趣聞 | hwchiu learning note。
. {
# enables error logging
errors
# fast failling
cancel
# loop detection on startup
# since container can have dot inside their name (pattern '[a-zA-Z0-9][a-zA-Z0-9_.-]'),
# it's impossible to make a allowlist / blocklist to only resolve to docker internal names.
# thus please make sure upstream have some way to break the infinite loop.
loop
# dump all queries on standard output
log
# blocks ANY queries
any
# bind to docker.kokomi.site subdomain
rewrite stop {
name suffix .docker.kokomi.site. .docker. answer auto
}
# only allow local network access
acl {
allow net 192.168.0.0/16
block
}
# forward to docker internal DNS server
forward . /etc/resolv.conf
}这里额外绑定到 .docker.kokomi.site 下面了,本来想用 view 来限制只去支持子域名查询的,来避免查询一个 a.docker 传递到上游的 DNSmasq,再由 server=/docker/192.168.2.53/ 设置传递回来形成死循环。可想想这样并没法限制,因为如果 a 是个不存在的容器,docker internal DNS 自身就会转发到上游,所以想要杜绝死循环需要在上游做动作。
好在我这里其实有两层转发,Docker <> OpenWrt <> Router,所有主机的 DNS 都是 Router,DNSmasq 转发规则也设置在 Router 上。那么可以在 OpenWrt 层不响应相对应的查询,打破了死循环。
server=/docker.kokomi.site/192.168.2.53
server=/docker/192.168.2.53config dnsmasq
option localise_queries '1'
option rebind_protection '0'
option local '/pve.kokomi.site/docker.kokomi.site/docker/'
option domain 'pve.kokomi.site'
option extraconftext 'enable-ra\ndhcp-range=::,constructor:br-lan,ra-names'然后编辑 compose 文件,这里选个 53 尾号的 IP 好记。因为都是 macvlan 可以直接访问,也就没有必要设置 ports 端口转发了。
services:
coredns:
container_name: coredns
image: coredns/coredns:latest
networks:
docker:
ipv4_address: 192.168.2.53
volumes:
- ./Corefile:/etc/coredns/Corefile:ro
command: -conf /etc/coredns/Corefile
networks:
docker:
external: true清理 Docker Dead Container
没有正常关机、直接执行 reboot 命令,会在 Docker Host 上留下 Dead 状态的容器
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d26e77d28cc3 nginx "/docker-entrypoint.…" 7 days ago Dead
cf4e5bb6fd43 nginx "/docker-entrypoint.…" 7 days ago Dead而且 docker rm 还无能为力,这时候只要去 /var/lib/docker/containers/,把目录里容器 ID 对应的目录删掉,然后 service docker restart 等方式重启 Host 就清除了。