Appearance
自定义网络
用户定义网络(User-defined Network)是 Docker 网络的最佳实践,相比默认 bridge 网络提供了更好的隔离性和服务发现能力。
创建自定义网络
bash
# 基本创建(使用默认 bridge 驱动)
docker network create my-network
# 指定驱动
docker network create --driver bridge my-network
# 指定子网和网关
docker network create \
--driver bridge \
--subnet 172.20.0.0/16 \
--gateway 172.20.0.1 \
my-network
# 指定 IP 范围(从 CIDR 范围中分配 IP)
docker network create \
--subnet 172.20.0.0/16 \
--ip-range 172.20.10.0/24 \
--gateway 172.20.0.1 \
my-network
# 设置标签
docker network create \
--label project=myapp \
--label env=production \
my-network
# 禁用容器间通信(只能访问外部网络)
docker network create \
--driver bridge \
--opt com.docker.network.bridge.enable_icc=false \
isolated-network查看网络详情
bash
# 列出所有网络
docker network ls
# 查看网络详细信息
docker network inspect my-network
# 格式化输出(查看连接的容器)
docker network inspect my-network \
--format '{{json .Containers}}' | python3 -m json.tool
# 查看网络子网配置
docker network inspect my-network \
--format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'容器连接到自定义网络
创建时指定网络
bash
# 创建容器时加入网络
docker run -d --name web --network my-network nginx
docker run -d --name db --network my-network mysql:8.0 \
-e MYSQL_ROOT_PASSWORD=secret
# 指定静态 IP
docker run -d \
--name web \
--network my-network \
--ip 172.20.0.100 \
nginx已有容器加入网络
bash
# 将已运行的容器加入网络
docker network connect my-network existing-container
# 指定 IP 加入
docker network connect --ip 172.20.0.200 my-network existing-container
# 设置别名(同一网络中可通过别名访问)
docker network connect --alias myalias my-network existing-container断开网络连接
bash
docker network disconnect my-network my-container容器间通信
在同一用户定义网络中的容器,可以通过容器名直接通信(内置 DNS):
bash
# 创建网络和容器
docker network create app-net
docker run -d --name mysql \
--network app-net \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=mydb \
mysql:8.0
docker run -d --name api \
--network app-net \
-e DB_HOST=mysql \
-e DB_PORT=3306 \
myapi:latest
# api 容器内可以直接通过 "mysql" 名称访问数据库
docker exec api ping mysql # 可以 ping 通
docker exec api curl http://mysql:80 # 通过名称访问多网络配置
一个容器可以同时连接多个网络,实现网络分层:
bash
# 前端网络(对外暴露)
docker network create frontend-net
# 后端网络(仅内部通信)
docker network create backend-net
# Nginx 连接两个网络(作为反向代理)
docker run -d --name nginx \
--network frontend-net \
-p 80:80 \
nginx
docker network connect backend-net nginx
# API 只在后端网络
docker run -d --name api \
--network backend-net \
myapi
# 数据库只在后端网络
docker run -d --name db \
--network backend-net \
mysql:8.0
# 架构:Internet → nginx(frontend-net + backend-net) → api(backend-net) → db(backend-net)网络别名
同一网络中可以为容器设置别名,实现简单的负载均衡:
bash
docker network create service-net
# 两个容器共享同一个别名(Round-robin DNS)
docker run -d --network service-net --network-alias api myapi:v1
docker run -d --network service-net --network-alias api myapi:v2
# 访问 "api" 会随机路由到其中一个
docker run --rm --network service-net alpine nslookup api
# 会返回两个 IP 地址实用配置示例
Web 应用的网络架构
bash
#!/bin/bash
# 创建网络
docker network create --driver bridge \
--subnet 172.20.0.0/24 \
webapp-net
# 数据库
docker run -d \
--name postgres \
--network webapp-net \
--ip 172.20.0.10 \
-e POSTGRES_PASSWORD=secret \
-v pgdata:/var/lib/postgresql/data \
postgres:16-alpine
# 缓存
docker run -d \
--name redis \
--network webapp-net \
--ip 172.20.0.11 \
redis:alpine
# 后端 API
docker run -d \
--name api \
--network webapp-net \
--ip 172.20.0.20 \
-e DATABASE_URL=postgresql://postgres:secret@postgres:5432/mydb \
-e REDIS_URL=redis://redis:6379 \
myapi:latest
# 前端(仅 API 通过 nginx 对外暴露)
docker run -d \
--name nginx \
--network webapp-net \
-p 80:80 \
-p 443:443 \
nginx:alpine删除网络
bash
# 删除指定网络(需要先断开所有容器)
docker network rm my-network
# 删除多个网络
docker network rm net1 net2 net3
# 删除所有未使用的网络
docker network prune
# 强制删除(-f 忽略确认)
docker network prune -f排查网络问题
bash
# 查看容器 IP 地址
docker inspect container --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
# 测试容器间连通性
docker exec container1 ping container2
docker exec container1 curl http://container2:8080
# 查看容器 DNS 解析
docker exec container1 nslookup container2
docker exec container1 cat /etc/resolv.conf
# 查看容器路由表
docker exec container1 ip route
# 抓包(需要 tcpdump)
docker exec container1 tcpdump -i eth0 -n总结
自定义网络的核心优势:
- 容器名 DNS 解析:无需记忆 IP,通过名称直接访问
- 网络隔离:不同应用使用不同网络,互不干扰
- 动态管理:随时连接/断开容器
- 网络别名:实现简单的服务发现
最佳实践:为每个应用创建独立的自定义网络,只通过 Nginx/负载均衡器对外暴露必要端口。