介绍
Docker 容器被设计为可移植和隔离的,但它们很少单独运行。容器需要相互通信、与主机系统以及外部服务通信。了解 Docker 的网络模型对于构建可靠、安全和高性能的容器化应用程序至关重要。
Docker 提供了多种内置网络驱动程序——bridge、host、overlay、macvlan、ipvlan 和 none——每种驱动程序都适合不同的用例。本指南深入介绍了每个驱动程序,以及 DNS 解析、端口映射、安全隔离和 Docker Compose 网络模式。
了解 Docker 网络驱动程序
每个容器都有一个连接到主机的虚拟网络接口(veth 对)。 Docker 使用 网络命名空间 为每个容器提供一个独立的网络堆栈,并拥有自己的 IP 地址、路由表和端口。
docker network 命令是管理网络的控制中心:
# List all networks
docker network ls
# Create a user-defined bridge network
docker network create my-network
# Inspect network details
docker network inspect my-network
# Connect a running container to a network
docker network connect my-network my-container
下面是 Docker 内置网络驱动的比较:
| 司机 | 范围 | 使用案例 | DNS解析 |
|---|---|---|---|
| 桥梁 | 单主机 | 独立容器的默认值 | 仅限用户定义 |
| 主持人 | 单主机 | 低延迟,无需隔离 | 不适用(主机 DNS) |
| 覆盖 | 多主机 | Swarm 服务、跨主机通信 | 是的 |
| 麦克弗兰 | 单主机 | 需要 MAC 地址的旧版应用程序 | 是的 |
| ipvlan | 单主机 | 高性能、大型子网 | 是的 |
| 无 | 单主机 | 最大程度的隔离 | 无 |
桥接网络的实践
桥接网络是 Docker 的默认驱动程序。当 Docker 启动时,它会在主机上创建一个名为 docker0 的虚拟网桥,并默认从 172.17.0.0/16 子网分配容器 IP。
默认网桥有局限性:没有自动 DNS 解析,并且所有容器都无隔离地连接。 用户定义的桥解决这些问题:
docker network create my-app-net
docker run -d --name web --net my-app-net nginx
docker run -d --name api --net my-app-net node:18
同一用户定义桥上的容器可以通过容器名称相互解析:
# From the api container, this resolves to web's IP
ping web
端口发布通过 iptables DNAT 规则将主机端口映射到容器端口:
# Map host port 8080 to container port 80
docker run -p 8080:80 nginx
主机和覆盖网络
主机网络
使用 --network host,容器直接共享主机的网络堆栈 — 无 NAT,无虚拟接口,并且延迟最小。这对于性能基准测试或需要监视主机接口的应用程序非常有用。但是,不存在网络隔离:容器可以绑定到任何主机端口并可能干扰其他服务。
# docker-compose.yml
services:
benchmark:
image: tool:latest
network_mode: "host"
覆盖网络
覆盖网络支持跨多个 Docker 主机进行通信。在 Swarm 模式下,创建覆盖网络会自动将其分发到所有节点:
docker network create -d overlay --attachable my-overlay
在底层,覆盖网络使用 VXLAN 封装来包装容器数据包,允许它们穿越物理网络边界。可以使用 --opt encrypted 标志通过 IPsec 对流量进行加密。性能开销约为每个数据包 50 字节,吞吐量降低 5-10%。
DNS解析和服务发现
Docker 在每个容器内的 127.0.0.11 处运行嵌入式 DNS 服务器。该服务器将容器名称解析为用户定义的桥接和覆盖网络上的 IP 地址。默认桥不提供 DNS 解析 - 您必须使用 --link (旧版)或切换到用户定义的桥。
在 Swarm 模式下,Docker DNS 为具有多个副本的服务提供循环解析:
# Create a service with 3 replicas
docker service create --name api --replicas 3 --network my-overlay my-api:latest
# Other containers resolve "api" to one of the 3 replicas via DNS round-robin
自定义 DNS 设置可以应用于每个容器:
docker run --dns 8.8.8.8 --dns-search example.com nginx
端口映射和安全隔离
端口映射将主机端口转换为容器端口。 -p 标志接受格式 hostPort:containerPort/protocol:
# Multiple ports, specific interface binding
docker run -p 127.0.0.1:8080:80 -p 443:443 nginx
对于网络隔离,Docker提供了几种机制:
- 内部网络 (
--internal) — 容器无法访问互联网。 - 无网络 (
--network none) — 仅环回,最大隔离。 - 单独的网桥 — 根据信任级别将容器保留在不同的用户定义的网桥上。
Docker 没有像 Kubernetes 那样内置网络策略。要进行细粒度控制,请使用 iptables、firewalld 或第三方插件,例如 Calico、Weave 或 Cilium。
Docker Compose 网络模式
Docker Compose 为每个项目创建一个用户定义的桥接网络 (<project>_default)。您可以在 Compose 文件中定义多个自定义网络来分隔关注点:
services:
web:
image: nginx
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
redis:
image: redis
networks:
- backend
networks:
frontend:
backend:
此模式将面向公众的 Web 层与内部数据层分开。 web 服务连接到两个网络,而 db 和 redis 只能在内部 backend 网络上访问。
要连接到预先存在的网络(例如共享监控网络),请使用外部网络:
networks:
monitoring:
external: true
扩展服务时,每个副本在同一网络上都有自己的容器。将 depends_on 与 healthcheck 和 condition 结合使用以确保服务准备就绪,而不是仅依赖启动顺序。
结论
Docker 的网络模型为容器通信提供了灵活、安全且高性能的选项。从针对单主机多容器应用程序的用户定义的桥接网络开始 - 它们提供自动 DNS 解析和比默认桥接更好的隔离。对于多主机部署,请使用带有 Docker Swarm 的 覆盖网络。
设计网络拓扑时:
- 优先选择基于 DNS 的服务发现,而不是硬编码的 IP 地址。
- 使用单独的桥接网络根据信任级别隔离各层。
- 仅当延迟或接口访问至关重要时才选择主机网络。
- 利用 Compose 网络定义使您的基础设施具有声明性和可复制性。
将 docker network inspect、docker exec 的网络问题调试到容器中以运行 ip addr 和 tcpdump,并检查防火墙规则是否存在跨主机连接问题。有了这些基础知识,您就可以构建强大且易于管理的容器网络。

