Docker 网络是容器化应用架构中最关键的方面之一。理解容器之间、与宿主机以及与外部网络的通信方式,对于构建可靠、安全和可扩展的应用至关重要。本指南涵盖了所有 Docker 网络类型、docker-compose 网络模式和故障排查策略。
Docker 网络概述
Docker 为容器创建隔离的网络环境。默认情况下,Docker 提供多种网络驱动,每种针对不同的使用场景设计。
# List all Docker networks
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
a1b2c3d4e5f6 bridge bridge local
f6e5d4c3b2a1 host host local
1a2b3c4d5e6f none null localDocker 网络类型
Bridge 网络(默认)
Bridge 网络是容器的默认网络驱动。用户定义的 bridge 网络支持使用容器名称进行自动 DNS 解析。
# Create a user-defined bridge network
$ docker network create my-app-network
# Run containers on the custom network
$ docker run -d --name web --network my-app-network nginx:alpine
$ docker run -d --name api --network my-app-network node:20-alpine
# Containers can now reach each other by name
$ docker exec web ping api
PING api (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.089 ms
# User-defined bridge vs default bridge
# Default bridge: containers communicate only via IP addresses
# User-defined bridge: automatic DNS resolution by container name
# Create bridge with custom subnet
$ docker network create \
--driver bridge \
--subnet 172.20.0.0/16 \
--gateway 172.20.0.1 \
custom-bridgeHost 网络
Host 网络模式消除了容器与宿主机之间的网络隔离。容器直接共享宿主机的网络栈。
# Run container with host networking
$ docker run -d --network host nginx:alpine
# No port mapping needed — container uses host ports directly
# The nginx server is accessible at localhost:80
# Check: container shares host's network interfaces
$ docker exec <container-id> ip addr
# Shows the same interfaces as the host machine
# Warning: Only one container can bind to a given host port
# Host networking is only supported on Linux (not macOS/Windows)Overlay 网络
Overlay 网络连接多个 Docker 守护进程,使 Swarm 服务能够相互通信。
# Initialize Docker Swarm (required for overlay networks)
$ docker swarm init
# Create an overlay network
$ docker network create \
--driver overlay \
--attachable \
my-overlay-network
# Create a service on the overlay network
$ docker service create \
--name web \
--network my-overlay-network \
--replicas 3 \
nginx:alpine
# Create encrypted overlay network for sensitive data
$ docker network create \
--driver overlay \
--opt encrypted \
secure-overlayMacvlan 网络
Macvlan 网络允许为容器分配 MAC 地址,使其看起来像网络上的物理设备。
# Create a Macvlan network
$ docker network create \
--driver macvlan \
--subnet 192.168.1.0/24 \
--gateway 192.168.1.1 \
-o parent=eth0 \
my-macvlan
# Run container with its own IP on the LAN
$ docker run -d \
--network my-macvlan \
--ip 192.168.1.100 \
--name legacy-app \
my-app:latest
# The container appears as 192.168.1.100 on the physical networkNone 网络
None 网络禁用容器的所有网络功能,提供完全的网络隔离。
# Run container with no networking
$ docker run -d --network none alpine sleep 3600
# Only loopback interface is available
$ docker exec <container-id> ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
inet 127.0.0.1/8 scope host loDocker Compose 网络
Docker Compose 默认为应用创建一个网络。每个容器可以使用服务名作为主机名来访问其他容器。
# docker-compose.yml — Default networking
# All services share a network named <project>_default
services:
web:
image: nginx:alpine
ports:
- "80:80"
api:
image: node:20-alpine
# Can reach web service at http://web:80
# Can reach db service at postgres://db:5432
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secretCompose 中的自定义网络
# docker-compose.yml — Custom networks for isolation
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
networks:
- frontend
api:
build: ./api
networks:
- frontend
- backend
depends_on:
- db
- redis
db:
image: postgres:16
volumes:
- pg-data:/var/lib/postgresql/data
networks:
- backend
redis:
image: redis:7-alpine
networks:
- backend
admin:
image: adminer
ports:
- "8080:8080"
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # No external access
volumes:
pg-data:网络隔离模式
可以使用多个网络来隔离服务。例如,前端网络用于 Web 和 API,后端网络用于 API 和数据库。
# Three-tier architecture with network isolation
#
# Internet
# |
# [nginx] <-- frontend network
# |
# [api] <-- frontend + backend network
# |
# [db] <-- backend network (internal)
#
# nginx can reach api, but NOT db
# api can reach both nginx and db
# db is completely isolated from external accessDNS 和服务发现
Docker 为用户定义的网络提供内置 DNS 解析。容器可以通过名称互相解析。
DNS 解析规则
# DNS resolution in user-defined networks
# 1. Container name → IP address
$ docker exec web nslookup api
Server: 127.0.0.11
Address: 127.0.0.11#53
Name: api
Address: 172.18.0.3
# 2. Service name in Compose → all container IPs (round-robin)
$ docker exec web nslookup api
# Returns IPs of all 'api' service replicas
# 3. Network aliases
$ docker run -d \
--network my-network \
--network-alias database \
--network-alias db \
--name postgres-primary \
postgres:16
# Container is reachable as: postgres-primary, database, or db
# 4. Check DNS configuration inside a container
$ docker exec web cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0跨网络连接容器
可以将运行中的容器同时连接到多个网络。
# Connect a running container to an additional network
$ docker network connect backend api-container
# Connect with a specific IP address
$ docker network connect --ip 172.20.0.10 backend api-container
# Disconnect from a network
$ docker network disconnect frontend api-container
# A container connected to multiple networks can route between them
# This is useful for "gateway" containers网络检查
Docker 提供多个命令来检查和调试网络配置。
# List all networks
$ docker network ls
# Inspect a network (shows connected containers, config)
$ docker network inspect my-app-network
# Find which networks a container is connected to
$ docker inspect --format='{{json .NetworkSettings.Networks}}' my-container
# Check container IP address
$ docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-container
# Check port mappings
$ docker port my-container
# Test connectivity between containers
$ docker exec web ping -c 3 api
$ docker exec web wget -qO- http://api:3000/health
# Debug with a temporary network tools container
$ docker run --rm -it --network my-app-network \
nicolaka/netshoot bashDocker 网络故障排查
容器无法访问另一个容器
验证容器是否在同一网络上。
# Check if containers are on the same network
$ docker network inspect bridge --format='{{range .Containers}}{{.Name}} {{end}}'
# Solution: Use a user-defined network
$ docker network create app-net
$ docker run -d --name web --network app-net nginx
$ docker run -d --name api --network app-net node:20-alpine
# Now name resolution works
$ docker exec web ping api # Works!端口冲突
检查冲突端口并更换映射。
# Error: port is already allocated
# Find what is using the port
$ lsof -i :8080
$ ss -tlnp | grep 8080
# Solution 1: Map to a different host port
$ docker run -d -p 8081:80 nginx
# Solution 2: Stop the conflicting service
$ sudo systemctl stop apache2DNS 解析失败
可以为容器指定自定义 DNS 服务器。
# Specify custom DNS servers
$ docker run -d --dns 8.8.8.8 --dns 8.8.4.4 my-app
# Or in docker-compose.yml
services:
web:
image: nginx
dns:
- 8.8.8.8
- 8.8.4.4网络性能问题
考虑对性能关键服务使用 host 网络。
# Check MTU settings
$ docker network inspect bridge | grep -i mtu
# Set custom MTU for a network
$ docker network create --opt com.docker.network.driver.mtu=1400 my-network
# Use host networking for maximum performance
$ docker run --network host my-performance-app网络安全最佳实践
遵循以下最佳实践来保护 Docker 网络:
- 使用用户定义的 bridge 网络。
- 使用内部网络限制外部访问。
- 仅发布必要端口。
- 使用加密的 overlay 网络。
- 实施网络策略控制流量。
- 定期审计网络配置。
# Bind to localhost only (not accessible from outside)
$ docker run -d -p 127.0.0.1:5432:5432 postgres:16
# Create internal network (no outbound internet)
$ docker network create --internal isolated-net
# In docker-compose.yml
networks:
database:
internal: true # Containers cannot reach the internet高级网络主题
自定义 IPAM 配置
可以为 Docker 网络配置自定义 IP 地址管理。
# Custom IPAM configuration
$ docker network create \
--driver bridge \
--subnet 10.10.0.0/16 \
--ip-range 10.10.1.0/24 \
--gateway 10.10.0.1 \
--aux-address "dns=10.10.0.2" \
custom-ipam-net
# In docker-compose.yml
networks:
app-net:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
ip_range: 172.28.5.0/24
gateway: 172.28.0.1IPv6 支持
Docker 支持 IPv6 网络。
# Enable IPv6 in Docker daemon (/etc/docker/daemon.json)
{
"ipv6": true,
"fixed-cidr-v6": "2001:db8:1::/64"
}
# Create a dual-stack network
$ docker network create \
--ipv6 \
--subnet 172.20.0.0/16 \
--subnet 2001:db8:2::/64 \
dual-stack-net内置负载均衡
Docker Swarm 为服务提供内置负载均衡。
# Docker Swarm built-in load balancing
$ docker service create \
--name web \
--replicas 5 \
--publish published=80,target=80 \
--network my-overlay \
nginx:alpine
# Requests to port 80 on ANY swarm node
# are load-balanced across all 5 replicas
# using ingress routing mesh
# Scale the service
$ docker service scale web=10网络驱动对比
| 驱动 | 使用场景 | 隔离性 | 性能 | 多主机 |
|---|---|---|---|---|
| Bridge | Single-host containers | High | Good | No |
| Host | Performance-critical apps | None | Best | No |
| Overlay | Multi-host / Swarm | High | Good | Yes |
| Macvlan | Legacy / physical network | High | Good | No |
| None | Maximum isolation | Complete | N/A | No |
总结
Docker 网络是使用容器的开发者的基础技能。Bridge 网络处理大多数单主机场景,Overlay 网络用于多主机部署。掌握这些概念,你就能构建健壮、可扩展的容器化应用。
常见问题
Docker 中 bridge 和 host 网络有什么区别?
Bridge 网络创建隔离的网络命名空间并提供端口映射。Host 网络直接共享宿主机网络栈,性能更好但没有端口隔离。
什么时候应该使用 overlay 网络?
当需要不同 Docker 主机上的容器通信时使用,通常用于 Docker Swarm 或 Kubernetes 部署。
不同网络上的容器能通信吗?
默认不能。可以使用 docker network connect 将容器连接到多个网络。
如何排查 Docker DNS 解析问题?
确保容器在用户定义的网络上,使用 docker exec 在容器内运行 nslookup 或 dig。