首页 / Docker 入门教程 / 容器网络基础与端口映射

Docker 入门教程

容器网络基础与端口映射

本教程共 25 篇 · 第 18 篇 · 更新于 2026-07-26 · 约 8 分钟阅读

DockerDocker 入门教程容器网络端口映射bridgehostdocker network

18. 容器网络基础与端口映射

本节目标:搞懂 Docker 的三种网络模式,学会用 -p-P 把容器端口映射到宿主机,让外部能访问容器里的服务。

前面跑容器时你已经用过端口映射了,比如 docker run -p 8080:80 nginx。但为什么要这么写、-p-P 有啥区别、bridge 和 host 网络又是怎么回事,这一章讲清楚。

为什么需要端口映射

容器是隔离的环境,有自己的网络栈。默认情况下,容器里的服务监听的端口,宿主机和外部是访问不到的。

打个比方:容器像一间有独立门牌的房间,里面的服务在房间内某个端口上听电话。但房间外面的人不知道这个端口,也进不来。端口映射就是在大门口设个前台,告诉来访者「你找 8080 号,我帮你转到房间的 80 号」。

不映射端口,容器里的服务只能容器自己玩;映射了,外部才能访问。这就是为什么跑 Web 服务必带 -p

Docker 的三种网络模式

Docker 安装后会自动建三个网络,用 docker network ls 能看到:

$ docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
c2c695315b3a   bridge    bridge    local
a875bec5d6fd   host      host      local
ead0e804a67b   none      null      local

这三个就是最基础的网络模式。

bridge:默认桥接网络

bridge 是默认网络。不指定 --network 时,容器都连到这个网络。

它的工作原理是在宿主机上建一个虚拟网桥(Linux 上叫 docker0),给每个容器分配一个内网 IP(通常是 172.17.0.x),容器通过网桥和宿主机通信,容器之间也能互通。

bridge 网络的特点:

  • 容器有独立 IP,和宿主机网络隔离。
  • 需要端口映射才能让外部访问。
  • 同一个 bridge 网络的容器之间,默认只能用 IP 通信,不能用容器名(默认 bridge 不带 DNS 解析)。
Note

默认 bridge 网络没有自动 DNS 解析,这是它和「自定义 bridge 网络」最大的区别。容器之间想用名字互相访问,得用自定义网络,这是下一章的重点。

host:直接用宿主机网络

host 模式下,容器不隔离网络,直接共用宿主机的网络栈。容器里监听 80 端口,就等于宿主机监听 80 端口,不用映射。

docker run -d --network host nginx

这种方式网络性能最好(没有桥接和 NAT 开销),但牺牲了隔离性:容器能看到的网络就是宿主机的网络,端口冲突也得自己处理。

Warning

host 模式下,容器里启动的服务端口如果和宿主机已有服务冲突,会直接启动失败。而且容器没有独立 IP,网络安全隔离变弱。生产环境慎用,主要用于对网络性能要求极高的场景。Docker Desktop(Mac/Windows)上 host 模式行为和 Linux 不同,因为宿主机本身就是个 VM,效果有限。

none:无网络

none 模式给容器一个独立的网络栈,但不配任何网络接口。容器里只有 lo(本地回环),没有外部网络。

docker run -d --network none alpine sleep 1000

这种容器完全断网,适合跑一些不需要联网的计算任务,或者出于安全考虑要隔离的容器。用得少,但要知道有这个选项。

端口映射:-p 和 -P

外部要访问容器,靠端口映射。docker run 时用 -p-P 标志。

-p:指定端口映射

-p(小写)让你精确控制映射,语法是 宿主机端口:容器端口

docker run -d -p 8080:80 nginx

这条命令把容器的 80 端口映射到宿主机的 8080 端口。访问 http://localhost:8080,流量被转发到容器的 80 端口。

宿主机端口和容器端口可以不一样,这是常用做法—容器内部用约定端口(比如 80),宿主机用你方便记的端口(比如 8080),避免和宿主机已有服务冲突。

一个容器可以映射多个端口:

docker run -d -p 8080:80 -p 8443:443 nginx

指定绑定的 IP

默认映射会绑定到宿主机的所有网络接口(0.0.0.0),意味着局域网里别的机器也能访问。如果想只允许本机访问,指定绑定 127.0.0.1

docker run -d -p 127.0.0.1:8080:80 nginx

这样只有宿主机自己能访问 8080,外部访问不了。适合跑数据库这种不想暴露到外网的服务。

完整语法是 IP:宿主机端口:容器端口

docker run -d -p 127.0.0.1:5432:5432 postgres
Warning

端口默认绑定到 0.0.0.0,意味着所有网卡都能访问。在云服务器上,如果你把数据库端口直接 -p 5432:5432 映射出去,又没配安全组,等于把数据库暴露在公网。务必用 127.0.0.1:5432:5432 限制只本机访问,或者干脆不映射端口,用自定义网络让其他容器内部访问。

指定 UDP 端口

默认映射的是 TCP 端口。要映射 UDP,在端口后加 /udp

docker run -d -p 5000:5000/udp my-udp-app

TCP 和 UDP 是两套独立的端口空间,可以同时映射:

docker run -d -p 5000:5000 -p 5000:5000/udp my-app

-P:随机映射所有暴露端口

-P(大写)让 Docker 自动把镜像里 EXPOSE 声明的所有端口,随机映射到宿主机的临时端口(通常是 32768-60999 范围)。

docker run -d -P nginx

查看映射到哪个端口了:

$ docker ps
CONTAINER ID   IMAGE    PORTS                    NAMES
a527355c9c53   nginx    0.0.0.0:54772->80/tcp    romantic_williamson

0.0.0.0:54772->80/tcp 表示宿主机的 54772 映射到容器的 80。访问 http://localhost:54772 即可。

-P 适合不想纠结端口冲突、临时跑起来测试的场景。生产环境一般用 -p 精确指定,端口固定才好配置和监控。

-p 和 -P 的区别

标志行为适用场景
-p 宿主机:容器指定端口映射生产、需要固定端口
-P随机映射所有 EXPOSE 端口测试、避免端口冲突
Note

注意区分「EXPOSE」和端口映射。Dockerfile 里的 EXPOSE 只是声明,不等于真的对外开。要真的能访问,还得靠 docker run -p-P-P 正是读取 EXPOSE 声明的端口来做自动映射的。

查看端口映射

除了 docker ps 看 PORTS 列,还有个专门命令 docker port

docker port romantic_williamson 80
# 输出:0.0.0.0:54772

它会告诉你某个容器的指定端口映射到了宿主机的哪里。查多个端口就多查几次,或者直接 docker port 容器名 列出所有映射。

多个容器用同一个端口怎么办

宿主机的同一个端口只能被一个进程占用,端口映射也一样。如果你起两个容器都映射到宿主机 8080,第二个会报端口占用失败。

解决办法是让宿主机端口不同,容器端口可以相同:

docker run -d -p 8080:80 nginx   # 第一个
docker run -d -p 8081:80 nginx   # 第二个,用 8081

两个容器内部都是 80,但宿主机分别用 8080 和 8081 访问。开发测试时经常这么干,一台机器跑多个实例。

Tip

想一次性起多个相同服务做负载测试,又不想手动指定端口,用 -P 让 Docker 随机分配,省心。

网络相关的常用命令

汇总一下网络管理常用命令:

# 列出所有网络
docker network ls

# 查看某个网络的详情(含哪些容器连在上面、子网等)
docker network inspect bridge

# 创建自定义网络(下一章重点)
docker network create my-net

# 把运行中的容器连到某个网络
docker network connect my-net 容器名

# 把容器从网络断开
docker network disconnect my-net 容器名

# 删除网络(没有容器连接时才能删)
docker network rm my-net

这一章先用 lsinspect 看看网络结构,createconnect 留到下一章细讲。

小结

把网络基础收一下:

  1. 容器默认网络隔离,外部访问靠端口映射。
  2. 三种网络模式:bridge(默认,需映射)、host(共用宿主机网络)、none(断网)。
  3. -p 宿主机:容器 精确映射,-P 随机映射所有 EXPOSE 端口。
  4. 127.0.0.1:宿主机:容器 限制只本机访问,别把数据库直接暴露公网。
  5. 同一宿主机端口不能被多个容器占用,换宿主机端口即可。
  6. EXPOSE 只是声明,-p/-P 才真的开放端口。

下一章讲容器互联—怎么让多个容器在一个自定义网络里用名字互相通信,这是搭建多服务应用的基础。