写在前面
大家在本地环境进行联调或者运行一些服务的时候,是不是经常通过 ip:port 进行测试。有时候服务一多,经常性的需要记住很多 ip:port 信息。
本文将介绍如何通过自定义域名的方式去替换 ip:port,减去我们的记忆负担,提升我们的开发体验。
方案一:修改本地 Hosts 文件 + Nginx Proxy
这里推荐一款工具,SwitchHosts(记忆中,之前的版本叫做 SwitchHosts!),页面简洁,操作一目了然。
配置 Hosts 文件,只需要将域名的地址跟 IP 做映射即可。

测试
➜ ~ ping a.dev.io
PING a.dev.io (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.098 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.086 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.093 ms
^C
--- a.dev.io ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.086/0.101/0.118/0.012 ms
修改 Hosts 文件这种方式,如果我们在本机又部署了一个 b 服务,此时需要加一个 b.dev.io,则需要额外新增一条记录,并不能做到泛域名解析(*.dev.io)。如果要在本地支持泛域名解析,那么就只能通过方案二来实现了。
方案二:dnsmasq
原生的 dnsmasq 是不具备界面的,这里推荐一款带有 web 界面的 dnsmasq,同时还支持「Hot Reload」机制。
我们通过 docker 快速启动一个 dnsmasq 服务,首先新建一个配置文件 dnsmasq.conf,并将配置文件存放在 config 目录下。
log-queries
no-resolv
server=8.8.8.8
server=114.114.114.114
strict-order
address=/dev.io/127.0.0.1
这里我们使用 jpillora/dnsmasq:latest 这个镜像,下面是编排文件:
version: "3.8"
services:
dns-server:
image: jpillora/dnsmasq:latest
ports:
- "53:53/udp"
- 8080:8080
environment:
- HTTP_USER=root
- HTTP_PASS=root
volumes:
- ./config/dnsmasq.conf:/etc/dnsmasq.conf
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "1m"
运行 docker-compose up 启动服务,访问管理界面 http://localhost:8080

测试(记得把方案一的 Hosts 记录重置一下😉)
➜ ~ ping a.dev.io
ping: cannot resolve a.dev.io: Unknown host
哦豁,失败了,需要修改本机 DNS 配置,如图所示:

再次测试
➜ ~ ping a.dev.io
PING a.dev.io (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.043 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.133 ms
^C
--- a.dev.io ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.043/0.099/0.144/0.045 ms
此时,如果测试一下 b.dev.io 呢?
➜ ~ ping b.dev.io
PING b.dev.io (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.052 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.143 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.142 ms
^C
--- b.dev.io ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.052/0.112/0.143/0.043 ms
没错,天然支持泛域名解析,还记得我们上面的配置么?
address=/dev.io/127.0.0.1
这里配置就意味着 *.dev.io 都会指向到 127.0.0.1。
方案三:go-dnsmasq(2021.09.16 更新)
运行了一段时间方案二之后,发现我的 MBP 越来越卡,通过 docker stats 发现可能存在内存泄漏的问题。经过折腾群群主(苏洋)的建议,更换了另外一个 dns 镜像,可解决内存泄漏的问题,同时苏大还对该镜像进行了精简(镜像大小约2.7M)。
新增配置文件 config/hosts.conf
127.0.0.1 *.dev.io
创建编排文件
version: "3.8"
services:
dns-server:
image: soulteary/go-dnsmasq:test
command: dnsmasq -l 0.0.0.0:53 -f /hosts.conf -p 1s -n 114.114.114.114:53 -n 8.8.8.8:53
ports:
- "53:53/udp"
- "53:53/tcp"
volumes:
- ./config/hosts.conf:/hosts.conf:rw
restart: unless-stopped
运行 docker-compose up 启动服务,同时别忘了参考方案二,需要修改本机 DNS 配置。
测试一下:
➜ ~ ping a.dev.io
PING a.dev.io (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.049 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.084 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.162 ms
^C
--- a.dev.io ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.049/0.098/0.162/0.047 ms
➜ ~ ping b.dev.io
PING b.dev.io (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.061 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.186 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.125 ms
^C
--- b.dev.io ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.061/0.124/0.186/0.051 ms
泛域名解析已经可以支持了。最重要的是,这个方案至少不会让我的电脑越用越卡。😁
如果想要知道 DNS 的解析日志,可以通过 docker-compose logs -f 查看,如果你不想通过命令行的方式查看,也可以通过配置 Dozzle 来查看容器的日志,具体使用方式可以参考苏大的博文:https://soulteary.com/2020/11/15/view-container-logs-in-realtime.html
小插曲
苏大当时未编译 arm 架构的镜像,因此我这边 clone 了源码,在本地的 m1 芯片的电脑上重新编译了一个本地镜像,所以小伙伴们可以看到上述编排文件的镜像 TAG 为 soulteary/go-dnsmasq:test。
如果也有小伙伴是 m1 芯片想要体验该镜像的话,可以参考我的方案进行本地编译。
- 首先 clone 仓库地址,
git clone https://github.com/soulteary/go-dnsmasq.git - 修改 Dockfile 内容,将 npx 注释一下,代码如下:
FROM golang:1.16-alpine AS Builder
WORKDIR /app
COPY . .
RUN go env -w GO111MODULE=on && \
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct && \
go mod download
ARG VERSION=1.1.0
# RUN apk add upx
RUN go build -o dnsmasq -ldflags "-w -s -X main.Version=${VERSION}" -tags="netgo" -trimpath cmd/dnsmasq/main.go
# RUN upx -9 -o dnsmasq.min dnsmasq
FROM scratch
# COPY --from=Builder /app/dnsmasq.min /bin/dnsmasq
COPY --from=Builder /app/dnsmasq /bin/dnsmasq
ENV DNSMASQ_LISTEN=0.0.0.0:53
EXPOSE 53 53/udp
CMD ["/bin/dnsmasq"]
- 打包本地镜像
docker build . -t soulteary/go-dnsmasq:test
另外,群主已经答应后面会更新 arm 架构的镜像啦,小伙伴们后面应该可以直接从官方的镜像仓库 soulteary/go-dnsmasq 拉取。
下一篇,我们来聊聊如果通过 Traefik 代理本地容器服务来提升本地的开发体验。