Docker Volume 与网络:数据持久化、容器通信与生产存储策略

详解 Docker 的存储与网络机制:Volume/Bind Mount/tmpfs 三种持久化方案对比、容器间网络通信(bridge/host/overlay)、自定义网络 DNS 发现、生产级存储策略(NFS/云盘)。

Docker 容器默认是无状态的——容器删除后数据即消失。生产环境必须使用持久化存储。本文详解 Docker 的 Volume、Bind Mount、网络模式及生产级存储策略,并深入底层 UnionFS 实现、内核 bind mount 原理、CSI 标准、Swarm Overlay 网络加密、Kubernetes PV/PVC 编排以及容器存储性能基准测试与选型决策矩阵。


一、数据持久化三种方案

方案说明数据位置适用场景
VolumeDocker 管理 named volume/var/lib/docker/volumes/生产首选,跨容器共享
Bind Mount映射宿主机路径任意目录开发环境代码热重载
tmpfs内存挂载宿主机内存敏感数据,不写入磁盘

底层实现原理

Docker 容器的文件系统基于 UnionFS(联合文件系统) 构建。UnionFS 将多个只读层与一个可写顶层叠加,使得容器镜像层共享只读数据,而容器的写操作全部落在上层的可写层(copy-on-write)。当容器被删除时,这个可写层随之销毁,这也是容器默认无状态的根本原因。

Volume 原理:Docker Daemon 通过内核的 mount 系统调用,在 /var/lib/docker/volumes/<name>/_data 处创建一个独立的目录,然后在容器启动时以 bind mount 方式挂载到容器指定路径。由于该目录完全独立于容器的可写层,因此容器删除后数据仍然保留。Docker 通过 Volume Driver 插件机制扩展存储后端。

Bind Mount 原理:直接利用 Linux 内核的 bind mount 特性,将宿主机现有目录或文件挂载到容器的文件系统中。bind mount 本质上是在内核 VFS(Virtual File System)层面创建了一个新的挂载点指向同一个 inode,不经过 Docker 的存储管理层。

tmpfs 原理:基于 Linux tmpfs 文件系统,数据完全驻留在内存和 swap 中,不写入任何持久化块设备。适合存放会话密钥、临时缓存等敏感数据。

# Volume(Docker 管理)
docker volume create my-data
docker run -v my-data:/app/data my-app

# Bind Mount(宿主机目录)
docker run -v /host/data:/app/data:ro my-app      # 只读
docker run -v /host/data:/app/data:Z my-app       # SELinux 私有标签
docker run -v /host/data:/app/data:z my-app       # SELinux 共享标签

# tmpfs(内存,限制 100MB,禁止执行)
docker run --tmpfs /app/cache:size=100m,noexec my-app

性能对比

指标VolumeBind Mounttmpfs
写入延迟中(Docker 管理开销)低(直通宿主机 FS)极低(内存操作)
跨容器共享原生支持需手动管理路径不支持
备份迁移docker volume backup 插件rsync/cp不可持久化
权限隔离良好(命名空间隔离)依赖宿主机权限良好

Volume Driver 扩展

Docker 支持通过 Volume Driver 对接外部存储系统:

# 使用 NFS Volume Driver
docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.100,rw \
  --opt device=:/exports/data \
  nfs-data

# 使用 Ceph RBD Driver(通过 rexray/rbd 插件)
docker volume create --driver rexray/rbd \
  --opt size=20 ceph-volume

二、网络模式

模式说明适用
bridge默认,容器间通过内部 IP 通信单机多容器
host容器直接使用宿主机网络性能敏感
overlay跨主机容器通信Swarm/K8s
none无网络完全隔离

自定义 Bridge 网络详解

默认的 bridge(docker0)网络不附带 DNS 解析能力,容器间只能通过 IP 通信。创建用户自定义 bridge 网络后,Docker 内置的嵌入式 DNS 服务器(监听 127.0.0.11:53)会为同网络容器提供基于容器名的 DNS 发现。

# 创建自定义 bridge 网络,指定子网和网关
docker network create \
  --driver bridge \
  --subnet=172.28.0.0/16 \
  --gateway=172.28.0.1 \
  --opt com.docker.network.bridge.name=br_custom \
  my-net

# 在网络中启动容器
docker run -d --name db --network my-net --ip 172.28.0.10 postgres:15
docker run -d --name api --network my-net my-api

# api 容器内可直接访问 db:5432,底层由 Docker DNS 解析

网络隔离:不同自定义 bridge 网络之间默认二层隔离,容器无法直接通信。如需跨网络通信,需通过端口映射或显式路由。

macvlan / ipvlan 模式

macvlan 允许为容器分配独立的 MAC 地址和 IP,使其直接暴露在物理二层网络中,如同一台真实物理机。适用于需要与物理网络直接集成的场景(如传统监控系统、遗留中间件)。

# 创建 macvlan 网络
docker network create -d macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  -o parent=eth0 \
  macvlan-net

# 启动容器获取独立 IP
docker run --net macvlan-net --ip 192.168.1.100 -d nginx

ipvlan 与 macvlan 类似,但容器共享宿主机的 MAC 地址,通过不同 IP 区分,更适合 MAC 地址受限的数据中心环境。

container 模式

新容器共享另一个容器的网络命名空间(Network Namespace),实现 localhost 直连。

# sidecar 模式:日志采集容器共享应用容器网络
docker run -d --name app my-app
docker run -d --name log-collector --network container:app fluentd

网络排查命令

# 查看网络详情及连接容器
docker network inspect my-net

# 进入容器抓包
docker run --net container:app nicolaka/netshoot tcpdump -i eth0 -w /tmp/capture.pcap

# 验证 DNS 解析
docker run --rm --network my-net nicolaka/netshoot dig db

# 查看容器 iptables 规则
docker run --rm --privileged nicolaka/netshoot iptables -t nat -L -n -v

三、生产存储策略

方案说明
本地 Volume单宿主机,最简单
NFS Volume跨主机共享存储
云盘挂载AWS EBS / 阿里云 ESSD
分布式存储Ceph / Portworx

CSI 标准(Container Storage Interface)

CSI 是由 Kubernetes 社区主导的存储插件标准,旨在解耦容器编排系统与存储后端实现。Docker 本身不原生使用 CSI,但在 Swarm 和通过外部卷插件可对接 CSI 驱动。在 Kubernetes 生态中,CSI 已成为持久化存储的唯一标准接口。

CSI 核心组件包括:

  • CSI Controller:负责卷的创建、删除、附着(Attach)、快照管理等控制面操作。
  • CSI Node:运行在每个工作节点上,负责卷的挂载(Mount)、格式化等数据面操作。

云厂商 CSI 插件对比

云厂商CSI 驱动支持卷类型特性
AWSebs.csi.aws.comgp3/io1/io2IOPS 可配置、加密、快照
AWSefs.csi.aws.comEFS多可用区挂载、NFS 协议
Azuredisk.csi.azure.comStandard/Premium SSD磁盘加密集、共享磁盘
Azurefile.csi.azure.comAzure FilesSMB/NFS 双协议
阿里云diskplugin.csi.alibabacloud.comESSD/SSD/高效云盘多可用区、加密

分布式存储方案

Portworx:专为容器设计的分布式块存储,支持多云环境、细粒度 IO 控制、跨 AZ 复制。

Longhorn: Rancher 开源的轻量级分布式块存储,基于微服务架构,每个卷对应一个独立的控制器和副本集。

Rook:基于 Ceph 的 Kubernetes 云原生存存编排器,通过 Operator 自动化部署 Ceph 集群,提供块存储(RBD)、文件系统(CephFS)和对象存储(RGW)三种接口。


四、Docker Compose 网络与存储编排实战

Docker Compose 通过声明式 YAML 定义多容器应用的网络拓扑和存储依赖。

多网络隔离

version: "3.9"
services:
  frontend:
    image: nginx
    networks:
      - public-net
  api:
    image: my-api
    networks:
      - public-net
      - backend-net
  db:
    image: postgres:15
    networks:
      - backend-net
    volumes:
      - db-data:/var/lib/postgresql/data

networks:
  public-net:
    driver: bridge
  backend-net:
    driver: bridge
    internal: true  # 无外网访问,仅容器间通信

volumes:
  db-data:
    driver: local

Named Volumes 外部化配置

volumes:
  shared-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /mnt/nas/shared

  cache:
    driver: local
    driver_opts:
      type: tmpfs
      device: tmpfs
      o: size=500m,uid=1000

五、Swarm Overlay 网络:加密、负载均衡与服务发现

Docker Swarm 的 Overlay 网络基于 Linux VXLAN 技术,在宿主机之间构建虚拟二层网络,使跨主机容器获得同网段通信能力。

创建加密 Overlay 网络

docker network create \
  --driver overlay \
  --subnet 10.0.9.0/24 \
  --opt encrypted \
  --attachable \
  secure-overlay

--opt encrypted 启用 IPSec 加密,防止跨主机流量被窃听。Swarm 使用 Gossip 协议在各节点间同步网络拓扑信息。

服务发现与负载均衡

Swarm 内置基于虚拟 IP(VIP)的四层负载均衡。创建服务时,Swarm 为该服务分配一个虚拟 IP,并通过 IPVS 在内核层将流量分发到各任务副本。

# 部署三副本 Web 服务
docker service create \
  --name web \
  --network secure-overlay \
  --replicas 3 \
  --publish published=8080,target=80 \
  nginx

# 查看 VIP 和任务分布
docker service inspect web --format='{{json .Endpoint.VirtualIPs}}'

默认负载均衡策略为轮询(Round Robin)。如需会保持,需通过外部反向代理(如 Traefik、Nginx Ingress)实现七层会话粘性。


六、Kubernetes StorageClass / PersistentVolume / PVC 完整 YAML

Kubernetes 将存储抽象为三个层次:StorageClass(存储类,定义后端类型和参数)、PersistentVolume(持久卷,管理员预置或动态供给的存储资源)、PersistentVolumeClaim(持久卷声明,用户申请存储的接口)。

StorageClass 定义

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: ebs.csi.aws.com  # CSI 驱动名称
parameters:
  type: gp3
  iops: "10000"
  throughput: "500"
  encrypted: "true"
  kmsKeyId: alias/aws/ebs
reclaimPolicy: Retain
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
mountOptions:
  - debug

PersistentVolume(静态供给)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv-01
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: ""
  nfs:
    server: 192.168.1.100
    path: /exports/data
    readOnly: false

PersistentVolumeClaim(动态供给)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast-ssd
  resources:
    requests:
      storage: 50Gi

Pod 挂载 PVC

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: app
          image: my-app:latest
          volumeMounts:
            - name: data
              mountPath: /app/data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: app-data-pvc

七、容器存储性能基准测试与选型决策矩阵

存储选型需综合考量 IOPS、吞吐量、延迟、可用性、成本和运维复杂度。

fio 基准测试脚本

# 顺序写吞吐测试
docker run --rm -v test-vol:/data \n  williamyeh/fio --directory=/data \
  --name=seq-write --rw=write --bs=1M --size=1G --numjobs=4 --direct=1

# 随机读 IOPS 测试
docker run --rm -v test-vol:/data \n  williamyeh/fio --directory=/data \
  --name=rand-read --rw=randread --bs=4k --size=1G --numjobs=16 --direct=1 \
  --ioengine=libaio --iodepth=64 --runtime=60

典型场景选型矩阵

场景推荐方案理由
开发环境代码热重载Bind Mount实时同步,零延迟
数据库(MySQL/PostgreSQL)本地 SSD Volume / 云盘低延迟、高 IOPS、数据一致性
海量日志/文件存储NFS / CephFS多节点共享读写、大容量扩展
AI 训练大模型数据集对象存储(S3/OSS)+ 本地缓存低成本、高吞吐、按需加载
有状态微服务多 AZ 部署Portworx / Longhorn跨可用区复制、快照、灾难恢复
缓存/会话存储tmpfs / Redis内存级速度,允许数据丢失

延迟与 IOPS 参考值

存储类型读延迟写延迟随机读 IOPS
tmpfs< 1us< 1us> 1M
NVMe 本地盘~50us~20us~500K
云盘 gp3(AWS)~1ms~1ms~16K(基线)
NFS(千兆网)~5ms~10ms~10K
Ceph RBD(SSD)~2ms~3ms~50K

八、网络与安全:iptables/docker-proxy 原理、用户自定义网桥、网络命名空间

docker-proxy 与 iptables

当使用 docker run -p 8080:80 进行端口映射时,Docker 启动一个 docker-proxy 进程监听宿主机 8080 端口,将流量转发到容器的 80 端口。在 Linux 环境下,Docker 同时通过 iptables 的 DNAT 规则实现内核级转发,效率高于用户态代理。

# 查看 Docker 自动添加的 NAT 规则
sudo iptables -t nat -L DOCKER -n -v

# 典型输出包含:
# DNAT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80

对于用户自定义网桥,Docker 在 FORWARD 链中添加规则控制容器间及容器到外部网络的流量,默认策略为允许。

网络命名空间(Network Namespace)

每个 Docker 容器拥有独立的网络命名空间,包含独立的网络接口、路由表、防火墙规则和套接字。容器eth0 通过 veth pair 与宿主机 vethxxx 连接,veth 的一端在容器命名空间,另一端接在 docker0 或自定义 bridge 上。

# 查看容器网络命名空间中的接口
sudo nsenter -t $(docker inspect -f '{{.State.Pid}}' <container>) -n ip addr

# 查看宿主机侧的 veth 对端
ip link show | grep veth

# 查看容器的路由表
sudo nsenter -t $(docker inspect -f '{{.State.Pid}}' <container>) -n ip route

安全加固建议

  1. 禁用默认 bridge:生产环境废弃 docker0,仅使用用户自定义 bridge 以启用 DNS 发现和网络策略。
  2. 限制容器出站访问:通过 --iptables=false 配合自定义防火墙规则,或利用 Docker Network Policy(与 K8s NetworkPolicy 类似的外部项目)限制东西向流量。
  3. 启用用户命名空间 remapping:dockerd --userns-remap=default 将容器 root 映射到宿主机普通用户,降低容器逃逸后的权限。
  4. 加密 Overlay 网络:跨主机部署时始终使用 --opt encrypted。
# 用户命名空间 remapping 配置(/etc/docker/daemon.json)
{
  "userns-remap": "default"
}

相关阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「saas」更多文章

  1. 短链接对 SEO 的影响与优化最佳实践
  2. UTM 参数 + 短链接:追踪每一条营销链路
  3. 私域流量运营中的短链接策略:从引流到转化