← 全部文章
Docker网络原理

Docker 系列(六):容器网络与端口映射

2026年7月23日 · 12 分钟

容器的网络从哪来

每个容器启动时,Docker 会给它分配独立的网络命名空间——有自己的虚拟网卡和 IP。 容器怎么跟外界、跟彼此通信,取决于它用的网络模式

三种核心网络模式

docker network ls    # 查看所有网络,默认能看到 bridge / host / none

一、bridge(桥接,默认模式)

不指定时,容器默认接入名为 bridge 的虚拟网桥。容器有自己的内网 IP(如 172.17.x.x), 通过 NAT 访问外网。但外部无法直接访问容器——这就是为什么需要端口映射。

二、host(主机模式)

docker run -d --network host nginx

容器直接使用宿主机的网络,不做隔离。容器监听 80,就是宿主机的 80,无需 -p。 性能最好,但牺牲了隔离性,且端口容易冲突。Linux 上才完整支持。

三、none(无网络)

docker run --network none alpine

完全没有网络,只有 loopback。适合纯计算、对安全要求极高、不需联网的场景。

端口映射 -p 到底做了什么

docker run -d -p 8080:80 nginx

它在宿主机和容器之间建立了一条转发规则:

外部请求 -> 宿主机:8080 --[Docker NAT 转发]--> 容器:80

格式是 -p 宿主机端口:容器端口。几种变体:

-p 8080:80              # 宿主机 8080 -> 容器 80
-p 127.0.0.1:8080:80    # 只绑本机回环,外网访问不到(配合 Nginx 反代更安全)
-p 80:80 -p 443:443     # 映射多个端口
-P                      # 大写 P:自动映射 Dockerfile 里 EXPOSE 的所有端口

还记得部署博客时我建议把 -p 3000:3000 改成 -p 127.0.0.1:3000:3000 吗?原因就在 这里:只绑回环后,外网无法直连容器 3000,只能走 Nginx,更安全。

容器间通信:别用 IP,用服务名

新手常犯的错:想让 A 容器访问 B 容器,去查 B 的 IP。这是错的——容器 IP 会变。

正确做法是创建自定义 bridge 网络。自定义网络自带 DNS 解析,容器可以直接用 容器名/服务名互相访问。

# 1. 创建一个自定义网络
docker network create myapp-net

# 2. 让数据库加入这个网络,命名为 db
docker run -d --name db --network myapp-net \
  -e POSTGRES_PASSWORD=secret postgres:16

# 3. 让应用也加入同一网络
docker run -d --name api --network myapp-net myapi:latest

现在在 api 容器里,直接用主机名 db 就能连数据库:

postgres://user:secret@db:5432/mydb
                       ↑ 直接写容器名,Docker 内置 DNS 自动解析成 db 的 IP

这就是容器编排的基础——服务之间靠名字通信,而不是易变的 IP。第七篇的 Docker Compose 会把这套自动化。

网络管理命令

docker network ls                    # 列出网络
docker network create mynet          # 创建
docker network inspect mynet         # 查看详情(含已连接的容器)
docker network connect mynet web     # 把已有容器接入网络
docker network disconnect mynet web  # 断开
docker network rm mynet              # 删除

实战:Web 应用 + 数据库互联

# 1. 建网络
docker network create shop-net

# 2. 起数据库(不对外暴露端口,只在内网可见,更安全)
docker run -d --name shop-db --network shop-net \
  -e POSTGRES_PASSWORD=secret \
  -v shopdata:/var/lib/postgresql/data \
  postgres:16

# 3. 起应用,连接数据库用主机名 shop-db,只对外暴露应用端口
docker run -d --name shop-web --network shop-net \
  -e DATABASE_URL="postgres://postgres:secret@shop-db:5432/postgres" \
  -p 8080:3000 \
  myshop:latest

注意数据库没有 -p——它只需要在内网被应用访问,不必暴露给外网,这是安全最佳实践。

本篇小结

  • 三种网络模式:bridge(默认,需端口映射)、host(共享宿主网络)、none(无网络)。
  • -p 宿主:容器 建立端口转发;127.0.0.1:端口 只绑本机,配合反代更安全。
  • 容器间通信要用自定义网络 + 服务名,别依赖会变的 IP。
  • 数据库等内部服务不要 -p 暴露到外网,只在自定义网络内互通。

手动敲这么多 docker run 是不是很累?下一篇用 Docker Compose 把整套服务写进 一个文件、一条命令启动。

相关水晶