Docker的存储驱动就像建筑工地上的材料堆放策略。当我们在本地构建镜像时,存储驱动决定了如何高效地组织和管理这些"建筑材料"。主流的overlay2驱动采用类似俄罗斯套娃的分层机制:
我曾在生产环境遇到因存储驱动选择不当导致的性能问题。某次使用devicemapper驱动时,容器批量启动时间比overlay2慢了近3倍。后来通过修改/etc/docker/daemon.json配置切换驱动:
json复制{
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
重要提示:修改存储驱动后原有镜像需重新构建,建议在测试环境验证后再上线
容器本身是临时沙盒,重要数据必须外挂存储。就像不能把公司财务数据写在沙滩上,我们通常采用三种持久化方案:
bash复制docker run -v /host/path:/container/path nginx
bash复制docker volume create my_volume
docker run -v my_volume:/data mysql
bash复制docker run --tmpfs /app/cache redis
去年我们有个惨痛教训:某服务直接写入容器内部,服务器宕机后数据全失。现在团队强制规定所有生产容器必须显式声明存储方式,通过docker inspect检查挂载配置已成发布流程必备环节。
Docker提供五种网络模式,就像办公室的不同通讯方案:
| 模式 | 适用场景 | 性能损耗 | 隔离性 | 典型命令 |
|---|---|---|---|---|
| bridge | 默认单机环境 | 15% | 中 | docker run --net=bridge |
| host | 高性能场景 | <5% | 低 | docker run --net=host |
| none | 安全隔离环境 | 0 | 高 | docker run --net=none |
| container | 容器间直连 | 10% | 中 | docker run --net=container:xxx |
| overlay | Swarm集群跨主机通信 | 25% | 高 | docker network create -d overlay |
我们在压力测试中发现,host模式虽然性能最优,但会导致端口冲突风险。某次线上事故就是因两个容器同时绑定80端口引发服务瘫痪。现在生产环境规范要求:
创建带子网的自定义网络:
bash复制docker network create \
--driver=bridge \
--subnet=172.28.0.0/16 \
--gateway=172.28.5.1 \
--ip-range=172.28.5.0/24 \
my_network
关键参数解析:
--subnet:指定整个网络的地址池--gateway:相当于办公室的总路由器--ip-range:限定容器IP分配范围我曾用这个方案解决过微服务IP冲突问题。当多个团队共享Docker主机时,预先划分IP段可以避免:
网络连接检查技巧:
bash复制# 查看容器网络详情
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 容器名
# 测试容器间连通性
docker exec -it 容器1 ping 容器2_IP
当存储需要跨主机访问时,网络配置尤为关键。我们曾为MongoDB分片集群设计过这样的方案:
bash复制docker network create -d overlay --attachable mongo_net
bash复制docker plugin install --alias cloudstor \
store/cloudstor:latest \
CLOUD_PLATFORM=AWS \
AWS_REGION=us-east-1 \
AWS_ACCESS_KEY_ID=xxx \
AWS_SECRET_ACCESS_KEY=xxx
bash复制docker service create \
--name mongo_shard \
--network mongo_net \
--mount type=volume,source=mongo_data,destination=/data/db,volume-driver=cloudstor \
mongo:4.2 --shardsvr
这个架构实现了:
存储性能常受网络制约。我们通过TC(Traffic Control)限制容器网络带宽:
bash复制# 创建带带宽限制的网络
docker network create \
--driver=bridge \
-o "com.docker.network.driver.mtu"="1500" \
-o "com.docker.network.bridge.name"="br-limit" \
limit_net
# 在宿主机配置TC规则
tc qdisc add dev br-limit root handle 1: htb default 12
tc class add dev br-limit parent 1: classid 1:1 htb rate 100mbit ceil 100mbit
tc class add dev br-limit parent 1:1 classid 1:12 htb rate 10mbit ceil 10mbit
这个方案将接入limit_net的所有容器带宽限制在10Mbps,避免某个容器耗尽带宽影响其他服务。实测发现对IO密集型应用,合理限制带宽反而能提高整体稳定性。
某次凌晨收到磁盘报警,/var/lib/docker占用率达95%。紧急处理流程:
bash复制docker ps -s --format "{{.ID}} {{.Names}} {{.Size}}"
bash复制docker system prune -af
bash复制find /var/lib/docker/containers -name "*.log" -size +100M -exec truncate -s 0 {} \;
事后我们增加了这些防护措施:
0 2 * * * docker system prune -fjson复制{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
当容器无法联网时,我的排查路线图:
bash复制docker exec -it 容器名 ping 8.8.8.8
bash复制docker exec -it 容器名 nslookup google.com
bash复制iptables -L -n -v --line-numbers
bash复制docker network inspect 网络名
常见坑点记录:
--attachable导致服务无法加入通过实测对比不同存储方案的IOPS表现:
| 方案 | 4K随机读(IOPS) | 顺序写(MB/s) | 适用场景 |
|---|---|---|---|
| 主机SSD绑定挂载 | 98,000 | 520 | 高性能数据库 |
| 数据卷(overlay2) | 45,000 | 210 | 常规应用 |
| 网络存储(NFS) | 12,000 | 110 | 共享存储 |
| tmpfs内存盘 | 280,000 | 1,200 | 临时数据处理 |
优化建议:
bash复制mount -t overlay overlay -o lowerdir=lower,upperdir=upper,workdir=work,index=on merged
调整内核参数提升网络性能(/etc/sysctl.conf):
conf复制net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
容器启动时设置网络参数:
bash复制docker run --sysctl net.ipv4.tcp_keepalive_time=600 ...
我们在某次性能测试中发现,调整这些参数后: