愉快的本地开发体验之本地DNS

写在前面

大家在本地环境进行联调或者运行一些服务的时候,是不是经常通过 ip:port 进行测试。有时候服务一多,经常性的需要记住很多 ip:port 信息。

本文将介绍如何通过自定义域名的方式去替换 ip:port,减去我们的记忆负担,提升我们的开发体验。

方案一:修改本地 Hosts 文件 + Nginx Proxy

这里推荐一款工具,SwitchHosts记忆中,之前的版本叫做 SwitchHosts!),页面简洁,操作一目了然。

配置 Hosts 文件,只需要将域名的地址跟 IP 做映射即可。
SwitchHosts

测试

1
2
3
4
5
6
7
8
9
➜  ~ 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 目录下。

1
2
3
4
5
6
7
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 这个镜像,下面是编排文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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

dnsmasq管理界面

测试(记得把方案一的 Hosts 记录重置一下😉)

1
2
➜  ~ ping a.dev.io
ping: cannot resolve a.dev.io: Unknown host

哦豁,失败了,需要修改本机 DNS 配置,如图所示:
DNS配置

再次测试

1
2
3
4
5
6
7
8
9
➜  ~ 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 呢?

1
2
3
4
5
6
7
8
9
➜  ~ 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

没错,天然支持泛域名解析,还记得我们上面的配置么?

1
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

1
127.0.0.1 *.dev.io

创建编排文件

1
2
3
4
5
6
7
8
9
10
11
12
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 配置。

测试一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
➜  ~ 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 芯片想要体验该镜像的话,可以参考我的方案进行本地编译。

  1. 首先 clone 仓库地址,git clone https://github.com/soulteary/go-dnsmasq.git
  2. 修改 Dockfile 内容,将 npx 注释一下,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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"]
  1. 打包本地镜像 docker build . -t soulteary/go-dnsmasq:test

另外,群主已经答应后面会更新 arm 架构的镜像啦,小伙伴们后面应该可以直接从官方的镜像仓库 soulteary/go-dnsmasq 拉取。


下一篇,我们来聊聊如果通过 Traefik 代理本地容器服务来提升本地的开发体验。

参考

  • https://little-star.love/posts/f114e298/
  • https://soulteary.com/2021/08/19/dns-for-local-development.html
-------------本文结束  感谢您的阅读-------------
xkcoding wechat
欢迎来我的公众号「xkcoding小凯扣丁」逛逛
o(╯□╰)o 赞助一杯咖啡 ~~