Docker 容器端口映射与服务访问详细说明
前言
在服务器地址为:
172.24.9.117
执行 docker ps -a 得到如下信息:
| 服务 | 容器端口 | 宿主机端口 | 外部访问端口 |
|---|---|---|---|
| MySQL | 3306 | 31306 | 31306 |
| MongoDB | 27017 | 31017 | 31017 |
于是就产生一个问题:
访问 MySQL:
172.24.9.117:31306
这是 MySQL 容器的 IP 吗?
答案:
❌ 不是
✅ 这是服务器(宿主机)的 IP + 映射端口
一、172.24.9.117:31306 到底是什么?
当你访问:
172.24.9.117:31306
本质流程是:
外部客户端
↓
宿主机 172.24.9.117:31306
↓(Docker NAT 转发)
容器在 Docker 网络的 3306端口
也就是说:
- 172.24.9.117 是服务器 IP
- 31306 是宿主机端口
- 3306 是容器端口(容器应用监听的端口)
- Docker 在宿主机上将端口 31306 的流量通过 NAT 转发到容器在 Docker 网络的 3306端口
这叫:
端口映射(Port Mapping)
配置通常类似:
ports:
- "31306:3306"
格式是:
宿主机端口:容器端口
二、容器在 Docker 网络的 IP
每个容器会被 Docker 分配一个虚拟 IP,用于容器间通信,例如:
172.18.0.2
可以用命令查看:
docker inspect mysql
"Networks": {
"heyun_net": {
"IPAddress": "172.18.0.2"
}
}
⚠ 注意:
- 这个 IP 只在 Docker 网络内可见
- 外部机器无法直接访问
- NAT 转发规则会把外部访问引到这个 IP
三、容器 IP 是自动分配的吗?
是的。Docker 创建网络时会生成一个子网,例如:
172.18.0.0/16
容器加入网络时自动分配 IP:
- mysql → 172.18.0.2
- redis → 172.18.0.3
- app → 172.18.0.4
完全自动完成,无需手动干预。
四、容器 IP 会变吗?
会。如果容器:
- 被删除
- 被重建
- 网络被重建
IP 很可能变化:
172.18.0.2 → 172.18.0.5
所以:
❌ 不应该在代码里写死容器 IP
五、容器间通信
容器之间通常不写 IP,而是用:
mysql:3306
Docker 内置 DNS 会解析:
mysql → 172.18.0.2
然后发起 TCP 连接。类似访问公网网站:
google.com → 142.xxx.xxx.xxx
前提条件:容器必须在同一个 Docker 网络,Docker 内置 DNS 只解析同一网络下的服务名。如果容器 A 在 network-a,容器 B 在 network-b,默认无法通过服务名互访
六、容器可以有多个 IP
前提:容器加入多个网络,例如:
docker network connect net-a mysql
docker network connect net-b mysql
此时 mysql 有:
- net-a 的 IP
- net-b 的 IP
相当于一台服务器插了两张网卡,可以看到多个网络接口。
docker inspect mysql
在 Docker 中,容器的应用端口是固定的,例如 MySQL 的 3306,但容器可以加入多个网络,每个网络分配不同的 IP,因此同一个端口在不同网络中可以同时存在而不冲突。
对于外部访问,用户无需关心容器的网络或 IP,只需使用宿主机的 IP 和映射端口即可。 Docker 会通过 NAT 自动将流量转发到容器对应网络的端口,因此无论容器 IP 如何变化,只要宿主机端口不变,访问就稳定可靠。
七、Docker 可以有多个虚拟网络
docker network create backend-net
docker network create db-net
不同网络默认隔离:
- app 在 backend-net
- mysql 在 db-net
它们默认无法通信。除非:
- 放到同一个网络
- 或让一个容器同时加入两个网络
八、外部访问与开发环境
外部机器访问容器服务总是通过:
宿主机 IP + 映射端口
例如:
MYSQL_DB_HOST=172.24.9.117
MYSQL_DB_PORT=31306
- 与容器在 Docker 网络的 IP 无关
- 即使容器 IP 改变,也不会影响
- Docker NAT 规则保证端口映射稳定
九、总结
-
172.24.9.117:31306 不是容器 IP
- 是宿主机 IP + 映射端口
-
容器在 Docker 网络有自己的 IP
- 只在 Docker 网络内部可见
-
容器 IP 是自动分配的,可能会变
- 不要写死在代码里
-
容器可以加入多个网络,拥有多个 IP
- 外部访问仍通过宿主机端口
-
端口映射规则不会变
- 保证外部访问稳定
-
开发者应该使用服务名访问容器
- 外部访问:宿主机 IP + 映射端口
- 容器间访问:容器名 + 容器端口
更多推荐
所有评论(0)