Docker 网络

容器默认是网络孤岛——既访问不到外面,也访问不到彼此。要让容器能联网、能被外部访问、能互相通信,就要理解 Docker 的网络模型。本章把默认网络、端口映射、自定义网络讲透,这是后面 Compose 多服务编排的基础。

三种默认网络

Docker 安装完就有三种预置网络,看一眼:

# Docker 自带三种网络,装完就有

docker network ls
# NETWORK ID   NAME      DRIVER    SCOPE
# a1b2c3d4     bridge    bridge    local     ← 默认,所有容器都连它
# e5f6g7h8     host      host      local     ← 直接用主机网络,无隔离
# i9j0k1l2     none      null      local     ← 完全无网络

# 1. bridge(默认):容器通过虚拟网桥 docker0 通信
docker run -d --name web nginx
# web 自动连到 bridge 网络,获得一个内网 IP(如 172.17.0.2)

# 2. host:容器直接用主机网络栈,无端口映射,性能最好
docker run -d --network host nginx
# 容器 80 端口就是主机 80 端口,-p 失效
# 仅 Linux 有效;macOS/Windows 由于有虚拟机层意义不大

# 3. none:完全无网络(适合纯离线计算任务)
docker run -d --network none alpine sleep 3600

99% 情况用默认的 bridge 就行。host 模式有特殊性能需求才考虑。

端口映射:让外部访问容器

默认 bridge 网络里的容器,IP 是内网的,外部访问不到。要让外部访问,必须用 -p 把主机端口映射到容器端口:

# 端口映射:让外部访问容器

# -p 主机端口:容器端口
docker run -d -p 8080:80 nginx          # 主机 8080 → 容器 80
docker run -d -p 80:80 nginx            # 主机 80 → 容器 80

# 多个端口
docker run -d -p 80:80 -p 443:443 nginx

# 指定监听 IP(默认 0.0.0.0 对所有网卡开放)
docker run -d -p 127.0.0.1:8080:80 nginx   # 只本机能访问,不对外暴露

# UDP 端口
docker run -d -p 53:53/udp dns

# 大写 -P:自动分配主机端口(从 49153~65535 选一个空闲的)
docker run -d -P nginx
docker port <容器>                       # 看分到了哪个端口

# 范围映射
docker run -d -p 8000-8010:8000-8010 app  # 端口范围

记忆方式:-p 主机端口:容器端口,左主机、右容器。一定要写具体端口,生产环境用 -P(大写,随机分配)会让运维找不到服务到底在哪个端口。127.0.0.1:8080:80 这种写法在生产很有用——只让本机能访问的管理后台、数据库,避免暴露到公网。

自定义网络:容器互访的关键

默认 bridge 有个大问题:容器之间只能用 IP 通信,不能用名字。这就导致数据库连接串要写死 IP,容器一重启 IP 变了就连不上。解决方案是自定义 bridge 网络——它会自动启用 DNS,让容器能用名字互访:

# 自定义 bridge 网络:容器互访的关键

# 默认 bridge 网络有个大问题:容器之间只能用 IP 通信,不能用名字
# 解决:创建自定义 bridge 网络,自动启用 DNS,容器能用名字互访

docker network create mynet

# 把容器加进同一网络
docker run -d --network mynet --name api myapp
docker run -d --network mynet --name db postgres:16

# 在 api 容器里,直接用名字 db 就能连到 postgres
docker exec -it api sh
> ping db              # 能解析到 db 的 IP
> psql -h db -U app    # 数据库连接串直接写 db:5432

# 把运行中容器加入/移出网络
docker network connect mynet web        # 把 web 加入 mynet(可同时连多个)
docker network disconnect mynet web     # 移出网络

# 看网络里有谁
docker network inspect mynet            # 列出所有连进来的容器和 IP

这就是为什么后面 Compose 不用手动配网络也能互访——Compose 默认给每个项目创建一个自定义网络,服务名自动注册为 DNS。一个容器可以同时连多个网络(用多次 --networkdocker network connect),实现精细的网络隔离。

自动 DNS 详解

# 自动 DNS 是自定义网络的核心优势

# 默认 bridge 网络:容器间只能用 IP 通信
docker run -d --name app1 alpine sleep 3600
docker run -d --name app2 alpine sleep 3600
docker exec app1 ping app2              # ping 不通!DNS 不解析 app2

# 自定义 bridge 网络:容器名自动注册为 DNS 名
docker network create mynet
docker run -d --network mynet --name svc1 alpine sleep 3600
docker run -d --network mynet --name svc2 alpine sleep 3600
docker exec svc1 ping svc2              # 通了!自动解析到 svc2 的 IP

# 这就是为什么 Compose 不用手动配网络也能互访:
# Compose 会为每个项目自动创建一个自定义网络,服务名即 DNS 名
# 在 docker-compose.yml 里写 db:5432 就能连数据库,背后就是这个机制

理解了这个对比,你就明白了为什么"默认 bridge 不适合多容器应用"。注意 DNS 解析的是容器名网络别名(alias),不是镜像名。同一个自定义网络内的容器才能互相解析,跨网络不行。

docker network 全套命令

# docker network 全套命令

# 创建网络
docker network create mynet                          # bridge(默认)
docker network create --driver bridge mynet          # 显式指定 bridge
docker network create --subnet 192.168.10.0/24 mynet # 指定子网
docker network create --internal secure-net          # 内部网络,不能出网

# 列出所有网络
docker network ls

# 看网络详情(容器列表、子网、网关)
docker network inspect mynet

# 删除网络(必须先断开所有容器)
docker network rm mynet

# 清理所有无用网络
docker network prune

# 让运行中容器加入/退出网络
docker network connect mynet web
docker network disconnect mynet web

docker network inspect 是排错利器——能看到某网络里有哪些容器、各自的 IP 是多少。"容器 A 连不上容器 B"时,先 inspect 看它们是否在同一个网络、IP 段是否一致。

生产网络拓扑实战

真实项目通常做多层网络隔离,把对外的和对内的分开:

# 生产环境网络拓扑(典型)

# 前端代理 → 后端 API → 数据库,三层隔离
docker network create web-tier         # 公开,前端代理在这层
docker network create app-tier         # 内部,API 和数据库在这层

# 前端代理:同时连 web-tier 和 app-tier
docker run -d --name proxy --network web-tier \
  --network app-tier nginx

# API:只连 app-tier
docker run -d --name api --network app-tier myapp

# 数据库:只连 app-tier
docker run -d --name db --network app-tier postgres

# 效果:
#   - 外部只能访问 proxy 的 80/443
#   - api 和 db 不暴露任何端口给外部
#   - proxy 通过 app-tier 网络能访问 api
#   - 数据库被严格隔离在内部,无法被外部直连

# 多机部署:overlay 网络(配合 Swarm 或 Kubernetes)
docker network create --driver overlay --attachable mynet

这种"代理层连两个网络、内层服务不暴露端口"的拓扑,是生产环境的基本安全模式。数据库绝不-p 暴露端口到公网,只在内部网络被 API 访问。多机部署时,跨主机容器通信用 overlay 网络(配合 Docker Swarm 或 Kubernetes),它能像在一个局域网里一样让不同主机的容器互访。

常见问题

← 上一篇 Docker 数据卷

下一篇 Docker Compose

✈️💬