文章目录
- 一、问题背景:一个非常常见的疑惑
- 二、先给结论(一句话版)
- [三、为什么在「不用 Docker」时,端口看起来很自由?](#三、为什么在「不用 Docker」时,端口看起来很自由?)
- [四、Docker 场景:为什么一切都变了?(核心)](#四、Docker 场景:为什么一切都变了?(核心))
- [五、listen 和 -p 的职责划分](#五、listen 和 -p 的职责划分)
- 六、请求流转全过程
- 七、几种常见组合方式
- [八、为什么生产环境几乎都用 listen 80?](#八、为什么生产环境几乎都用 listen 80?)
- 九、总结
一、问题背景:一个非常常见的疑惑
在使用 Docker 部署 Nginx 时,很多人都会产生类似疑问:
- 为什么在 Windows / Linux 裸机上,端口好像"随便用"?
- 为什么进了 Docker 之后,
listen 80、listen 8111就变得这么讲究?- 为什么 Docker 里端口不对齐,就直接
Connection refused?
二、先给结论(一句话版)
Docker 中端口不是"随便用"的,
listen决定容器内部监听,-p决定宿主机对外暴露,
两者必须一一对应。



三、为什么在「不用 Docker」时,端口看起来很自由?
裸机 Nginx / Java 服务的模型
当你在 Linux 或 Windows 上直接启动一个服务:
nginx
listen 8888;
操作系统会直接在 宿主机 上监听 8888 端口:
浏览器 → 操作系统 → Nginx 进程
只要端口没被占用:
- 你监听 8888 ✅
- 你监听 18080 ✅
- 你监听 30000 ✅
👉 端口属于操作系统,进程直接对外暴露
四、Docker 场景:为什么一切都变了?(核心)
Docker 不是进程,是"迷你系统"
Docker 容器具备:
- 独立的网络命名空间
- 独立的端口
- 独立的 IP(如
172.x.x.x)
📌 容器内的端口 ≠ 宿主机端口
Docker 端口映射在干什么?
当你运行:
bash
docker run -p 8111:80 nginx
它的真实含义是:
宿主机 8111 → 容器 80
也就是说:
- 外界只能访问 8111
- 容器里必须有服务监听 80
五、listen 和 -p 的职责划分
listen(Nginx)
nginx
listen 80;
👉 决定容器内部哪个端口有服务在接请求
-p(Docker)
bash
-p 8111:80
👉 决定宿主机哪个端口"打洞"连进容器
两者关系总结
| 层级 | 决定者 | 作用 |
|---|---|---|
| 容器内部 | listen |
有没有进程监听 |
| 宿主机对外 | -p |
外部能不能访问 |
六、请求流转全过程
浏览器
↓ http://IP:8111
宿主机 8111
↓ Docker 映射
容器 80
↓
Nginx listen 80
📌 每一层都必须"接得住"
七、几种常见组合方式
正确组合(最推荐)
bash
docker run -p 8111:80 nginx
nginx
listen 80;
✔ 最常见
✔ 最稳定
✔ 容器内部统一端口
也正确(但不常用)
bash
docker run -p 8111:8111 nginx
nginx
listen 8111;
✔ 内外端口一致
❌ 可维护性略差
❌ 错误组合 1(最常见坑)
bash
docker run -p 8111:80 nginx
nginx
listen 8111;
❌ 请求进容器 80
❌ Nginx 在 8111 等
➡ 必然 Connection refused
❌ 错误组合 2
bash
docker run -p 8111:8111 nginx
nginx
listen 80;
❌ 容器 8111 没服务
➡ 访问失败
八、为什么生产环境几乎都用 listen 80?
符合 Web 默认认知
- HTTP → 80
- HTTPS → 443
容器复用性高
- 镜像不用关心外部端口
方便平台化
- Docker Compose
- Kubernetes(Pod 内固定 80)
职责清晰
- Docker 管"对外"
- Nginx 管"接入"
九、总结
Docker 世界三件事:
listen:容器里有没有人接电话-p:宿主机给不给你电话线- 两头对不上,一定打不通
在 Docker 里,端口不是"随便写"的,
而是"每一层都要有人负责"