找回密码
 立即注册

QQ登录

只需一步,快速开始

peUfSYR.png
查看: 30|回复: 0

Day 06 数据持久化:Docker卷(Volume)完全指南

[复制链接]

876

主题

13

回帖

2808

积分

管理员

积分
2808
发表于 2026-3-29 16:16:40 | 显示全部楼层 |阅读模式
容器删除后数据就丢了?学会Docker卷,让你的数据永久保存!

━━━━━━━━━━━━━━━━━━━━

今天我们要解决一个重要问题:如何让Docker容器中的数据不随容器消失而丢失

你将学会
  • ✅ 理解Docker数据持久化的必要性
  • ✅ 掌握三种数据存储方式及使用场景
  • ✅ 实战管理MySQL、Redis等有状态应用的数据
  • ✅ 备份和迁移Docker卷数据

    难度等级:⭐⭐⭐☆☆(进阶必备)

    所需时间:约 30 分钟

    前置要求
  • 已安装Docker(Day 2)
  • 熟悉基本容器操作(Day 3-5)
  • 了解容器的生命周期

    准备好了吗?让我们开始探索Docker的数据持久化世界!

    ━━━━━━━━━━━━━━━━━━━━

    🤔 为什么需要数据持久化?

    问题场景

    想象一下这个场景:
    1. # 运行一个MySQL容器
    2. docker run -d --name mydb -e MYSQL_ROOT_PASSWORD=123456 mysql:8.0
    3. # 创建数据库和表,插入重要数据
    4. docker exec -it mydb mysql -uroot -p123456 -e "CREATE DATABASE shop;"
    5. docker exec -it mydb mysql -uroot -p123456 -e "USE shop; CREATE TABLE users(id INT, name VARCHAR(50));"
    6. # 不小心删除了容器
    7. docker rm -f mydb
    复制代码

    结果:所有数据都丢失了!

    Docker容器的特性

    Docker容器是临时性的,具有以下特点:

    | 特性 | 说明 | 影响 |
    |------|------|------|
    | 无状态 | 容器删除后内部数据消失 | 数据不持久 |
    | 隔离性 | 容器间文件系统互不影响 | 数据无法共享 |
    | 可替换 | 容器可随时创建和销毁 | 数据易丢失 |

    这就是为什么我们需要数据持久化!

    ━━━━━━━━━━━━━━━━━━━━

    🛠️ 环境准备

    系统要求

    | 项目 | 要求 | 检查方法 |
    |------|------|----------|
    | 操作系统 | macOS / Windows / Linux | - |
    | Docker版本 | 20.10+ |
    1. docker --version
    复制代码
    |
    | 磁盘空间 | 至少 5GB | - |

    检查命令
    1. # 检查Docker版本
    2. docker --version
    3. # 检查Docker是否运行
    4. docker ps
    5. # 查看当前卷列表
    6. docker volume ls
    复制代码

    准备工作目录
    1. # 创建工作目录
    2. mkdir -p ~/docker-practice/day06
    3. cd ~/docker-practice/day06
    复制代码

    ✅ 环境准备完成,开始正式学习!

    ━━━━━━━━━━━━━━━━━━━━

    📖 Docker数据存储方式

    Docker提供了三种主要的数据持久化方式:

    1. Volume(卷)- 推荐方式 ⭐

    特点
  • Docker管理,存储在
    1. /var/lib/docker/volumes/
    复制代码
  • 完全由Docker控制,安全可靠
  • 支持备份、迁移、加密
  • 最佳实践,强烈推荐

    2. Bind Mount(绑定挂载)

    特点
  • 直接映射主机目录
  • 灵活但依赖主机路径
  • 适合开发环境、配置文件

    3. tmpfs(临时文件系统)

    特点
  • 存储在内存中
  • 容器停止数据消失
  • 适合临时数据、敏感信息

    对比图示
    1. ┌─────────────────────────────────────────────────────┐
    2. │                   主机系统                            │
    3. │                                                       │
    4. │  ┌─────────────┐  ┌──────────────┐  ┌───────────┐  │
    5. │  │   Volume    │  │  Bind Mount  │  │   tmpfs   │  │
    6. │  │   (推荐)     │  │   (灵活)      │  │  (临时)    │  │
    7. │  └──────┬──────┘  └──────┬───────┘  └─────┬─────┘  │
    8. │         │                 │                 │         │
    9. │         │                 │                 │         │
    10. │  ┌──────▼─────────────────▼─────────────────▼─────┐ │
    11. │  │              Docker 容器                         │ │
    12. │  │  /var/lib/mysql   /app/config   /tmp/cache     │ │
    13. │  └──────────────────────────────────────────────────┘ │
    14. └─────────────────────────────────────────────────────┘
    复制代码

    ━━━━━━━━━━━━━━━━━━━━

    📖 操作步骤

    第一部分:Volume(卷)实战

    步骤1:创建和查看Volume

    目标:学会创建、查看和管理Docker卷

    创建卷
    1. # 创建一个名为 mydata 的卷
    2. docker volume create mydata
    3. # 查看所有卷
    4. docker volume ls
    复制代码

    预期输出
    1. DRIVER    VOLUME NAME
    2. local     mydata
    复制代码

    查看卷详情
    1. docker volume inspect mydata
    复制代码

    输出示例
    1. [
    2.     {
    3.         "CreatedAt": "2024-01-15T10:30:00Z",
    4.         "Driver": "local",
    5.         "Labels": {},
    6.         "Mountpoint": "/var/lib/docker/volumes/mydata/_data",
    7.         "Name": "mydata",
    8.         "Options": {},
    9.         "Scope": "local"
    10.     }
    11. ]
    复制代码

    关键字段说明
    1. Mountpoint
    复制代码
    :卷在主机上的实际存储位置
    1. Driver
    复制代码
    :存储驱动类型
    1. Name
    复制代码
    :卷名称

    检查点:执行
    1. docker volume ls
    复制代码
    能看到 mydata 卷

    ━━━━━━━━━━━━━━━━━━━━

    步骤2:在容器中使用Volume

    目标:将卷挂载到容器,实现数据持久化

    运行容器并挂载卷
    1. # 运行nginx容器,挂载卷到 /usr/share/nginx/html
    2. docker run -d \
    3.   --name web1 \
    4.   -v mydata:/usr/share/nginx/html \
    5.   -p 8080:80 \
    6.   nginx:alpine
    复制代码

    命令解析
    1. -v mydata:/usr/share/nginx/html
    复制代码
    :将mydata卷挂载到容器的 /usr/share/nginx/html 目录
  • 格式:
    1. 卷名:容器内路径
    复制代码

    向卷中写入数据
    1. # 在容器中创建文件
    2. docker exec web1 sh -c 'echo "<h1>Hello from Volume!</h1>" > /usr/share/nginx/html/index.html'
    复制代码

    验证数据
    1. # 浏览器访问 http://localhost:8080
    2. # 或使用curl
    3. curl http://localhost:8080
    复制代码

    预期输出
    1. <h1>Hello from Volume!</h1>
    复制代码

    检查点:能够访问到我们写入的内容

    ━━━━━━━━━━━━━━━━━━━━

    步骤3:验证数据持久性

    目标:证明卷数据不随容器消失

    删除容器
    1. # 删除容器
    2. docker rm -f web1
    复制代码

    创建新容器,挂载同一个卷
    1. # 运行新容器,使用相同的卷
    2. docker run -d \
    3.   --name web2 \
    4.   -v mydata:/usr/share/nginx/html \
    5.   -p 8080:80 \
    6.   nginx:alpine
    复制代码

    验证数据依然存在
    1. curl http://localhost:8080
    复制代码

    输出
    1. <h1>Hello from Volume!</h1>
    复制代码

    🎉 数据依然存在! 这证明了卷的持久性。

    检查点:删除容器后,新容器仍能访问到之前的数据

    ━━━━━━━━━━━━━━━━━━━━

    步骤4:实战案例 - MySQL数据持久化

    目标:实现MySQL数据库的持久化存储

    创建MySQL专用卷
    1. # 创建卷
    2. docker volume create mysql-data
    复制代码

    运行MySQL容器
    1. docker run -d \
    2.   --name mysql-db \
    3.   -e MYSQL_ROOT_PASSWORD=mypassword \
    4.   -e MYSQL_DATABASE=testdb \
    5.   -v mysql-data:/var/lib/mysql \
    6.   -p 3306:3306 \
    7.   mysql:8.0
    复制代码

    等待MySQL启动
    1. # 查看日志,等待 "ready for connections"
    2. docker logs -f mysql-db
    复制代码

    创建测试数据
    1. # 连接MySQL并创建表
    2. docker exec -it mysql-db mysql -uroot -pmypassword -e "
    3. USE testdb;
    4. CREATE TABLE users (
    5.     id INT AUTO_INCREMENT PRIMARY KEY,
    6.     name VARCHAR(50),
    7.     email VARCHAR(100)
    8. );
    9. INSERT INTO users (name, email) VALUES
    10.     ('张三', 'zhangsan@example.com'),
    11.     ('李四', 'lisi@example.com');
    12. "
    复制代码

    查询数据
    1. docker exec -it mysql-db mysql -uroot -pmypassword -e "
    2. USE testdb;
    3. SELECT * FROM users;
    4. "
    复制代码

    预期输出
    1. +----+--------+------------------------+
    2. | id | name   | email                  |
    3. +----+--------+------------------------+
    4. |  1 | 张三   | zhangsan@example.com   |
    5. |  2 | 李四   | lisi@example.com       |
    6. +----+--------+------------------------+
    复制代码

    重启容器验证
    1. # 删除容器
    2. docker rm -f mysql-db
    3. # 重新创建容器(使用同一个卷)
    4. docker run -d \
    5.   --name mysql-db \
    6.   -e MYSQL_ROOT_PASSWORD=mypassword \
    7.   -v mysql-data:/var/lib/mysql \
    8.   -p 3306:3306 \
    9.   mysql:8.0
    10. # 等待启动后查询数据
    11. sleep 20
    12. docker exec -it mysql-db mysql -uroot -pmypassword -e "
    13. USE testdb;
    14. SELECT * FROM users;
    15. "
    复制代码

    检查点:重启后数据依然存在,说明MySQL数据已持久化

    ━━━━━━━━━━━━━━━━━━━━

    第二部分:Bind Mount(绑定挂载)实战

    步骤5:使用Bind Mount

    目标:映射主机目录到容器

    创建主机目录和文件
    1. # 创建目录
    2. mkdir -p ~/docker-practice/day06/html
    3. # 创建HTML文件
    4. cat > ~/docker-practice/day06/html/index.html << 'EOF'
    5. <!DOCTYPE html>
    6. <html>
    7. <head>
    8.     <meta charset="UTF-8">
    9.     <title>Docker Bind Mount Demo</title>
    10.     <style>
    11.         body {
    12.             font-family: Arial, sans-serif;
    13.             text-align: center;
    14.             padding: 50px;
    15.             background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    16.             color: white;
    17.         }
    18.     </style>
    19. </head>
    20. <body>
    21.     <h1>🚀 这是通过Bind Mount挂载的页面</h1>
    22.     <p>修改主机文件,容器内容会实时更新!</p>
    23. </body>
    24. </html>
    25. EOF
    复制代码

    使用Bind Mount运行容器
    1. # 运行nginx,绑定本地目录
    2. docker run -d \
    3.   --name web-bind \
    4.   -v ~/docker-practice/day06/html:/usr/share/nginx/html \
    5.   -p 8081:80 \
    6.   nginx:alpine
    复制代码

    命令解析
    1. -v ~/docker-practice/day06/html:/usr/share/nginx/html
    复制代码
  • 格式:
    1. 主机绝对路径:容器路径
    复制代码

    访问测试
    1. curl http://localhost:8081
    复制代码

    实时修改测试
    1. # 修改主机文件
    2. echo "<h1>文件已更新 - $(date)</h1>" > ~/docker-practice/day06/html/index.html
    3. # 立即查看效果(无需重启容器)
    4. curl http://localhost:8081
    复制代码

    预期输出
    1. <h1>文件已更新 - Mon Jan 15 14:30:00 CST 2024</h1>
    复制代码

    检查点:修改主机文件后,容器内容实时更新

    常见错误 ⚠️

    错误1:权限被拒绝
    1. Error: Permission denied
    复制代码
    原因:容器内用户权限不足
    解决
    1. # 方法1:修改主机目录权限
    2. chmod -R 755 ~/docker-practice/day06/html
    3. # 方法2:使用--user参数
    4. docker run -d --name web-bind --user $(id -u):$(id -g) -v ...
    复制代码

    ━━━━━━━━━━━━━━━━━━━━

    步骤6:实战案例 - 开发环境配置

    目标:使用Bind Mount实现开发环境的实时同步

    创建项目结构
    1. mkdir -p ~/docker-practice/day06/myapp
    2. cd ~/docker-practice/day06/myapp
    3. # 创建package.json
    4. cat > package.json << 'EOF'
    5. {
    6.   "name": "docker-dev-demo",
    7.   "version": "1.0.0",
    8.   "scripts": {
    9.     "start": "node server.js"
    10.   }
    11. }
    12. EOF
    13. # 创建简单的Node.js服务器
    14. cat > server.js << 'EOF'
    15. const http = require('http');
    16. const fs = require('fs');
    17. const server = http.createServer((req, res) => {
    18.     const html = fs.readFileSync('./index.html', 'utf8');
    19.     res.writeHead(200, {'Content-Type': 'text/html'});
    20.     res.end(html);
    21. });
    22. server.listen(3000, () => {
    23.     console.log('Server running at http://localhost:3000/');
    24. });
    25. EOF
    26. # 创建HTML文件
    27. cat > index.html << 'EOF'
    28. <!DOCTYPE html>
    29. <html>
    30. <head><title>开发环境测试</title></head>
    31. <body>
    32.     <h1>实时开发环境</h1>
    33.     <p>当前时间: <span id="time"></span></p>
    34.     <script>
    35.         document.getElementById('time').textContent = new Date().toLocaleString();
    36.     </script>
    37. </body>
    38. </html>
    39. EOF
    复制代码

    运行开发容器
    1. docker run -d \
    2.   --name dev-container \
    3.   -v ~/docker-practice/day06/myapp:/app \
    4.   -w /app \
    5.   -p 3000:3000 \
    6.   node:18-alpine \
    7.   sh -c "npm start"
    复制代码

    命令解析
    1. -v ~/docker-practice/day06/myapp:/app
    复制代码
    :绑定项目目录
    1. -w /app
    复制代码
    :设置工作目录
    1. sh -c "npm start"
    复制代码
    :启动应用

    访问测试
    1. curl http://localhost:3000
    复制代码

    实时修改代码
    1. # 修改HTML文件
    2. sed -i '' 's/实时开发环境/实时开发环境 - 已更新/g' ~/docker-practice/day06/myapp/index.html
    3. # 刷新页面查看效果
    4. curl http://localhost:3000
    复制代码

    检查点:修改代码后,刷新页面即可看到更新

    ━━━━━━━━━━━━━━━━━━━━

    第三部分:卷管理与高级操作

    步骤7:批量管理卷

    目标:学会批量创建、查看、删除卷

    查看所有卷
    1. docker volume ls
    复制代码

    查看卷占用空间
    1. docker system df -v
    复制代码

    输出示例
    1. VOLUME NAME          LINKS     SIZE
    2. mydata              0         12.5MB
    3. mysql-data          1         180MB
    复制代码

    删除未使用的卷
    1. # 查看未使用的卷
    2. docker volume ls -f dangling=true
    3. # 删除所有未使用的卷(谨慎操作!)
    4. docker volume prune
    5. # 确认删除
    6. # WARNING! This will remove all local volumes not used by at least one container.
    7. # Are you sure you want to continue? [y/N] y
    复制代码

    ⚠️ 警告
    1. docker volume prune
    复制代码
    会删除所有未被容器使用的卷,数据无法恢复!

    安全删除单个卷
    1. # 先停止使用该卷的容器
    2. docker stop web2
    3. docker rm web2
    4. # 删除卷
    5. docker volume rm mydata
    复制代码

    检查点:能够安全地管理和清理卷

    ━━━━━━━━━━━━━━━━━━━━

    步骤8:备份和恢复卷数据

    目标:学会备份和迁移Docker卷数据

    备份卷数据
    1. # 创建备份目录
    2. mkdir -p ~/docker-practice/day06/backups
    3. # 运行临时容器进行备份
    4. docker run --rm \
    5.   -v mysql-data:/source \
    6.   -v ~/docker-practice/day06/backups:/backup \
    7.   alpine \
    8.   tar czf /backup/mysql-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /source .
    复制代码

    命令解析
    1. --rm
    复制代码
    :容器退出后自动删除
    1. -v mysql-data:/source
    复制代码
    :挂载要备份的卷
    1. -v ~/docker-practice/day06/backups:/backup
    复制代码
    :挂载备份目录
    1. tar czf ...
    复制代码
    :打包压缩数据

    验证备份文件
    1. ls -lh ~/docker-practice/day06/backups/
    复制代码

    恢复数据到新卷
    1. # 创建新卷
    2. docker volume create mysql-data-restored
    3. # 恢复数据
    4. docker run --rm \
    5.   -v mysql-data-restored:/target \
    6.   -v ~/docker-practice/day06/backups:/backup \
    7.   alpine \
    8.   sh -c "cd /target && tar xzf /backup/mysql-backup-*.tar.gz"
    复制代码

    验证恢复
    1. # 使用恢复的卷运行MySQL
    2. docker run -d \
    3.   --name mysql-restored \
    4.   -e MYSQL_ROOT_PASSWORD=mypassword \
    5.   -v mysql-data-restored:/var/lib/mysql \
    6.   -p 3307:3306 \
    7.   mysql:8.0
    8. # 等待启动
    9. sleep 20
    10. # 查询数据
    11. docker exec mysql-restored mysql -uroot -pmypassword -e "
    12. USE testdb;
    13. SELECT * FROM users;
    14. "
    复制代码

    检查点:恢复的数据库包含原始数据

    ━━━━━━━━━━━━━━━━━━━━

    步骤9:跨容器共享卷

    目标:多个容器共享同一个卷

    创建共享卷
    1. docker volume create shared-logs
    复制代码

    运行生产者容器
    1. # 容器1:写入日志
    2. docker run -d \
    3.   --name producer \
    4.   -v shared-logs:/logs \
    5.   alpine \
    6.   sh -c 'while true; do echo "Log: $(date)" >> /logs/app.log; sleep 2; done'
    复制代码

    运行消费者容器
    1. # 容器2:读取日志
    2. docker run -d \
    3.   --name consumer \
    4.   -v shared-logs:/logs \
    5.   alpine \
    6.   sh -c 'tail -f /logs/app.log'
    复制代码

    查看日志
    1. # 查看消费者容器输出
    2. docker logs -f consumer
    复制代码

    预期输出
    1. Log: Mon Jan 15 15:30:01 UTC 2024
    2. Log: Mon Jan 15 15:30:03 UTC 2024
    3. Log: Mon Jan 15 15:30:05 UTC 2024
    4. ...
    复制代码

    清理
    1. docker stop producer consumer
    2. docker rm producer consumer
    复制代码

    检查点:多个容器可以同时读写同一个卷

    ━━━━━━━━━━━━━━━━━━━━

    💻 完整示例:WordPress + MySQL

    目标:综合运用卷实现WordPress完整部署

    项目结构
    1. wordpress-project/
    2. ├── docker-compose.yml
    3. └── README.md
    复制代码

    docker-compose.yml
    1. version: '3.8'
    2. services:
    3.   # MySQL数据库
    4.   db:
    5.     image: mysql:8.0
    6.     container_name: wordpress-db
    7.     volumes:
    8.       - db-data:/var/lib/mysql
    9.     environment:
    10.       MYSQL_ROOT_PASSWORD: rootpassword
    11.       MYSQL_DATABASE: wordpress
    12.       MYSQL_USER: wpuser
    13.       MYSQL_PASSWORD: wppassword
    14.     networks:
    15.       - wordpress-net
    16.     restart: unless-stopped
    17.   # WordPress应用
    18.   wordpress:
    19.     image: wordpress:latest
    20.     container_name: wordpress-app
    21.     depends_on:
    22.       - db
    23.     ports:
    24.       - "8888:80"
    25.     volumes:
    26.       - wp-content:/var/www/html/wp-content
    27.     environment:
    28.       WORDPRESS_DB_HOST: db:3306
    29.       WORDPRESS_DB_USER: wpuser
    30.       WORDPRESS_DB_PASSWORD: wppassword
    31.       WORDPRESS_DB_NAME: wordpress
    32.     networks:
    33.       - wordpress-net
    34.     restart: unless-stopped
    35. # 定义卷
    36. volumes:
    37.   db-data:
    38.     name: wordpress-db-data
    39.   wp-content:
    40.     name: wordpress-content
    41. # 定义网络
    42. networks:
    43.   wordpress-net:
    44.     name: wordpress-network
    复制代码

    一键运行脚本
    1. #!/bin/bash
    2. # run-wordpress.sh
    3. echo "🚀 启动WordPress项目..."
    4. # 创建项目目录
    5. mkdir -p wordpress-project
    6. cd wordpress-project
    7. # 创建docker-compose.yml
    8. cat > docker-compose.yml << 'COMPOSE'
    9. version: '3.8'
    10. services:
    11.   db:
    12.     image: mysql:8.0
    13.     container_name: wordpress-db
    14.     volumes:
    15.       - db-data:/var/lib/mysql
    16.     environment:
    17.       MYSQL_ROOT_PASSWORD: rootpassword
    18.       MYSQL_DATABASE: wordpress
    19.       MYSQL_USER: wpuser
    20.       MYSQL_PASSWORD: wppassword
    21.     networks:
    22.       - wordpress-net
    23.     restart: unless-stopped
    24.   wordpress:
    25.     image: wordpress:latest
    26.     container_name: wordpress-app
    27.     depends_on:
    28.       - db
    29.     ports:
    30.       - "8888:80"
    31.     volumes:
    32.       - wp-content:/var/www/html/wp-content
    33.     environment:
    34.       WORDPRESS_DB_HOST: db:3306
    35.       WORDPRESS_DB_USER: wpuser
    36.       WORDPRESS_DB_PASSWORD: wppassword
    37.       WORDPRESS_DB_NAME: wordpress
    38.     networks:
    39.       - wordpress-net
    40.     restart: unless-stopped
    41. volumes:
    42.   db-data:
    43.     name: wordpress-db-data
    44.   wp-content:
    45.     name: wordpress-content
    46. networks:
    47.   wordpress-net:
    48.     name: wordpress-network
    49. COMPOSE
    50. # 启动服务
    51. docker-compose up -d
    52. # 查看状态
    53. docker-compose ps
    54. echo ""
    55. echo "✅ WordPress 已启动!"
    56. echo "🌐 访问 http://localhost:8888 开始配置"
    57. echo ""
    58. echo "📊 查看日志: docker-compose logs -f"
    59. echo "⏹️  停止服务: docker-compose down"
    60. echo "🗑️  删除数据: docker-compose down -v"
    复制代码

    使用方法
    1. chmod +x run-wordpress.sh
    2. ./run-wordpress.sh
    复制代码

    验证部署
    1. # 查看容器状态
    2. docker-compose ps
    3. # 查看卷
    4. docker volume ls | grep wordpress
    5. # 访问WordPress
    6. open http://localhost:8888  # macOS
    7. # 或在浏览器打开 http://localhost:8888
    复制代码

    备份WordPress数据
    1. # 备份数据库
    2. docker exec wordpress-db mysqldump -uwpuser -pwppassword wordpress > wordpress-backup.sql
    3. # 备份文件
    4. docker run --rm \
    5.   -v wordpress-content:/source \
    6.   -v $(pwd):/backup \
    7.   alpine \
    8.   tar czf /backup/wp-content-backup.tar.gz -C /source .
    复制代码

    📦 完整代码仓库:https://github.com/yourusername/docker-30days/tree/main/day06

    ━━━━━━━━━━━━━━━━━━━━

    🚀 进阶实践

    实践1:实现自动化备份

    目标:编写脚本实现每日自动备份Docker卷

    提示
  • 使用cron定时任务
  • 备份文件添加日期戳
  • 保留最近7天的备份
  • 可以考虑压缩和加密

    参考思路
    1. #!/bin/bash
    2. # backup-volumes.sh
    3. BACKUP_DIR="/backups"
    4. RETENTION_DAYS=7
    5. # 备份函数
    6. backup_volume() {
    7.     volume_name=$1
    8.     timestamp=$(date +%Y%m%d-%H%M%S)
    9.     # 你的备份逻辑...
    10. }
    11. # 清理旧备份
    12. cleanup_old_backups() {
    13.     # 删除7天前的备份...
    14. }
    复制代码

    ━━━━━━━━━━━━━━━━━━━━

    实践2:卷性能优化

    目标:对比不同卷驱动的性能差异

    建议
  • 使用
    1. docker run --mount
    复制代码
    测试不同选项
  • 使用
    1. dd
    复制代码
    1. fio
    复制代码
    进行性能测试
  • 记录读写速度对比

    检查清单
  • [ ] 测试Volume的读写性能
  • [ ] 测试Bind Mount的读写性能
  • [ ] 测试tmpfs的读写性能
  • [ ] 对比结果并分析

    ━━━━━━━━━━━━━━━━━━━━

    实践3:跨主机卷迁移

    目标:将Docker卷从一台主机迁移到另一台

    挑战
  • 导出卷数据
  • 传输到目标主机
  • 在目标主机重建卷
  • 验证数据完整性

    资源
  • Docker Volume Plugin文档
  • 数据迁移最佳实践

    💡 提示:完成这些实践后,在评论区分享你的备份脚本或性能测试结果!

    ━━━━━━━━━━━━━━━━━━━━

    🐛 故障排查

    问题1:卷挂载失败

    症状
    1. Error response from daemon: invalid mount config for type "volume"
    复制代码

    原因:卷名称或路径格式错误

    解决方案

    检查卷是否存在
    1. docker volume ls | grep 卷名
    复制代码

    正确的挂载格式
    1. # Volume方式
    2. -v 卷名:/容器路径
    3. # Bind Mount方式(必须是绝对路径)
    4. -v /主机绝对路径:/容器路径
    5. # 错误示例
    6. -v ./relative/path:/container/path  # ❌ 相对路径不行
    7. -v ~/path:/container/path            # ❌ 波浪号可能有问题
    8. # 正确示例
    9. -v $(pwd)/path:/container/path      # ✅ 使用$(pwd)转换为绝对路径
    10. -v /Users/username/path:/container/path  # ✅ 绝对路径
    复制代码

    ━━━━━━━━━━━━━━━━━━━━

    问题2:权限被拒绝

    症状
    1. Permission denied
    复制代码

    原因:容器内进程用户权限不足

    解决方案

    方法1:调整主机目录权限
    1. # 查看目录权限
    2. ls -la /path/to/directory
    3. # 修改权限
    4. chmod -R 755 /path/to/directory
    5. # 或
    6. chmod -R 777 /path/to/directory  # 仅用于测试
    复制代码

    方法2:使用--user参数
    1. docker run -d \
    2.   --user $(id -u):$(id -g) \
    3.   -v /path:/container/path \
    4.   image:tag
    复制代码

    方法3:修改容器内文件所有权
    1. docker exec container-name chown -R www-data:www-data /container/path
    复制代码

    ━━━━━━━━━━━━━━━━━━━━

    问题3:卷数据丢失

    症状:重启容器后数据不见了

    排查步骤

    1. 检查是否正确使用了卷
    1. # 查看容器挂载信息
    2. docker inspect container-name | grep -A 10 Mounts
    复制代码

    2. 确认卷类型
    1. "Mounts": [
    2.     {
    3.         "Type": "volume",  // 应该是 "volume" 不是 "bind"
    4.         "Name": "mydata",
    5.         "Source": "/var/lib/docker/volumes/mydata/_data",
    6.         "Destination": "/data",
    7.         "Driver": "local",
    8.         "RW": true
    9.     }
    10. ]
    复制代码

    3. 检查卷是否被误删
    1. docker volume ls
    复制代码

    预防措施
  • ✅ 使用
    1. docker-compose.yml
    复制代码
    管理卷
  • ✅ 定期备份重要数据
  • ✅ 使用命名卷而非匿名卷
  • ✅ 添加卷标签便于识别

    ━━━━━━━━━━━━━━━━━━━━

    问题4:磁盘空间不足

    症状
    1. no space left on device
    复制代码

    排查
    1. # 查看Docker使用的磁盘空间
    2. docker system df
    3. # 详细信息
    4. docker system df -v
    复制代码

    清理方案
    1. # 清理未使用的卷
    2. docker volume prune
    3. # 清理所有未使用资源
    4. docker system prune -a --volumes
    5. # 删除特定卷
    6. docker volume rm volume-name
    复制代码

    ⚠️ 警告:清理前务必确认数据已备份!

    ━━━━━━━━━━━━━━━━━━━━

    更多问题?

    如果遇到其他问题:
  • 查看 Docker官方文档 - Volumes
  • 搜索 Docker GitHub Issues
  • 在评论区留言,我会及时回复
  • 加入学习群讨论(文末二维码)

    ━━━━━━━━━━━━━━━━━━━━

    📚 知识点回顾

    今天我们深入学习了Docker数据持久化:

    核心命令总结

    | 命令 | 作用 | 示例 |
    |------|------|------|
    |
    1. docker volume create
    复制代码
    | 创建卷 |
    1. docker volume create mydata
    复制代码
    |
    |
    1. docker volume ls
    复制代码
    | 列出所有卷 |
    1. docker volume ls
    复制代码
    |
    |
    1. docker volume inspect
    复制代码
    | 查看卷详情 |
    1. docker volume inspect mydata
    复制代码
    |
    |
    1. docker volume rm
    复制代码
    | 删除卷 |
    1. docker volume rm mydata
    复制代码
    |
    |
    1. docker volume prune
    复制代码
    | 清理未使用的卷 |
    1. docker volume prune
    复制代码
    |
    |
    1. -v
    复制代码
    参数 | 挂载卷 |
    1. -v mydata:/data
    复制代码
    |
    |
    1. --mount
    复制代码
    参数 | 挂载(推荐) |
    1. --mount source=mydata,target=/data
    复制代码
    |

    三种存储方式对比

    | 特性 | Volume | Bind Mount | tmpfs |
    |------|--------|------------|-------|
    | 管理方式 | Docker管理 | 用户管理 | 内存管理 |
    | 存储位置 |
    1. /var/lib/docker/volumes/
    复制代码
    | 自定义路径 | 内存 |
    | 持久性 | ✅ 持久 | ✅ 持久 | ❌ 临时 |
    | 性能 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
    | 共享性 | ✅ 易共享 | ⚠️ 依赖路径 | ❌ 不可共享 |
    | 备份 | ✅ 易备份 | ⚠️ 手动 | ❌ 不可备份 |
    | 适用场景 | 生产环境 | 开发环境 | 临时数据 |

    最佳实践清单

  • 生产环境优先使用Volume:安全可靠,易于管理
  • 使用命名卷:避免匿名卷难以管理
  • 定期备份数据:使用自动化脚本
  • 监控磁盘空间:避免空间不足
  • 使用docker-compose:统一管理卷配置
  • 设置卷标签:便于识别和管理
  • 只读挂载:不需要写入时使用
    1. :ro
    复制代码
  • 权限最小化:避免使用777权限

    关键概念

  • 数据持久化:容器删除后数据依然保留
  • 卷驱动:local、nfs、云存储等不同存储后端
  • 挂载点:容器内访问数据的路径
  • 数据卷容器:专门用于共享数据的容器(已过时,推荐使用Volume)

    下一步学习

    完成今天的实践后,建议:
  • ✅ 实践所有示例代码,理解卷的工作原理
  • ✅ 完成至少一个进阶实践项目
  • ✅ 为你的项目实现数据持久化
  • 📖 学习下一篇:Day 7 - Docker网络详解

    ━━━━━━━━━━━━━━━━━━━━

    💬 作业时间

    今日挑战
  • ✅ 部署WordPress项目,并实现数据持久化
  • ✅ 编写一个自动化备份脚本
  • ✅ 尝试卷的跨容器共享
  • ✅ 测试并对比Volume和Bind Mount的性能差异

    讨论话题
  • 你在项目中如何管理Docker数据持久化?
  • 遇到过哪些数据丢失的坑?如何避免?
  • 对于大规模数据,你会选择什么存储方案?

    在评论区分享你的:
  • 📸 WordPress部署成功截图
  • 💾 备份脚本代码
  • 📊 性能测试结果
  • 💡 实践心得和踩坑经验

    互动奖励 🎁
    精彩分享将获得:
  • 🏆 专属学习徽章
  • 📚 进阶学习资料
  • 👥 学习群优先答疑

    ━━━━━━━━━━━━━━━━━━━━

    📖 系列文章导航

  • Day 1:Docker简介与应用场景
  • Day 2:Docker安装与环境配置
  • Day 3:Docker容器基础操作
  • Day 4:Docker镜像管理
  • Day 5:Dockerfile实战
  • Day 6:数据持久化完全指南 ← 📍 当前
  • Day 7:Docker网络详解(明天发布)
  • Day 8:Docker Compose入门

    📑 查看完整30天学习计划

    ━━━━━━━━━━━━━━━━━━━━

    🎁 学习资源

    本文代码仓库 📦
    1. git clone https://github.com/yourusername/docker-30days.git
    2. cd docker-30days/day06
    复制代码

    配套视频教程 🎬
  • 数据持久化原理讲解
  • WordPress实战演示
  • 备份恢复完整流程

    推荐阅读 📖
  • Docker官方文档 - Volumes
  • Docker官方文档 - Bind Mounts
  • Docker Storage最佳实践

    ━━━━━━━━━━━━━━━━━━━━

    关注公众号 🔔
    回复「Volume」获取:
  • ✅ 完整示例代码
  • ✅ 备份脚本模板
  • ✅ 性能测试工具
  • ✅ 常见问题FAQ

    加入学习社群 👥
    扫描下方二维码,加入「Docker 30天实战」学习群
  • 💬 与500+学员交流
  • 🎯 每日打卡挑战
  • 🏆 优秀作业展示
  • 📚 独家学习资料

    ━━━━━━━━━━━━━━━━━━━━

    下期预告 📢

    Day 7 - Docker网络详解:容器间通信完全指南

    内容抢先看:
  • 🌐 Docker网络模型
  • 🔗 容器互联实战
  • 🛡️ 网络隔离与安全
  • 🚀 跨主机通信方案

    明天见!🎉

    ━━━━━━━━━━━━━━━━━━━━



    ━━━━━━━━━━━━━━━━━━━━

    如果这篇文章对你有帮助,请点个「在看」「转发」,让更多人学到实用的Docker技能! ❤️
  • 您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    扫码关注微信公众号

    Archiver|手机版|小黑屋|风叶林

    GMT+8, 2026-5-8 23:04 , Processed in 0.166684 second(s), 20 queries .

    Powered by 风叶林

    © 2001-2026 Discuz! Team.

    快速回复 返回顶部 返回列表