这几天在写QQ机器人和微信机器人的合并信息转发适配器时,因为要某些原因创建两个docker容器,由于之前创建容器的时候使用了netword host来使用宿主环境,但在第二个机器人不能再使用这种方式创建,因为会有端口占用。

映射不等于绑定

因为创建时要使用到两个端口映射,第一个是调用cqhttp api的端口,第二个是收到QQ消息时上报消息的端口,而处理上报消息的是宿主机中的程序。这里值得注意的是,因为调用返回结果是返回到浏览器,而上报消息要返回到宿主机中的程序处理。在docker中,我创建了contrainer并进行了端口映射之后,我使用机器人上报事件端口进行处理信息时,发现宿主程序无法接受到信息。而使用http调用机器人的发送消息api时,却发现我的QQ可以接受到信息,所以排除了调用,所以问题应该出在了上报事件处理的端口上。

机器人宿主处理

我回看了一下我的docker运行命令

docker run -ti --rm --name cqhttp-test \
-p 9009:9000 -p 5701:5701 -p 9999:9999\
-v $(pwd)/coolq:/home/user/coolq \
-e COOLQ_ACCOUNT=****-e \
CQHTTP_POST_URL=http://127.0.0.1:9999 \
-e CQHTTP_SERVE_DATA_FILES=yes richardchien/cqhttp

可以看到,我直接绑定了3个端口。第一个是访问coolq管理页面的访问端口,第二个和第三个就是我刚刚说的调用接口端口和上报事件端口。我在post_url中设置了http://127.0.0.1:9999就代表了处理程序在这个端口接受信息,对比来对比去。当这行指令创建出一个docker时,我在宿主机的程序也能识别到9999的端口,但是为什么就处理程序就收不到任何信息。

在排除了很久之后,后知后觉发现因为netword host是不隔离宿主机与容器端口,相当于在宿主机上运行程序,所以第一个机器可以畅通无阻,但是由于我第二个机器使用了端口映射,并且隔离了宿主机,虽然我设置了9999的端口映射,但这是从宿主机映射到容器中,并不包括容器映射到宿主机中,这之间是隔离开的,所以当我将post_url设置成127.0.0.1的ip是错误的,这会导致宿主机能发送信息给容器,而容器无法发送信息给宿主机,因为这个ip仅代表容器内部的localhost。

最后得出的解决办法,将post_url的ip用服务器的公网ip代替。改成CQHTTP_POST_URL=http://服务器ip:9999