Skip to content

Docker 数据管理

本章将深入讲解 Docker 中的数据管理,包括数据卷、绑定挂载、临时文件系统以及数据持久化策略,帮助你有效管理容器中的数据。

数据管理概述

容器数据的特点

Docker 容器默认是无状态的,容器删除时其内部的数据也会丢失。为了实现数据持久化和共享,Docker 提供了多种数据管理方案:

┌─────────────────────────────────────────────────────────┐
│                    主机文件系统                          │
├─────────────────────────────────────────────────────────┤
│  数据卷        │  绑定挂载      │  tmpfs 挂载          │
│  (Volumes)     │  (Bind Mounts) │  (tmpfs Mounts)      │
│                │                │                      │
│  Docker 管理   │  主机路径      │  内存存储            │
│  可移植性好    │  性能较好      │  临时数据            │
│  安全性高      │  依赖主机      │  容器停止即删除      │
└─────────────────────────────────────────────────────────┘

数据管理方式对比

特性数据卷 (Volumes)绑定挂载 (Bind Mounts)tmpfs 挂载
管理方式Docker 管理用户管理系统管理
存储位置Docker 目录主机任意路径内存
性能最好最好
可移植性不适用
安全性
持久化

数据卷 (Volumes)

数据卷基础操作

bash
# 创建数据卷
docker volume create my-volume

# 列出所有数据卷
docker volume ls

# 查看数据卷详细信息
docker volume inspect my-volume

# 删除数据卷
docker volume rm my-volume

# 删除所有未使用的数据卷
docker volume prune

# 强制删除所有数据卷
docker volume prune -f

使用数据卷

bash
# 在容器中使用数据卷
docker run -d --name web-server -v my-volume:/usr/share/nginx/html nginx

# 使用匿名数据卷
docker run -d --name app -v /app/data nginx

# 多个容器共享数据卷
docker run -d --name app1 -v shared-data:/data nginx
docker run -d --name app2 -v shared-data:/data nginx

# 只读数据卷
docker run -d --name app -v my-volume:/data:ro nginx

# 使用数据卷容器模式
docker create --name data-container -v /data busybox
docker run -d --volumes-from data-container --name app1 nginx
docker run -d --volumes-from data-container --name app2 nginx

数据卷驱动程序

bash
# 使用本地驱动(默认)
docker volume create --driver local my-local-volume

# 使用 NFS 驱动
docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.100,rw \
  --opt device=:/path/to/nfs/share \
  nfs-volume

# 使用 CIFS/SMB 驱动
docker volume create --driver local \
  --opt type=cifs \
  --opt o=username=user,password=pass,uid=1000,gid=1000 \
  --opt device=//192.168.1.100/share \
  cifs-volume

# 查看可用驱动
docker info | grep "Volume:"

数据卷配置选项

bash
# 创建带标签的数据卷
docker volume create --label environment=production --label team=backend my-volume

# 创建带驱动选项的数据卷
docker volume create \
  --driver local \
  --opt type=none \
  --opt o=bind \
  --opt device=/host/path \
  my-bind-volume

# 设置数据卷大小限制(需要支持的存储驱动)
docker volume create \
  --driver local \
  --opt type=tmpfs \
  --opt device=tmpfs \
  --opt o=size=100m \
  tmp-volume

绑定挂载 (Bind Mounts)

基本绑定挂载

bash
# 绑定挂载主机目录
docker run -d --name web -v /host/path:/container/path nginx

# 使用绝对路径
docker run -d --name web -v $(pwd)/html:/usr/share/nginx/html nginx

# 只读绑定挂载
docker run -d --name web -v /host/path:/container/path:ro nginx

# 绑定挂载单个文件
docker run -d --name app -v /host/config.json:/app/config.json nginx

# 使用 --mount 语法(推荐)
docker run -d --name web \
  --mount type=bind,source=/host/path,target=/container/path \
  nginx

绑定挂载选项

bash
# 只读挂载
docker run -d --name app \
  --mount type=bind,source=/host/path,target=/container/path,readonly \
  nginx

# 绑定传播设置
docker run -d --name app \
  --mount type=bind,source=/host/path,target=/container/path,bind-propagation=shared \
  nginx

# 一致性设置(macOS)
docker run -d --name app \
  --mount type=bind,source=/host/path,target=/container/path,consistency=cached \
  nginx

开发环境示例

bash
# Node.js 开发环境
docker run -it --rm \
  --name node-dev \
  -v $(pwd):/workspace \
  -v node_modules:/workspace/node_modules \
  -w /workspace \
  -p 3000:3000 \
  node:16 \
  bash

# Python 开发环境
docker run -it --rm \
  --name python-dev \
  -v $(pwd):/app \
  -w /app \
  -p 8000:8000 \
  python:3.9 \
  bash

# 数据库开发环境
docker run -d \
  --name postgres-dev \
  -v $(pwd)/data:/var/lib/postgresql/data \
  -v $(pwd)/init.sql:/docker-entrypoint-initdb.d/init.sql \
  -e POSTGRES_PASSWORD=password \
  -p 5432:5432 \
  postgres:13

tmpfs 挂载

tmpfs 基础使用

bash
# 创建 tmpfs 挂载
docker run -d --name app --tmpfs /tmp nginx

# 指定 tmpfs 选项
docker run -d --name app \
  --tmpfs /tmp:rw,size=100m,mode=1777 \
  nginx

# 使用 --mount 语法
docker run -d --name app \
  --mount type=tmpfs,destination=/tmp,tmpfs-size=100m \
  nginx

# 多个 tmpfs 挂载
docker run -d --name app \
  --tmpfs /tmp \
  --tmpfs /var/run \
  nginx

tmpfs 应用场景

bash
# 临时文件处理
docker run -d --name processor \
  --tmpfs /tmp:size=1g \
  --tmpfs /var/tmp:size=500m \
  my-data-processor

# 缓存目录
docker run -d --name web-app \
  --tmpfs /app/cache:size=200m \
  --tmpfs /app/sessions:size=100m \
  my-web-app

# 敏感数据处理
docker run -d --name secure-app \
  --tmpfs /secure:noexec,nosuid,size=50m \
  my-secure-app

Docker Compose 中的数据管理

数据卷配置

yaml
version: '3.8'

services:
  web:
    image: nginx
    volumes:
      # 命名数据卷
      - web-content:/usr/share/nginx/html
      # 绑定挂载
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      # 匿名数据卷
      - /var/log/nginx
    
  db:
    image: postgres:13
    volumes:
      # 命名数据卷
      - postgres-data:/var/lib/postgresql/data
      # 初始化脚本
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    environment:
      POSTGRES_PASSWORD: password

  app:
    image: myapp
    volumes:
      # 开发时代码挂载
      - .:/app
      # 防止 node_modules 被覆盖
      - /app/node_modules
    tmpfs:
      # 临时文件
      - /tmp
      - /app/cache

# 定义命名数据卷
volumes:
  web-content:
    driver: local
  postgres-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /host/postgres/data

外部数据卷

yaml
version: '3.8'

services:
  app:
    image: myapp
    volumes:
      - existing-volume:/data

volumes:
  existing-volume:
    external: true
    # 或指定外部数据卷名称
    # external:
    #   name: my-existing-volume

数据卷配置选项

yaml
version: '3.8'

services:
  app:
    image: myapp
    volumes:
      # 长格式配置
      - type: volume
        source: app-data
        target: /data
        read_only: false
        volume:
          nocopy: true
      
      # 绑定挂载长格式
      - type: bind
        source: ./config
        target: /app/config
        read_only: true
        bind:
          propagation: shared
      
      # tmpfs 长格式
      - type: tmpfs
        target: /tmp
        tmpfs:
          size: 100M
          mode: 1777

volumes:
  app-data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=nfs-server,rw
      device: ":/path/to/nfs/share"
    labels:
      - "environment=production"
      - "backup=daily"

数据备份和恢复

数据卷备份

bash
# 备份数据卷到 tar 文件
docker run --rm \
  -v my-volume:/data \
  -v $(pwd):/backup \
  ubuntu \
  tar czf /backup/backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .

# 使用专用备份容器
docker run --rm \
  -v my-volume:/source:ro \
  -v $(pwd):/backup \
  --name backup-container \
  alpine \
  sh -c "cd /source && tar czf /backup/volume-backup.tar.gz ."

# 备份到远程存储
docker run --rm \
  -v my-volume:/data:ro \
  -e AWS_ACCESS_KEY_ID=your-key \
  -e AWS_SECRET_ACCESS_KEY=your-secret \
  amazon/aws-cli \
  s3 sync /data s3://your-bucket/backup/

数据卷恢复

bash
# 从 tar 文件恢复
docker run --rm \
  -v my-volume:/data \
  -v $(pwd):/backup \
  ubuntu \
  tar xzf /backup/backup.tar.gz -C /data

# 从另一个数据卷复制
docker run --rm \
  -v source-volume:/source:ro \
  -v target-volume:/target \
  ubuntu \
  cp -a /source/. /target/

# 从远程存储恢复
docker run --rm \
  -v my-volume:/data \
  -e AWS_ACCESS_KEY_ID=your-key \
  -e AWS_SECRET_ACCESS_KEY=your-secret \
  amazon/aws-cli \
  s3 sync s3://your-bucket/backup/ /data

自动化备份脚本

bash
#!/bin/bash
# backup-volumes.sh

BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d-%H%M%S)

# 获取所有数据卷
VOLUMES=$(docker volume ls -q)

for volume in $VOLUMES; do
    echo "备份数据卷: $volume"
    
    # 创建备份目录
    mkdir -p "$BACKUP_DIR/$volume"
    
    # 备份数据卷
    docker run --rm \
        -v "$volume":/source:ro \
        -v "$BACKUP_DIR/$volume":/backup \
        alpine \
        tar czf "/backup/$volume-$DATE.tar.gz" -C /source .
    
    # 保留最近 7 天的备份
    find "$BACKUP_DIR/$volume" -name "*.tar.gz" -mtime +7 -delete
    
    echo "备份完成: $volume-$DATE.tar.gz"
done

echo "所有数据卷备份完成"

数据同步和迁移

容器间数据同步

bash
# 使用 rsync 同步数据
docker run --rm \
  -v source-volume:/source:ro \
  -v target-volume:/target \
  instrumentisto/rsync \
  rsync -av --delete /source/ /target/

# 实时同步(使用 inotify)
docker run -d \
  -v source-volume:/source:ro \
  -v target-volume:/target \
  --name sync-container \
  alpine \
  sh -c "
    apk add --no-cache inotify-tools rsync
    while inotifywait -r -e modify,create,delete /source; do
      rsync -av --delete /source/ /target/
    done
  "

跨主机数据迁移

bash
# 导出数据卷
docker run --rm \
  -v my-volume:/data:ro \
  alpine \
  tar czf - -C /data . > volume-export.tar.gz

# 传输到目标主机
scp volume-export.tar.gz user@target-host:/tmp/

# 在目标主机导入
docker volume create my-volume
docker run --rm \
  -v my-volume:/data \
  -i alpine \
  tar xzf - -C /data < /tmp/volume-export.tar.gz

性能优化

存储驱动优化

json
// /etc/docker/daemon.json
{
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true",
    "overlay2.size=20G"
  ]
}

数据卷性能调优

bash
# 使用本地 SSD 存储
docker volume create \
  --driver local \
  --opt type=none \
  --opt o=bind \
  --opt device=/ssd/path \
  fast-volume

# 内存文件系统
docker volume create \
  --driver local \
  --opt type=tmpfs \
  --opt device=tmpfs \
  --opt o=size=1G \
  memory-volume

# 网络存储优化
docker volume create \
  --driver local \
  --opt type=nfs \
  --opt o=addr=nfs-server,rw,tcp,hard,intr,timeo=600 \
  --opt device=:/fast/nfs/share \
  nfs-volume

监控存储使用

bash
# 查看 Docker 存储使用情况
docker system df

# 详细查看
docker system df -v

# 查看数据卷使用情况
docker volume ls --format "table {{.Name}}\t{{.Driver}}\t{{.Scope}}"

# 监控脚本
#!/bin/bash
while true; do
    echo "=== Docker 存储使用情况 ==="
    docker system df
    echo ""
    echo "=== 数据卷列表 ==="
    docker volume ls
    echo ""
    sleep 60
done

安全考虑

数据卷安全

bash
# 设置数据卷权限
docker run --rm \
  -v my-volume:/data \
  alpine \
  chown -R 1000:1000 /data

# 加密数据卷
docker volume create \
  --driver local \
  --opt type=ext4 \
  --opt o=loop,encryption=aes256 \
  --opt device=/encrypted/volume/file \
  encrypted-volume

# 只读挂载敏感数据
docker run -d \
  -v /host/secrets:/secrets:ro \
  --security-opt no-new-privileges \
  myapp

访问控制

bash
# 限制容器用户权限
docker run -d \
  --user 1000:1000 \
  -v app-data:/data \
  myapp

# 使用 SELinux 标签
docker run -d \
  --security-opt label:type:container_file_t \
  -v /host/data:/data:Z \
  myapp

# AppArmor 配置
docker run -d \
  --security-opt apparmor:docker-default \
  -v app-data:/data \
  myapp

故障排查

常见问题诊断

bash
# 检查数据卷挂载
docker inspect container_name | grep -A 10 "Mounts"

# 查看数据卷内容
docker run --rm -v my-volume:/data alpine ls -la /data

# 检查权限问题
docker run --rm -v my-volume:/data alpine \
  sh -c "ls -la /data && id"

# 测试读写权限
docker run --rm -v my-volume:/data alpine \
  sh -c "echo 'test' > /data/test.txt && cat /data/test.txt"

# 查看存储驱动信息
docker info | grep -A 20 "Storage Driver"

性能问题排查

bash
# 监控 I/O 性能
docker run --rm -v my-volume:/data alpine \
  sh -c "dd if=/dev/zero of=/data/test bs=1M count=100 oflag=direct"

# 检查磁盘空间
docker run --rm -v my-volume:/data alpine df -h /data

# 查看 inode 使用情况
docker run --rm -v my-volume:/data alpine df -i /data

本章小结

本章全面介绍了 Docker 数据管理的各个方面:

关键要点:

  • 数据卷:Docker 管理的持久化存储,推荐用于生产环境
  • 绑定挂载:直接挂载主机路径,适合开发环境
  • tmpfs 挂载:内存存储,适合临时数据
  • 备份恢复:定期备份重要数据,制定恢复策略
  • 性能优化:选择合适的存储驱动和配置
  • 安全考虑:权限控制和访问限制

最佳实践:

  • 生产环境优先使用数据卷
  • 定期备份重要数据
  • 监控存储使用情况
  • 合理设置权限和安全策略
  • 选择合适的存储驱动

在下一章中,我们将学习 Docker 网络配置,包括网络模式、自定义网络和服务发现。

延伸阅读

本站内容仅供学习和研究使用。