装好 Docker 引擎只是入门。真正决定一台主机能不能稳定跑生产容器的,是网络、存储和镜像拉取这三件事。这一篇围绕"网络模式 + 存储卷 + 镜像代理 + 常见排障"四个高频主题,把零散的运维笔记整理成可复用的参考。
阅读对象:已经能跑
docker run的开发者、想把 Docker 用于生产环境或本地自建集群的运维同学 覆盖范围:bridge / host / none / container / 自定义网络 + Volume 生命周期 + Docker Hub / ghcr / GCR / k8s / Quay 代理 + 故障排查
一、为什么需要关注网络与存储
跑一个 hello-world 很简单,但一旦要把 Docker 真正"用起来",就会撞到这些问题:
- 容器之间怎么互访?同一个 Pod 里的两个 sidecar 容器能直接
localhost通信吗? - 数据库的数据在容器里,删容器数据就没了——怎么持久化?
- 怎么让外部用户访问容器内的服务?
- 不同机器上的容器怎么互联?
- 国内服务器拉 Docker Hub 镜像慢到秒级超时,K8s 节点拉 CoreDNS 镜像也卡怎么办?
- 私有仓库(
ghcr.io/gcr.io/quay.io)在国内怎么拉?
这些问题的答案,藏在网络模式、Volume、镜像代理三个核心机制里。
When to use:
- 单机多容器互访 → bridge / 自定义网络
- 容器需要"绑定宿主机端口"的高性能场景 → host 网络
- 强隔离、不能联网的安全沙箱 → none 网络
- 数据库、需要长期保存的日志 → Volume(命名卷)/ bind mount
- 跨主机容器互联(Swarm / k8s)→ overlay 网络(本文不展开)
- 国内服务器拉镜像 → 镜像代理(
dockerproxy/ghcr.nju.edu.cn等)
二、容器网络基础:docker0 网桥与 veth pair
Docker 启动时会在宿主机上创建一个叫 docker0 的虚拟网桥(默认子网 172.17.0.0/16)。所有以 bridge 模式启动的容器都会接到这张网桥上,通过这张网桥 + iptables NAT 表与宿主机通信。
可以用 ifconfig(或 ip a)看到 docker0:
| |
核心机制(veth pair):
- 容器内看到的
eth0并不是真正的网卡,而是一对 veth pair 设备的一端 - 另一端放在宿主机,挂到
docker0网桥上 - 数据从一端进,另一端出,等同于一根虚拟网线
可以用 brctl show(来自 bridge-utils 包)查看网桥上挂了哪些 veth:
| |
重要结论:docker0 网桥对外是不可见的,外部网络无法通过 Container-IP 直接访问容器。要让外部访问,必须做端口映射(-p 参数)。
三、四种网络模式详解
Docker 在安装时会自动创建三个网络:bridge(默认)、none、host:
| |
创建容器时通过 --net / --network 指定:
| 模式 | 指定方式 | 核心特点 | 典型场景 |
|---|---|---|---|
| bridge | --net=bridge(默认) | 独立 netns,分配 IP,通过 docker0 + NAT 通信 | 90% 场景 |
| host | --net=host | 共享宿主机 netns,无独立 IP | 高性能网络服务、监控 agent |
| none | --net=none | 仅有 lo 回环,无任何网络 | 强隔离、离线批处理 |
| container | --net=container:NAME | 共享另一个容器的 netns | sidecar 模式紧密协作 |
3.1 bridge 模式(默认)
| |
访问路径:
| |
可以用 iptables -t nat -vnL 看到 Docker 自动添加的 DNAT 规则:
| |
等价类比:bridge 模式 ≈ VMware 里的 NAT 模式——容器有独立 IP、能上网,但需要端口映射才能被外部访问。
3.2 host 模式
容器不创建自己的网卡,直接使用宿主机的 IP 和端口。
| |
优势:
- 没有 NAT 转换,性能最佳
- 适合需要"处理大量端口"的服务(如 nginx 反代、Kafka、Prometheus exporter)
代价:
- 容器与宿主机共用网络栈,端口冲突会直接报错
-p/--publish参数被忽略,会出现WARNING: Published ports are discarded when using host network mode
注意:host 网络驱动只支持 Linux 宿主机。Docker Desktop for Mac / Windows / Windows Server 上的 Docker 不支持 host 模式。
在 Swarm 集群里也可以使用 host 网络:
| |
控制流量(swarm manager 相关)仍走 overlay 网络,但 swarm 服务容器本身使用 Docker 守护进程的主机网络和端口发送数据——这意味着如果一个服务容器绑定到 80 端口,那么在给定的集群节点上只能运行一个该服务容器。
3.3 none 模式
容器有独立的 Network Namespace,但 Docker 不会给它配置任何网络。
- 没有 eth0、没有 IP、没有路由
- 只有
lo回环网卡 - 完全不能上网
典型场景:安全沙箱、离线批处理任务(如敏感数据脱敏、纯计算作业)。
3.4 container 模式
新创建的容器共享指定容器的 netns,而不是和宿主机共享。
| |
特性:
- 两个容器共享 IP、端口范围
- 网络之外(文件系统、进程、用户)仍然隔离
- 两个容器的进程可以通过
lo通信
典型场景:sidecar 模式——主容器和 sidecar 容器(如日志收集器、监控 agent、Service Mesh proxy)共用 netns,方便在 localhost 上互调。
四、自定义网络:指定 IP / 子网
直接用默认 bridge 模式,不能给容器指定固定 IP:
| |
正确做法:先自定义网络,再指定 IP 启动。
| |
参数说明:
--subnet:定义子网范围--opt "com.docker.network.bridge.name"="docker1":让ifconfig -a看到的是docker1,而不是br-110eb56a0b22这种随机名mynetwork:网络名,docker network ls里的NAME列
Why 用自定义网络:
- 容器 DNS 自动解析(容器名 → IP),默认 bridge 不支持
- 可以在创建时规划 IP 段
- 适合需要稳定网络拓扑的复杂部署
配套的清理命令:当自定义网络不再需要时:
| |
注意:手工
brctl delbr docker0之后,下次 daemon 启动(未指定-b参数)会自动重建docker0。要真正控制默认网桥,需要在daemon.json里写:
1 2 3 4{ "iptables": false, "bridge": "" }
五、存储卷(Volume):让数据活过容器生命周期
容器的文件系统是临时的——docker rm 时容器层全部销毁。任何需要持久化的数据,都必须挂载到 Volume 或 bind mount。
5.1 Volume 操作四件套
| |
5.2 两种挂载方式
| |
| 维度 | Volume | Bind Mount |
|---|---|---|
| 路径 | Docker 管理(默认 /var/lib/docker/volumes/) | 任意宿主机路径 |
| 迁移 | docker volume 命令一键迁移 | 手动 rsync |
| 权限 | Docker 自动设 | 手动 chmod |
| 适用 | 数据库、共享数据 | 配置文件、日志、特殊路径 |
5.3 关键避坑
docker volume prune会删所有未挂载的卷——生产环境跑这个命令之前必须docker volume ls确认- bind mount 时容器内 UID 与宿主机不一致会导致权限问题——用
user: "1000:1000"显式指定 - Volume 在多容器间共享非常合适(如配置中心、日志聚合),但不能用 tmpfs 替代——重启数据就没了
5.4 配合清理
| |
六、镜像代理与加速
国内服务器拉 Docker Hub 镜像默认会非常慢甚至超时。除了 daemon.json 里配 registry-mirrors,还可以直接用镜像代理拉特定 registry 的镜像。
6.1 Docker Hub 镜像代理
| 场景 | 官方命令 | 代理命令 |
|---|---|---|
| 用户镜像 | docker pull stilleshan/frpc:latest | docker pull dockerproxy.com/stilleshan/frpc:latest |
| 根镜像(library) | docker pull nginx:latest | docker pull dockerproxy.net/library/nginx:latest |
dockerproxy.com 和 dockerproxy.net 是两个常用的镜像代理。根镜像(library/xxx)必须显式写 library/——这是和用户镜像最大的区别。
6.2 GitHub Container Registry (ghcr.io)
2019 年 9 月 GitHub 即将开放公开测试的 ghcr.io,配合 GitHub Actions 的 docker push 流程,越来越多的开源项目(包括很多 K8s 生态组件)开始把镜像推到 ghcr 而非 Docker Hub。
| |
南京大学的 ghcr 加速:
ghcr.nju.edu.cn是高校里对 ghcr 比较稳定的镜像(南大信管系维护)。速度通常比走 dockerproxy 更快,适合学术 / 教学环境。
6.3 Google Container Registry (gcr.io) 与 k8s.gcr.io
K8s 自身组件(coredns、kube-proxy、etcd 等)都托管在 k8s.gcr.io(2018 年起)或新地址 registry.k8s.io(2019 年开始迁移)。国内拉这些镜像几乎必走代理:
| |
CoreDNS 1.6.5 是 2019 年中比较常用的稳定版本——CNI 插件、KubeDNS 替换等场景都会用到。
6.4 Quay.io
Red Hat 系镜像(coreos/etcd 旧版本、Operator Framework 等)大多托管在 Quay:
| |
6.5 加速效果对比
| |
- 直连 Docker Hub:~1m14s(国内典型)
- 用镜像代理:~5-15s(视镜像大小)
注意:公开镜像代理可能因合规或运营原因失效。生产环境建议自建 mirror(用
registry镜像 + 反代),或者用云厂商(阿里云 ACR、DaoCloud)的企业级加速服务。
七、常见问题与排障
7.1 WARNING: IPv4 forwarding is disabled
容器网络不通,dockerd 启动时打这条警告。生产环境装完 Docker 必须先修这个:
| |
7.2 unknown or invalid runtime name: docker-runc
从老版本(Docker 18.06 之前)升级到 Docker 18.09+ 后,runtime 名从 docker-runc 改为 runc,老容器的 hostconfig.json 还引用老名字,导致容器起不来。
| |
7.3 live-restore:让容器在 daemon 重启时不停机
升级 Docker daemon 或 daemon 崩溃时,默认会停掉所有正在运行的容器。开启 live-restore 可让容器继续运行:
| |
| |
之后 systemctl restart docker 时,容器不会停。
多机同步:在 K8s 集群里,可以用脚本批量同步
daemon.json:
1 2 3 4 5for NODE in master2 master3 worker1 worker3 worker4 worker5 worker6 worker7 worker8 worker9; do echo $NODE scp /etc/docker/daemon.json $NODE:/etc/docker/ ssh root@$NODE "systemctl daemon-reload && systemctl reload docker && systemctl restart docker" done
7.4 network disconnect:容器临时断网
| |
排查网络问题时很有用——能快速判断"是容器问题还是网络问题"。
八、核心要点 / 常见坑
把这一篇的要点压缩成 8 条:
- bridge 模式是默认(90% 场景),host 模式换性能换隔离,none 模式是沙箱
- 端口映射必须用
-p——bridge 模式下不映射外部访问不了 - 容器共享 netns用
container模式,sidecar 利器 - 指定固定 IP必须用自定义网络,默认 bridge 不支持
- 数据持久化用 Volume,
docker volume prune是危险命令 - bind mount vs Volume:配置/日志用 bind mount,数据库用 Volume
- 国内拉镜像必须用代理或 mirror——
dockerproxy系列、ghcr.nju.edu.cn、阿里云、DaoCloud 都要会 - live-restore 是 daemon 升级不停机的关键配置
九、小结
- 网络模式:4 种核心模式(bridge / host / none / container)+ 自定义网络,理解 veth pair 是关键
- 存储卷:Volume 管数据生命周期,bind mount 管配置文件,两手都要硬
- 镜像代理:
dockerproxy系列覆盖 Docker Hub / GCR / k8s.gcr.io / Quay,ghcr.nju.edu.cn补足 ghcr - 排障思路:先看
docker info状态、再看journalctl -u docker日志、最后看 iptables 和 netns
下一步:单机 Docker 玩熟之后,下一步就是 Swarm / Kubernetes 的多机编排——那时网络(overlay / flannel / calico)、存储(Rexray / CSI)、调度(scheduler)都会变成新的核心议题。在 2019 年的 K8s 生态里,CoreDNS 已经取代 kube-dns 成为默认 DNS,
ghcr.io即将开放公开测试,镜像分发的格局正在重写——提前理解这些变化能少踩很多坑。
