Docker容器内无法连接主机本地MongoDB的问题求助
问题背景
- 环境:Ubuntu 22.04,Docker容器内的Python脚本需连接主机
localhost上的MongoDB实例 - 主机配置:NGINX将27020端口流量转发至MongoDB默认的27017端口
- 异常现象:
- 本地运行脚本(用
localhost)可正常连接MongoDB - Docker Compose指定27020端口能正常连接
- 容器内用
host.docker.internal:27020时,nc命令能连通端口、请求NGINX能获取正常响应,但无法连接MongoDB - 仅
host网络模式可行,需非host模式的解决方案
- 本地运行脚本(用
相关文件
Dockerfile
FROM ubuntu RUN apt-get update RUN apt-get install curl pip micro netcat -y COPY requirements.txt app/requirements.txt WORKDIR /app RUN pip install --upgrade pip RUN pip install -r requirements.txt COPY . /app
requirements.txt
fastapi==0.85.1 uvicorn==0.19.0 motor==3.1.0dev black==22.10.0 python-dotenv==0.21.0 orjson==3.8.0 requests==2.28.1
mongodb.py
import asyncio import requests from motor.motor_asyncio import ( AsyncIOMotorClient, AsyncIOMotorCollection, ) from bson.codec_options import DEFAULT_CODEC_OPTIONS def get_collection( ) -> AsyncIOMotorCollection: # 设置时区感知的日期返回选项 options = DEFAULT_CODEC_OPTIONS.with_options(tz_aware=True) motor_client = AsyncIOMotorClient( "mongodb://usr:pwd@host.docker.internal:27020/?authSource=admin&replicaSet=Replica1" ) database = motor_client["DBNAME"] # 应用时区感知选项 return database.get_collection(collName, codec_options=options) async def main(): coll = get_collection() response=requests.get('http://host.docker.internal') print(response.text) async for doc in coll.find({}).limit(10): print(doc) if __name__ == "__main__": try: asyncio.run( main() ) except KeyboardInterrupt: pass
容器构建与运行命令
docker build -t test_motor .
docker run -it --add-host host.docker.internal:host-gateway test_motor bash
解决方案
1. 修复NGINX的TCP转发配置
MongoDB基于TCP协议通信,不能用HTTP的proxy_pass配置转发。需改用NGINX的stream模块:
stream { server { listen 27020; proxy_pass localhost:27017; proxy_timeout 30s; proxy_connect_timeout 5s; } }
- 验证NGINX是否启用stream模块:执行
nginx -V,查看输出是否包含--with-stream - 重启NGINX生效:
sudo systemctl restart nginx
2. 修改MongoDB监听地址
主机MongoDB默认仅监听localhost,容器通过host.docker.internal访问时会被拒绝。修改/etc/mongod.conf:
net: bindIp: 127.0.0.1,172.17.0.1 # 172.17.0.1是Docker默认网桥的网关IP
测试环境可临时设置为0.0.0.0(生产环境不推荐),然后重启MongoDB:
sudo systemctl restart mongod
3. 调整MongoDB副本集配置
连接字符串指定了replicaSet=Replica1,若副本集节点配置的是localhost,容器内会解析为自身的localhost导致连接失败。需将副本集节点地址改为主机局域网IP:
- 进入MongoDB Shell:
mongosh - 切换到admin库并认证:
use admin db.auth("usr", "pwd") - 修改副本集配置:
var cfg = rs.conf(); cfg.members[0].host = "192.168.x.x:27017"; // 替换为主机实际局域网IP rs.reconfig(cfg);
4. 直接映射MongoDB端口替代NGINX转发
跳过NGINX,直接将主机27017端口映射给容器,脚本连接地址改为host.docker.internal:27017:
docker run -it --add-host host.docker.internal:host-gateway -p 27017:27017 test_motor bash
内容的提问来源于stack exchange,提问作者EanX
相关产品推荐
相关产品推荐

