Docker 存储管理

核心知识点

1. Docker 存储概述

1.1 存储驱动类型

Docker 支持多种存储驱动,适用于不同的文件系统:

┌─────────────────────────────────────────────────────────────┐
│                   Docker 存储驱动                          │
├─────────────────────────────────────────────────────────────┤
│                                                      │
│  overlay2    ──> 推荐驱动,性能好                   │
│  aufs        ──> 旧版驱动,逐渐淘汰                  │
│  btrfs       ──> 支持高级功能,需要特定文件系统       │
│  zfs         ──> 企业级功能,需要特定文件系统          │
│  vfs         ──> 简单但性能差,用于测试             │
│                                                      │
└─────────────────────────────────────────────────────────────┘

1.2 存储方式对比

存储方式 特点 适用场景
数据卷 (Volume) 由 Docker 管理,独立于宿主机 持久化数据、数据共享
绑定挂载 (Bind Mount) 直接挂载宿主机目录 开发环境、配置文件
临时文件系统 (tmpfs) 存储在内存中 临时数据、敏感信息

2. 数据卷管理

2.1 创建数据卷

# 创建命名数据卷
docker volume create my-data

# 创建时指定驱动
docker volume create --driver local my-data

# 查看数据卷列表
docker volume ls

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

# 查看数据卷使用情况
docker volume ls -f dangling=true

2.2 使用数据卷

# 运行容器并挂载数据卷
docker run -d \
    --name my-app \
    -v my-data:/app/data \
    nginx:latest

# 挂载多个数据卷
docker run -d \
    --name my-app \
    -v data1:/app/data1 \
    -v data2:/app/data2 \
    nginx:latest

# 只读挂载数据卷
docker run -d \
    --name my-app \
    -v my-data:/app/data:ro \
    nginx:latest

# 查看容器的挂载信息
docker inspect my-app | grep -A 20 Mounts

2.3 数据卷操作

# 复制数据到数据卷
docker run --rm -v my-data:/target busybox sh -c "echo 'Hello' > /target/file.txt"

# 从数据卷复制数据
docker run --rm -v my-data:/source busybox cat /source/file.txt

# 备份数据卷
docker run --rm -v my-data:/data -v $(pwd):/backup busybox \
    tar czf /backup/my-data-backup.tar.gz -C /data .

# 恢复数据卷
docker run --rm -v my-data:/data -v $(pwd):/backup busybox \
    tar xzf /backup/my-data-backup.tar.gz -C /data

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

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

3. 绑定挂载

3.1 基本绑定挂载

# 挂载宿主机目录
docker run -d \
    --name my-app \
    -v /host/path:/container/path \
    nginx:latest

# 挂载宿主机文件
docker run -d \
    --name my-app \
    -v /host/file.txt:/container/file.txt \
    nginx:latest

# 只读挂载
docker run -d \
    --name my-app \
    -v /host/path:/container/path:ro \
    nginx:latest

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

3.2 高级绑定挂载

# 挂载时指定权限
docker run -d \
    --name my-app \
    -v /host/path:/container/path:rw \
    nginx:latest

# 挂载时指定用户和组
docker run -d \
    --name my-app \
    -v /host/path:/container/path:rw,Z \
    nginx:latest

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

# 只读绑定
docker run -d \
    --name my-app \
    --mount type=bind,source=/host/path,target=/container/path,readonly \
    nginx:latest

4. 临时文件系统

4.1 创建 tmpfs 挂载

# 使用 tmpfs 挂载
docker run -d \
    --name my-app \
    --tmpfs /tmp \
    nginx:latest

# 指定 tmpfs 大小
docker run -d \
    --name my-app \
    --tmpfs /tmp:size=100m \
    nginx:latest

# 指定 tmpfs 权限
docker run -d \
    --name my-app \
    --tmpfs /tmp:rw,exec,size=100m \
    nginx:latest

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

4.2 tmpfs 使用场景

# 存储临时文件
docker run -d \
    --name cache-app \
    --tmpfs /cache:size=500m \
    redis:latest

# 存储敏感信息(不持久化)
docker run -d \
    --name secure-app \
    --tmpfs /secrets:size=10m \
    nginx:latest

# 查看挂载信息
docker inspect cache-app | grep -A 10 Mounts

5. 存储驱动配置

5.1 查看存储驱动

# 查看当前存储驱动
docker info | grep "Storage Driver"

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

# 查看数据目录
docker info | grep "Docker Root Dir"

5.2 配置存储驱动

# 修改 Docker 配置文件
sudo vi /etc/docker/daemon.json

# 添加存储驱动配置
{
    "storage-driver": "overlay2",
    "storage-opts": [
        "overlay2.override_kernel_check=true"
    ]
}

# 重启 Docker 服务
sudo systemctl restart docker

# 验证配置
docker info | grep "Storage Driver"

6. 数据备份与恢复

6.1 备份数据卷

# 方法1:使用 tar 备份
docker run --rm \
    -v my-data:/data \
    -v $(pwd):/backup \
    busybox \
    tar czf /backup/my-data-$(date +%Y%m%d).tar.gz -C /data .

# 方法2:使用 rsync 备份
docker run --rm \
    -v my-data:/data \
    -v $(pwd):/backup \
    alpine \
    sh -c "apk add --no-cache rsync && rsync -av /data/ /backup/"

# 方法3:使用 docker cp 备份
docker run -d --name temp-container -v my-data:/data busybox sleep 1000
docker cp temp-container:/data ./backup
docker rm -f temp-container

6.2 恢复数据卷

# 方法1:使用 tar 恢复
docker run --rm \
    -v my-data:/data \
    -v $(pwd):/backup \
    busybox \
    tar xzf /backup/my-data-20240101.tar.gz -C /data

# 方法2:使用 rsync 恢复
docker run --rm \
    -v my-data:/data \
    -v $(pwd):/backup \
    alpine \
    sh -c "apk add --no-cache rsync && rsync -av /backup/ /data/"

# 方法3:使用 docker cp 恢复
docker run -d --name temp-container -v my-data:/data busybox sleep 1000
docker cp ./backup/. temp-container:/data/
docker rm -f temp-container

7. 存储性能优化

7.1 使用 overlay2 驱动

# 检查是否使用 overlay2
docker info | grep "Storage Driver"

# 如果不是,修改配置
sudo vi /etc/docker/daemon.json

{
    "storage-driver": "overlay2"
}

# 重启 Docker
sudo systemctl restart docker

7.2 优化数据卷性能

# 使用本地 SSD 存储
docker volume create --opt type=tmpfs --opt device=tmpfs --opt o=size=100g my-fast-volume

# 使用特定文件系统
docker volume create --opt type=none --opt device=/dev/sdb1 --opt o=bind my-ssd-volume

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

实用案例分析

案例 1:数据库数据持久化

场景描述

为 MySQL 数据库配置数据持久化,确保数据安全。

操作步骤

# 1. 创建数据卷
docker volume create mysql-data

# 2. 启动 MySQL 容器
docker run -d \
    --name mysql \
    -v mysql-data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=rootpassword \
    -e MYSQL_DATABASE=myapp \
    -p 3306:3306 \
    mysql:5.7

# 3. 等待数据库启动
sleep 20

# 4. 连接数据库并创建测试数据
docker exec -i mysql mysql -uroot -prootpassword myapp << 'EOF'
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    email VARCHAR(100)
);
INSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');
INSERT INTO users (name, email) VALUES ('李四', 'lisi@example.com');
EOF

# 5. 查询数据
docker exec mysql mysql -uroot -prootpassword myapp -e "SELECT * FROM users;"

# 6. 停止并删除容器
docker stop mysql
docker rm mysql

# 7. 重新启动容器(数据仍然存在)
docker run -d \
    --name mysql \
    -v mysql-data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=rootpassword \
    -e MYSQL_DATABASE=myapp \
    -p 3306:3306 \
    mysql:5.7

# 8. 验证数据
docker exec mysql mysql -uroot -prootpassword myapp -e "SELECT * FROM users;"

# 9. 清理
docker stop mysql
docker rm mysql
docker volume rm mysql-data

案例 2:开发环境绑定挂载

场景描述

使用绑定挂载实现代码热重载,提高开发效率。

操作步骤

# 1. 创建项目目录
mkdir ~/my-web-app
cd ~/my-web-app

# 2. 创建 HTML 文件
cat > index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
    <title>我的 Web 应用</title>
</head>
<body>
    <h1>欢迎来到我的 Web 应用</h1>
    <p>这是一个测试页面。</p>
</body>
</html>
EOF

# 3. 启动 Nginx 容器并挂载本地目录
docker run -d \
    --name my-web \
    -p 8080:80 \
    -v $(pwd):/usr/share/nginx/html \
    nginx:alpine

# 4. 测试访问
curl http://localhost:8080

# 5. 修改 HTML 文件
cat > index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
    <title>我的 Web 应用</title>
</head>
<body>
    <h1>欢迎来到我的 Web 应用</h1>
    <p>这是一个测试页面。</p>
    <p>页面已更新!</p>
</body>
</html>
EOF

# 6. 再次测试(无需重启容器)
curl http://localhost:8080

# 7. 查看容器日志
docker logs my-web

# 8. 清理
docker stop my-web
docker rm my-web

案例 3:数据卷备份与恢复

场景描述

实现数据卷的定期备份和快速恢复。

操作步骤

# 1. 创建数据卷并添加数据
docker volume create app-data
docker run --rm -v app-data:/data busybox sh -c "echo '重要数据' > /data/important.txt"

# 2. 创建备份目录
mkdir -p ~/backups

# 3. 备份数据卷
docker run --rm \
    -v app-data:/data \
    -v ~/backups:/backup \
    busybox \
    tar czf /backup/app-data-$(date +%Y%m%d-%H%M%S).tar.gz -C /data .

# 4. 查看备份文件
ls -lh ~/backups

# 5. 模拟数据丢失
docker volume rm app-data

# 6. 从备份恢复
docker run --rm \
    -v app-data:/data \
    -v ~/backups:/backup \
    busybox \
    tar xzf /backup/app-data-$(ls ~/backups | tail -1) -C /data

# 7. 验证恢复的数据
docker run --rm -v app-data:/data busybox cat /data/important.txt

# 8. 清理
docker volume rm app-data
rm -rf ~/backups

最佳实践

  1. 使用数据卷持久化重要数据:避免容器删除后数据丢失。

  2. 合理选择存储方式

    • 数据持久化:使用数据卷
    • 开发环境:使用绑定挂载
    • 临时数据:使用 tmpfs
  3. 定期备份数据卷:确保数据安全。

# 创建备份脚本
cat > ~/backup-volumes.sh << 'EOF'
#!/bin/bash
BACKUP_DIR=~/backups
DATE=$(date +%Y%m%d-%H%M%S)

mkdir -p $BACKUP_DIR

for volume in $(docker volume ls -q); do
    docker run --rm \
        -v $volume:/data \
        -v $BACKUP_DIR:/backup \
        busybox \
        tar czf /backup/${volume}-${DATE}.tar.gz -C /data .
done
EOF

chmod +x ~/backup-volumes.sh

# 设置定时任务
crontab -e
# 添加:0 2 * * * /home/user/backup-volumes.sh
  1. 监控存储使用情况:及时发现存储问题。
# 查看数据卷使用情况
docker system df -v

# 查看磁盘使用情况
df -h

# 查看容器磁盘使用
docker ps -s
  1. 清理未使用的存储资源:释放磁盘空间。
# 清理未使用的数据卷
docker volume prune -f

# 清理未使用的镜像
docker image prune -a -f

# 清理未使用的容器
docker container prune -f

# 清理所有未使用的资源
docker system prune -a -f --volumes

总结

本教程详细介绍了 Docker 的存储管理方法,包括数据卷、绑定挂载、临时文件系统等存储方式。通过实际案例,我们学习了如何持久化数据库数据、实现开发环境热重载以及备份和恢复数据卷。掌握这些技能后,可以有效地管理 Docker 容器的数据存储。

« 上一篇 Docker 网络配置 下一篇 » Docker Compose