Docker网络
嘿!长安来讲Docker网络了!这个看起来复杂,但我会用最简单的方式讲给你听!🌐
🤔 为什么需要网络?
问题场景
# 运行一个Web应用
docker run -d --name web nginx
# 运行一个MySQL数据库
docker run -d --name db mysql
# 问题:web容器怎么连接到db容器?
答案:Docker网络!
📚 Docker网络类型
Docker有几种网络模式:
1. bridge(桥接网络)- 默认
# 不指定网络,默认就是bridge
docker run -d nginx
特点:
- 容器之间可以互相访问
- 容器可以访问外网
- 外网不能直接访问容器(需要端口映射)
2. host(主机网络)
docker run -d --network host nginx
特点:
- 容器直接使用宿主机网络
- 没有网络隔离
- 性能最好
- 端口冲突风险高
3. none(无网络)
docker run -d --network none nginx
特点:
- 容器没有网络
- 完全隔离
- 适合安全要求极高的场景
4. container(容器网络)
# 容器2使用容器1的网络
docker run -d --name web1 nginx
docker run -d --name web2 --network container:web1 nginx
特点:
- 共享网络栈
- 可以用localhost互相访问
- 端口冲突风险
5. 自定义网络(最推荐!)
# 创建自定义网络
docker network create my-network
# 使用自定义网络
docker run -d --network my-network --name web nginx
docker run -d --network my-network --name db mysql
特点:
- 容器可以通过容器名互相访问
- 更好的隔离性
- 生产环境首选!
💡 长安建议:生产环境用自定义网络!
🌐 自定义网络详解
创建网络
# 创建bridge网络(默认)
docker network create my-network
# 指定子网
docker network create \
--subnet=172.18.0.0/16 \
my-network
# 指定网关
docker network create \
--subnet=172.18.0.0/16 \
--gateway=172.18.0.1 \
my-network
# 指定驱动
docker network create \
--driver bridge \
my-network
查看网络
# 列出所有网络
docker network ls
# 查看网络详情
docker network inspect my-network
输出:
[
{
"Name": "my-network",
"Driver": "bridge",
"Scope": "local",
"IPAM": {
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Containers": {}
}
]
使用网络
# 创建时指定网络
docker run -d --network my-network --name web nginx
# 运行中的容器连接到网络
docker network connect my-network web
# 断开网络
docker network disconnect my-network web
删除网络
# 删除网络
docker network rm my-network
# 清理未使用的网络
docker network prune
🎯 实战案例
案例1:Web + Database
传统方式(不好):
# 运行MySQL
docker run -d \
--name db \
-e MYSQL_ROOT_PASSWORD=123456 \
-p 3306:3306 \
mysql:8.0
# 运行Web应用(连接宿主机的3306端口)
docker run -d \
--name web \
-e DB_HOST=宿主机IP \
-e DB_PORT=3306 \
-p 8080:8080 \
my-web-app
问题:
- 需要暴露MySQL端口(不安全)
- 需要知道宿主机IP
- 配置复杂
Docker网络方式(好!):
# 创建网络
docker network create app-network
# 运行MySQL(不需要-p)
docker run -d \
--name db \
--network app-network \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0
# 运行Web应用(直接用容器名连接)
docker run -d \
--name web \
--network app-network \
-e DB_HOST=db \
-e DB_PORT=3306 \
-p 8080:8080 \
my-web-app
优点:
- MySQL不暴露端口(安全)
- 用容器名通信(简单)
- 完全隔离(网络层面)
案例2:微服务架构
# 创建网络
docker network create microservices
# 服务1:用户服务
docker run -d \
--name user-service \
--network microservices \
my-user-service
# 服务2:订单服务
docker run -d \
--name order-service \
--network microservices \
my-order-service
# 服务3:API网关(对外暴露)
docker run -d \
--name api-gateway \
--network microservices \
-p 80:80 \
my-api-gateway
服务之间通信:
// order-service访问user-service
fetch('http://user-service:3000/api/users')
// 用容器名就行,DNS自动解析!
案例3:多网络隔离
# 创建前端网络
docker network create frontend
# 创建后端网络
docker network create backend
# 数据库(只在后端网络)
docker run -d \
--name db \
--network backend \
mysql
# API服务(连接两个网络)
docker run -d \
--name api \
--network backend \
my-api
docker network connect frontend api
# Web服务(只在前端网络)
docker run -d \
--name web \
--network frontend \
-p 80:80 \
nginx
结果:
- web可以访问api ✅
- web不能访问db ❌(安全)
- api可以访问db ✅
🔍 容器DNS
自动DNS解析
在自定义网络中,容器可以通过容器名互相访问:
# 创建网络
docker network create my-net
# 运行容器1
docker run -d --name web --network my-net nginx
# 运行容器2,ping容器1
docker run --rm --network my-net alpine ping web
# ✅ 成功!容器名自动解析为IP
DNS配置
# 自定义DNS服务器
docker run -d \
--dns 8.8.8.8 \
--dns 114.114.114.114 \
nginx
# 自定义hosts
docker run -d \
--add-host myhost:192.168.1.100 \
nginx
🎨 网络调试技巧
1. 查看容器IP
# 方法1
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web
# 方法2
docker inspect web | grep IPAddress
2. 测试容器连接
# 从容器1 ping 容器2
docker exec web ping db
# 测试端口连通性
docker exec web nc -zv db 3306
# 使用curl测试HTTP
docker exec web curl http://db:3000
3. 查看网络中的所有容器
docker network inspect my-network | grep -A 5 Containers
4. 抓包调试
# 在容器内抓包
docker run --rm --net container:web nicolaka/netshoot tcpdump -i any
🚀 网络性能优化
1. 使用host网络(性能最好)
# 适合对性能要求极高的场景
docker run -d --network host nginx
缺点:
- 失去隔离性
- 端口冲突风险
2. 自定义MTU
docker network create \
--opt com.docker.network.driver.mtu=1450 \
my-network
3. 使用overlay网络(多主机)
# 需要Docker Swarm
docker network create \
--driver overlay \
--attachable \
my-overlay-network
💡 网络安全最佳实践
1. 最小暴露原则
# ❌ 不好(暴露所有端口)
docker run -p 3306:3306 mysql
# ✅ 好(不暴露,只在内网访问)
docker run --network my-network mysql
2. 网络隔离
# 前端和后端分开网络
docker network create frontend
docker network create backend
# 数据库只在后端网络
docker run --network backend mysql
3. 使用防火墙规则
# 限制IP访问
iptables -A DOCKER-USER -i eth0 ! -s 192.168.1.0/24 -j DROP
📊 常用命令速查
# 网络管理
docker network create <name> # 创建网络
docker network ls # 列出网络
docker network inspect <name> # 查看详情
docker network rm <name> # 删除网络
docker network prune # 清理未使用的网络
# 容器连接网络
docker network connect <network> <container> # 连接
docker network disconnect <network> <container> # 断开
# 创建容器时指定网络
docker run --network <name> # 指定网络
docker run --network host # 主机网络
docker run --network none # 无网络
# 查看容器IP
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' <container>
# 测试连接
docker exec <container> ping <target>
docker exec <container> curl <url>
💡 小结
今天长安教你玩转Docker网络:
核心概念
- 网络类型:bridge、host、none、自定义
- 推荐用法:生产环境用自定义网络
- 容器通信:通过容器名(DNS自动解析)
- 安全原则:最小暴露、网络隔离
常用命令
docker network create # 创建网络
docker network ls # 列出网络
docker network inspect # 查看详情
docker network connect # 连接容器到网络
docker run --network # 指定网络
最佳实践
- 使用自定义网络
- 不要随便暴露端口
- 服务通过容器名通信
- 敏感服务隔离网络
- 定期清理未使用的网络
🚀 下一步
基础知识都学完了!下一章长安带你进阶,学习 Docker Compose,一键管理多个容器!
💬 长安的网络踩坑记:
刚开始用Docker的时候,我所有容器都用默认网络。
结果容器之间通信要用IP,IP还总变,配置文件改到吐血😂
后来发现自定义网络可以用容器名通信,爽翻了!
还有一次,我把MySQL端口暴露到公网,结果被扫描器攻击了...
教训:
- 用自定义网络,通过容器名通信
- 不需要外网访问的服务,不要暴露端口!
网络搞明白了,Docker就掌握一大半了!💪
