Docker 入门学习笔记 03:端口映射到底是什么,为什么容器启动了却访问不到

Docker 入门学习笔记 03:端口映射到底是什么,为什么容器启动了却访问不到

文章目录

本专栏文章导航

这一篇开始进入 Docker 学习里非常关键的一步:

为什么容器里的服务已经启动了,但宿主机还是访问不到?

这个问题看起来很基础,但它会直接影响后面学习:

  • Docker Compose
  • 容器网络
  • 微服务部署
  • Kubernetes Service

所以端口映射这一步一定要真正理解,而不是只记住一个 -p 参数。

一、先理解核心问题

例如执行下面这条命令:

bash 复制代码
docker run --name mynginx nginx

这时 Nginx 确实已经在容器里启动了,但这并不代表宿主机就能直接访问。

原因在于:

  • 服务运行在容器内部
  • 容器有自己的网络空间
  • 容器内部监听的端口,不会自动暴露给宿主机

所以首先要记住一句话:

容器里的端口,不等于宿主机的端口。

二、为什么会有端口这个概念

理解端口映射之前,先要知道为什么网络里会有"端口"。

一台机器上可以同时运行很多网络服务,例如:

  • Web 服务
  • 数据库
  • Redis
  • SSH
  • 监控系统

这些服务可能都在同一个 IP 上运行。

如果没有端口,系统就无法区分:

这次请求到底要交给哪个服务处理?

所以可以这样理解:

  • IP 像一栋楼的地址
  • 端口 像楼里的房间号

请求先到这栋楼,再根据端口号被送到不同服务。

例如常见端口:

  • 80:HTTP
  • 443:HTTPS
  • 22:SSH
  • 3306:MySQL
  • 6379:Redis

三、容器里的端口和宿主机端口不是一回事

Docker 里最容易误解的一点就是:

容器里的 80 端口,不等于宿主机的 80 端口。

例如 Nginx 在容器里监听 80,它只是说明:

这个服务在容器内部的 80 端口上提供服务。

但宿主机并不会自动把自己的某个端口交给它使用。

如果希望宿主机也能访问到这个服务,就必须显式做端口映射。

四、什么叫端口映射

Docker 里最常见的写法是:

bash 复制代码
-p 宿主机端口:容器端口

例如:

bash 复制代码
-p 8080:80

它表示:

  • 宿主机访问 8080
  • Docker 把流量转发到容器内部的 80

所以更准确地说:

-p 8080:80 不是"开放两个端口",而是"把宿主机 8080 转发到容器 80"。`

五、一个最常见的例子

下面这条命令是学习端口映射时最经典的例子:

bash 复制代码
docker run -d --name mynginx -p 8080:80 nginx

它可以拆成四部分理解:

  • -d:后台运行
  • --name mynginx:给容器起名字
  • -p 8080:80:宿主机 8080 映射到容器 80
  • nginx:使用 Nginx 镜像

它的真正含义是:

启动一个运行在容器里的 nginx,并把它的 80 端口暴露到宿主机的 8080 端口上。

六、为什么学习时推荐用 8080:80

理论上也可以写成:

bash 复制代码
-p 80:80

但在学习阶段,更推荐先用:

bash 复制代码
-p 8080:80

这样有两个好处:

  • 不容易和宿主机已有服务冲突
  • 更容易区分"宿主机端口"和"容器端口"是两个不同概念

学习时故意让两个数字不一样,理解会更清楚。

七、端口映射成功后会看到什么

执行下面这条命令:

bash 复制代码
docker run -d --name mynginx -p 8080:80 nginx

如果启动成功,终端通常会返回一个容器 ID,例如:

text 复制代码
a2b2ae9e288595d09281f23f8139c63fd67ee428e68ec474bc732aa901fe54ce

然后执行:

bash 复制代码
docker ps

可以看到类似下面的输出:

text 复制代码
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                                     NAMES
a2b2ae9e2885   nginx     "/docker-entrypoint...."   5 seconds ago   Up 4 seconds   0.0.0.0:8080->80/tcp, [::]:8080->80/tcp   mynginx

这里最值得关注的是 PORTS 这一列:

text 复制代码
0.0.0.0:8080->80/tcp, [::]:8080->80/tcp

学习阶段可以先抓住最核心的部分:

宿主机 8080 -> 容器 80/tcp

八、这段 PORTS 应该怎么理解

以这段输出为例:

text 复制代码
0.0.0.0:8080->80/tcp, [::]:8080->80/tcp

可以先这样理解:

  • 0.0.0.0:8080->80/tcp:宿主机所有 IPv4 地址上的 8080,都转发到容器 80/tcp
  • [::]:8080->80/tcp:宿主机所有 IPv6 地址上的 8080,也转发到容器 80/tcp

如果刚开始觉得 IPv4、IPv6 太多,可以先记最核心的一句:

访问宿主机的 8080,就会被转发到容器里的 80。

九、如何验证映射真的生效

最简单的方法就是直接访问宿主机对应端口:

bash 复制代码
curl http://localhost:8080

如果映射成功,通常会看到一段 HTML 内容,例如:

html 复制代码
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
<h1>Welcome to nginx!</h1>
...
</html>

这说明两件事:

  1. 容器里的 Nginx 确实启动成功了
  2. 宿主机 8080 已经成功转发到了容器 80

十、最容易混淆的三个点

1. 容器启动成功,不代表宿主机能访问

容器启动成功,只说明容器里的进程活着。

是否能从宿主机访问,还取决于是否做了端口映射。

2. -p 8080:80 里的顺序不能写反

顺序必须是:

bash 复制代码
宿主机:容器

也就是:

bash 复制代码
-p 8080:80

不是反过来。

3. 宿主机同一个端口不能随便重复占用

如果已经有一个容器使用了宿主机 8080,再启动另一个容器也想绑定 8080,通常会冲突。

例如:

bash 复制代码
docker run -d --name nginx2 -p 8080:80 nginx

这种情况下,宿主机的 8080 一般已经被前一个容器占用了。

所以更常见的做法是换一个宿主机端口,例如:

bash 复制代码
docker run -d --name nginx2 -p 8081:80 nginx

这时就会变成:

  • localhost:8080 -> 第一个容器
  • localhost:8081 -> 第二个容器

十一、一个常见的名字冲突问题

在练习过程中,还有一个很常见的问题不是端口冲突,而是容器名字冲突

例如执行:

bash 复制代码
docker run -d --name mynginx -p 8080:80 nginx

如果之前已经存在一个叫 mynginx 的容器,即使它已经退出,也仍然会报错。

常见错误类似这样:

text 复制代码
docker: Error response from daemon: Conflict. The container name "/mynginx" is already in use ...

这时候说明:

  • 问题不是端口本身
  • 而是容器名字已经被占用

解决方法通常是先删除旧容器:

bash 复制代码
docker rm mynginx

然后再重新启动。

这个问题也提醒了一个很重要的学习点:

容器退出了,不等于容器对象已经不存在。

十二、这一部分学完后应该掌握什么

如果这一部分真正掌握了,应该能清楚表达这些内容:

  • 容器内部端口和宿主机端口不是同一个概念
  • -p 宿主机端口:容器端口 表示端口映射
  • -p 8080:80 表示宿主机 8080 转发到容器 80
  • docker ps 里的 PORTS 能帮助判断映射是否生效
  • curl http://localhost:8080 能验证服务是否真的通了
  • 宿主机同一个端口通常不能同时重复绑定给多个容器

十三、这一部分最值得记住的一句话

如果只记一句话,最值得记住的是:

服务跑在容器里,不等于宿主机就能访问;要访问它,必须先把宿主机端口映射到容器端口。

十四、下一步要学什么

端口映射讲清楚之后,下一步最自然的延伸就是:

  • 为什么有些服务即使映射了端口也访问不到
  • 环境变量是怎么传进容器的
  • 数据为什么需要卷

也就是说,后面会继续进入"容器运行要素"的另外两块内容:

  • 环境变量

本专栏文章导航

相关推荐
xinzheng新政2 小时前
Javascript·深入学习基础知识
前端·javascript·学习
chushiyunen2 小时前
textCnn笔记
笔记
xieliyu.2 小时前
大一自学 Java:SE 阶段学习总结
学习
Terry Chu2 小时前
WordPress 完全教程:从入门到进阶(2026 最新版)
学习·学习方法
迷路爸爸1802 小时前
Docker 入门学习笔记 07:用一个多服务案例真正理解 Docker Compose
运维·笔记·学习·spring cloud·docker·容器·eureka
chh5632 小时前
从零开始学C++--类和对象
java·开发语言·c++·学习·算法
HyperAI超神经2 小时前
【TVM教程】理解 Relax 抽象层
人工智能·深度学习·学习·机器学习·gpu·tvm·vllm
炽烈小老头2 小时前
【每天学习一点算法 2026/04/07】快乐数
学习·算法
计算机安禾2 小时前
【数据结构与算法】第31篇:排序概述与插入排序
c语言·开发语言·数据结构·学习·算法·重构·排序算法