家里的宽带固网用上公网IP,可以方便修改域名指向推送,接入微信网页开发。笔记本却提出新的问题:一旦出门在外,环境失效。

依然需要一个单独的开发测试域名,通过固定的公网服务器,内网穿透到开发环境,保证这个渠道可以随时工作。目前,这个方案最成熟的是开源 Ngrok。

大致流程如下:

  1. 用户发起网址请求
  2. 从 DNS 获得域名解析
  3. 网络请求被转向指定的服务器IP
  4. 服务器侦听 80/443 端口,将对应的访问转给 Ngnix
  5. Ngnix 将不同的域名按照配置,通过反向代理转发给运行着 Ngrock 的 Docker。
  6. Ngrok Server 通过和客户端的持久连接,将数据转发给客户端。
  7. Ngrok Client 客户端按照配置,将数据转发给本地服务器端口。
  8. 本地服务器正常响应,原路返回。

在尝试过的许多办法里,我都遇到无法连接的错误,最后是在 有时右逝ngrok内网穿透 找到可用方案。此方案转载编辑如下:

首先,是客户端出现 connecting - reconnect 的报错。
在服务器命令行里查看日志:

docker logs ngrok-server

发现以下类似错误:

1
2
3
4
New connection from 115.194.14.96:64688
[01:45:31 UTC 2019/04/06] [DEBG] (ngrok/log.(*PrefixLogger).Debug:79) [tun:6f958746] Waiting to read message
[01:45:31 UTC 2019/04/06] [WARN] (ngrok/log.(*PrefixLogger).Warn:87) [tun:6f958746] Failed to read message: read tcp 172.17.0.4:4443->115.194.14.96:64688: read: connection reset by peer
[01:45:31 UTC 2019/04/06] [DEBG] (ngrok/log.(*PrefixLogger).Debug:79) [tun:6f958746] Closing

其中的重点主要是:

Failed to read message: read tcp 172.17.0.4:4443->115.194.14.96:64688: read: connection reset by peer

ngrok内网穿透 一文提供了多步检查错误配置,包括域名指向、端口状态、防火墙(如果你是云服务器,还有云安全组等设置)。

在所有配置正常的状态下,解决方案就是重构镜像部署。步骤如下:

1 新镜像

在命令行里逐行输入:

1
2
3
4
5
git clone https://github.com/hteen/docker-ngrok.git
cd docker-ngrok
sed -i '1cFROM golang:1.8.3' Dockerfile
sed -i '4cRUN apt-get install git make openssl' Dockerfile
docker build -t hteen/ngrok .

2 运行镜像

在此例中,我开启了 80/443 方案,因为我需要的是基于域名的开发。可以看到,4443 是 Ngrok 服务端用于接收客户端请求的端口。80 和 443 是在容器内部的 http/https 端口,在容器外被映射为 8880/8443。

docker run -idt –name ngrok-server -p 7788:7788 -p 8880:80 -p 8443:443 -v /data/ngrok:/myfiles -e DOMAIN=’你的域名’ hteen/ngrok /bin/sh /server.sh

3 本地配置

在本地 config.yml 中写入配置:

1
2
3
4
5
6
7
server_addr: dev.dagong.in:7788
trust_host_root_certs: false
tunnels:
YOURDOMAIN.com:
proto:
http: 2233
https: 2233

最后运行命令行指令启动:

./ngrok -config=config.yml start YOURDOMAIN.com

4 日志清理

Ngrok 的心跳日志可能很大,可以定期清理:

crontab -e

每天晚上定时启动,保留最新 1M 大小:

1
> 0 1 * * *     sudo truncate -s 1M `docker inspect --format='{{.LogPath}}' YOUR_NGROK_CONTAINER_NAME`