# 前言
某些时候,我们会有在容器内容访问宿主机某个服务的需求,比如现在 openai 无法直接访问,需要给项目添加代理,我的 chatgpt-dingtalk (opens new window) 项目支持了通过环境变量指定代理地址。
添加方式如下:
# 运行项目
$ docker run -itd --name chatgpt -p 8090:8090 -e APIKEY=换成你的key -e MODEL="gpt-3.5-turbo" -e SESSION_TIMEOUT=600 -e HTTP_PROXY="" -e DEFAULT_MODE="单聊" --restart=always dockerproxy.com/eryajf/chatgpt-dingtalk:latest
复制
其中的 HTTP_PROXY 就是对应的代理服务。
# 方案
要解决这个问题,并且让如上命令能通用在 Linux,Mac,Windows 系统都通用,因此网上一些通过命令获取到宿主机 IP 的方案就不满足需求了,要实现这个需求,需要一点点骚操作才行。
# 方案一
使用 host 模式启动服务。
默认情况下,docker 使用的是桥接模式启动服务,即 Docker 容器将使用 Docker 自己创建的虚拟网络,Docker 容器之间可以相互通信,但是它们无法直接访问宿主机上的网络服务。Docker 容器需要通过端口映射来暴露自己的服务,以便宿主机或其他网络主机访问。
而使用 host 模式启动,Docker 容器与宿主机共享同一个网络命名空间,即 Docker 容器将直接使用宿主机的网络。这意味着 Docker 容器可以使用宿主机的 IP 地址和端口,可以直接访问宿主机上的网络服务。然而,host 模式也存在一些限制,例如 Docker 容器之间无法直接通信,Docker 容器的网络性能可能会受到影响。
所以此时启动命令可以改成下边这样:
# 运行项目
$ docker run -itd --name chatgpt --network host -e APIKEY=换成你的key -e MODEL="gpt-3.5-turbo" -e SESSION_TIMEOUT=600 -e HTTP_PROXY="http://127.0.0.1:1080" -e DEFAULT_MODE="单聊" --restart=always dockerproxy.com/eryajf/chatgpt-dingtalk:latest
复制
这样容器就能直接访问到宿主机的 1080 了。
但是因为这种模式的局限性,因此实际生产当中几乎没有人会用这种方式,所以不推荐使用方案一,推荐方案二。
# 方案二
docker 官方提供了一种支持方案,可通过指向 host.docker.internal
来指向宿主机的 IP。参见文档:从容器连接到主机上的服务 (opens new window)
但注意,这个方案存在一个问题,那就是只支持 Mac 与 Windows 中 desktop 这种环境,并不支持在 Linux 中使用,所以不能直接使用。
于是,有人在官方提交了这个 issue:Support host.docker.internal DNS name to host (opens new window)。
在其中的一个回答里,找到了一种可行方案:
按照如上说明,可以使用如下命令进行启动:
# 运行项目
$ docker run -itd --name chatgpt -p 8090:8090 --add-host="host.docker.internal:host-gateway" -e APIKEY=换成你的key -e MODEL="gpt-3.5-turbo" -e SESSION_TIMEOUT=600 -e HTTP_PROXY="http://host.docker.internal:15732" -e DEFAULT_MODE="单聊" --restart=always dockerproxy.com/eryajf/chatgpt-dingtalk:latest
复制
于是我在自己的 Mac 以及 Linux 都使用这种方案做了测试,发现是可以的。
需要注意的是,这个功能在 docker 版本过低的时候,可能支持的有问题,所以你的 docker 版本最好不低于 20。
如果使用的是docker-compose,则通过添加如下内容进行配置:
extra_hosts:
- 'host.docker.internal:host-gateway'
复制
比如上边的项目改成docker-compose部署,就变成下边这样:
version: '3.9'
services:
chatgpt:
image: dockerproxy.com/eryajf/chatgpt-dingtalk:latest
container_name: chatgpt
environment:
- APIKEY=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
- MODEL="gpt-3.5-turbo-0301"
- SESSION_TIMEOUT=600
- HTTP_PROXY=http://host.docker.internal:15777
- DEFAULT_MODE="单聊"
ports:
- "8090:8090"
restart: always
extra_hosts:
- host.docker.internal:host-gateway