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:13tmpfs 挂载
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 \
nginxtmpfs 应用场景
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-appDocker 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 网络配置,包括网络模式、自定义网络和服务发现。