CentOS7使用docker 启动容器后 , 宿主机连接访问不到容器的端口

本文详细介绍了CentOS7下Docker容器网络配置的问题,包括docker0网桥、容器IP、路由检查等。当宿主机无法访问容器端口时,通过检查网络配置、修改docker0默认网段以及使用--net=host模式解决问题。同时提供了两种解决方案,一种是手动调整网络设置,另一种是利用--net=host启动容器,使其直接使用宿主机IP。

CentOS7使用docker 启动容器后 , 宿主机连接访问不到容器的端口

注意第一种方法是在网上找的 , 我并没有执行成功 , 但是他分析的很不错,
可以参考第二种方法

首先需要明确docker的网桥模式,网桥工作在二层(OSI堆栈),是通用网络设备的一种,可以设置IP地址。有了IP地址,Linux便可通过路由表或IP表,在网络层定位网桥,这就相当于有了一个虚拟网卡,即docker0。docker0默认的地址划分:IP(172.17.0.1/16),在启动容器时,docker会在宿主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备,容器启动时,Docker引擎将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在宿主机中,以veth***这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show命令查看,从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。

方法一:

1. 首先检查宿主机的网络配置

需要先安装网桥管理工具包

yum install bridge-utils -y

1)检查网桥brctl show

[root@localhost ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
docker0         8000.000000000000       no
2) 检查ip 
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:85:de:4a brd ff:ff:ff:ff:ff:ff
    inet 192.168.137.130/24 brd 192.168.137.255 scope global dynamic eno16777736
       valid_lft 1627sec preferred_lft 1627sec
    inet6 fe80::20c:29ff:fe85:de4a/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
    link/ether 02:42:32:06:66:2d brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:32ff:fe06:662d/64 scope link
       valid_lft forever preferred_lft forever

可以看到docker创建的虚拟网卡docker0的网段为172.17.0.1/16

3)查看路由: ip route

[root@localhost ~]# ip route
default via 192.168.137.2 dev eno16777736  proto static  metric 100
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1
192.168.137.0/24 dev eno16777736  proto kernel  scope link  src 192.168.137.130  metric 100

即172.17.0.0/16网段的包均通过docker0网桥来转发.

  1. 再来查看容器的ip: docker exec -it <容器名称> ip a
[root@localhost ~]# docker exec -it mn  ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN   
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00  
    inet 127.0.0.1/8 scope host lo  
       valid_lft forever preferred_lft forever  
129: eth0@if130: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP   
    link/ether 02:42:ac:11:0a:02 brd ff:ff:ff:ff:ff:ff  
    inet 172.17.0.0/16 brd 172.17.10.255 scope global eth0  
       valid_lft forever preferred_lft forever  

可以看到虚拟网卡eth0的ip为172.17.0.0

  1. 查看容器内的路由: docker exec -it c_name ip route
[root@localhost ~]# docker exec -it mn ip route
default via 172.17.10.1 dev eth0   
172.17.0.0/16 dev eth0 scope link  src 172.17.0.1

由此可知172.17.0.0网段的包均走容器内的eth0,默认网关为172.17.10.1

  1. 如果容器中无法ping通外网,首先查看能否ping通网关。如果网关都无法ping通,说明网桥或网段有问题。这里就可以用tcpdump来查看。比如监控上面第一步的网桥接口tcpdump -i vethaef304e -nn,正常的网络包应答如下:bash-4.4# ping -c 1 8.8.8.8
[root@localhost ~]#  tcpdump -i vethaef304e -nn 
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode  
listening on vethaef304e, link-type EN10MB (Ethernet), capture size 262144 bytes  
17:17:16.282976 IP 172.17.10.2 > 8.8.8.8: ICMP echo request, id 2304, seq 0, length 64  
17:17:16.325812 IP 8.8.8.8 > 172.17.10.2: ICMP echo reply, id 2304, seq 0, length 64  
17:17:21.297595 ARP, Request who-has 172.17.10.1 tell 172.17.10.2, length 28  
17:17:21.297656 ARP, Reply 172.17.10.1 is-at f2:29:f4:5b:3d:f2, length 28  

异常时就只有request who-has包,没有reply

  1. 问题解决

查看网桥,路由和ip均没发现问题,试试修改docker0的默认网段,居然成功了,步骤如下:

1) 删除原有配置

service docker stop  
ip link set dev docker0 down  
brctl delbr docker0  
iptables -t nat -F POSTROUTING  
  1. 创建新的网桥
brctl addbr docker0  
ip addr add 172.17.10.1/24 dev docker0  
ip link set dev docker0 up  
  1. 修改docker配置,在/etc/docker/daemon.json中追加bip如下,注意json的格式,bip前面需要有,root@XXXXXX~# cat /etc/docker/daemon.json
vim /etc/docker/daemon.json
{
  "insecure-registries":["x.x.x"],
  "bip": "172.17.10.1/24"
}  

4)重启docker: systemctl restart docker

[root@localhost ~]# systemctl  restart  docker

方法二:

docker容器自动分配的ip为172.17.0.0/24网段的ip,开发用的物理机和这个容器不在一个网段,根本没法访问到,这时候网上查到docker有一种网络模式是–net=host,就是让容器直接使用宿主服务器的ip,这样开发用的物理机就能够访问这个容器的接口了

在执行启动命令的时候 , 加一个属性 --net=host

docker run --name mn -p 80:80 -d --net=host nginx

当你在 **虚拟机中的 Docker 容器** 里运行了 MongoDB,但在 **宿主机(Host Machine)上连接不上**,这是一个非常常见的网络问题。下面我会详细分析可能的原因,并提供解决方案。 --- ## 🧩 场景还原 - 你有一台 **虚拟机(VM)**,比如使用 VMware、VirtualBox 或云服务器(如本地 VM 跑 Ubuntu)。 - 在这个虚拟机中,你用 Docker 启动了一个 MongoDB 容器: ```bash docker run -d --name mongodb -p 27017:27017 mongo:6 ``` - 你想从你的 **物理机(宿主机 / 本机电脑)** 使用 MongoDB 客户端(如 `mongosh`、Robo 3T、MongoDB Compass)连接到该 MongoDB。 - 但连接失败:`Connection refused` 或超时。 --- ## ✅ 正确的连接方式 你应该过以下地址尝试连接: ``` mongodb://<虚拟机IP>:27017 ``` 例如: ```bash mongosh "mongodb://192.168.1.100:27017" ``` > ❌ 错误做法:使用 `localhost` 或 `127.0.0.1` 连接 —— 那是指你本机,不是虚拟机! --- ## 🔍 常见原因及解决方案 ### ✅ 1. 没有正确获取虚拟机的 IP 地址 #### 解决方法:查看虚拟机的真实局域网 IP 在虚拟机中执行: ```bash ip addr show # 或更简单 hostname -I # 或 ip route get 1 | awk '{print $7}' ``` 输出类似: ``` 192.168.1.100 ``` 然后你在宿主机使用这个 IP 来连接: ```bash mongosh "mongodb://192.168.1.100:27017" ``` > ⚠️ 注意:不要用 `127.0.0.1` 或 `localhost`,那是虚拟机自己的回环地址。 --- ### ✅ 2. 虚拟机防火墙或安全组阻止了端口 27017 即使 Docker 映射了 `-p 27017:27017`,如果虚拟机操作系统防火墙没放行,外部仍无法访问。 #### 解决方法: ##### 对于 Ubuntu/Debian(使用 ufw): ```bash sudo ufw allow 27017 ``` ##### 对于 CentOS/RHEL(使用 firewalld): ```bash sudo firewall-cmd --permanent --add-port=27017/tcp sudo firewall-cmd --reload ``` ##### 如果是云服务器(阿里云、AWS、腾讯云等): 确保 **安全组规则** 允许入方向(Inbound)的 `27017` 端口开放(建议限制来源 IP)。 --- ### ✅ 3. Docker 容器未正确映射端口 检查是否真的做了端口映射: ```bash docker ps ``` 输出应包含: ``` CONTAINER ID IMAGE COMMAND PORTS NAMES ... mongo "docker-entrypoint.s…" 0.0.0.0:27017->27017/tcp mongodb ``` ✅ 必须看到 `0.0.0.0:27017->27017/tcp`,表示监听所有接口。 ❌ 如果只显示 `127.0.0.1:27017->27017/tcp`,则只能从虚拟机内部访问。 #### 修复命令(重新启动容器并正确映射): ```bash docker stop mongodb docker rm mongodb docker run -d --name mongodb \ -p 27017:27017 \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=password \ mongo:6 ``` > `-p 27017:27017` 默认绑定到 `0.0.0.0`,所以可以被外部访问。 --- ### ✅ 4. MongoDB 绑定到了 localhost(默认行为) 新版本 MongoDB 默认会绑定到 `127.0.0.1`,即仅允许本地连接。如果你没有显式配置,它不会接受来自外部的连接。 #### 解决方法:启动容器时指定绑定所有接口 修改启动命令,添加 `--bind_ip_all` 参数: ```bash docker run -d --name mongodb \ -p 27017:27017 \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=password \ mongo:6 --bind_ip_all ``` > 💡 `--bind_ip_all` 表示监听所有网络接口(等价于 `--bind_ip 0.0.0.0`) ⚠️ 不要使用 `--bind_ip 192.168.1.100`,因为这是宿主 IP,在容器内无效。 --- ### ✅ 5. 虚拟机网络模式问题(NAT vs Bridged) #### 常见情况: - **NAT 模式**:虚拟机和宿主机不在同一网段,需要做端口转发。 - **桥接(Bridged)模式**:虚拟机获得局域网独立 IP,可以直接访问。 #### 推荐方案: 使用 **桥接模式(Bridged Networking)**,让虚拟机拥有一个局域网 IP(如 `192.168.1.x`),这样宿主机和其他设备可以直接访问。 如果你必须用 NAT,需配置端口转发: ##### VirtualBox 示例(NAT + 端口转发): 1. 设置 → 网络 → 高级 → 端口转发 2. 添加规则: - 名称:MongoDB - 协议:TCP - 主机IP:留空(或 127.0.0.1) - 主机端口:27017 - 子系统IP:留空 - 子系统端口:27017 然后你在宿主机连接: ```bash mongosh "mongodb://localhost:27017" ``` --- ### ✅ 6. MongoDB 用户权限不足或未启用认证 虽然不影响“连上”,但可能导致认证失败。 建议始终设置用户名密码: ```bash docker run -d --name mongodb \ -p 27017:27017 \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=password \ mongo:6 --bind_ip_all ``` 连接时带上认证信息: ```bash mongosh "mongodb://admin:password@192.168.1.100:27017/admin" ``` --- ## ✅ 测试连性的小技巧 ### 在宿主机测试端口是否可达: ```bash telnet 192.168.1.100 27017 # 或 nc -zv 192.168.1.100 27017 ``` 如果提示 `Connection refused` 或超时,则说明网络不。 --- ## ✅ 最终推荐完整启动命令 ```bash docker run -d --name mongodb \ -p 27017:27017 \ -e MONGO_INITDB_ROOT_USERNAME=admin \ -e MONGO_INITDB_ROOT_PASSWORD=password \ mongo:6 \ --bind_ip_all ``` 然后从宿主机连接: ```bash mongosh "mongodb://admin:password@192.168.1.100:27017/admin" ``` ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值