第二部分-Docker核心原理——11. 容器存储原理
11. 容器存储原理1. 容器存储概述容器存储是 Docker 数据持久化的关键。默认情况下容器内的数据是临时的当容器删除时数据也会丢失。Docker 提供了多种存储方案来实现数据持久化和共享。┌─────────────────────────────────────────────────────────────┐ │ Docker 存储架构 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ 容器 │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │ 可写容器层 (Container Layer) │ │ │ │ │ │ - 临时存储容器删除后丢失 │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────┐ │ │ │ │ │ 镜像层 (Image Layers) │ │ │ │ │ │ - 只读共享存储 │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ │ ┌─────────────────┼─────────────────┐ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ Volume │ │ Bind Mount│ │ tmpfs │ │ │ │ 持久卷 │ │ 绑定挂载 │ │ 内存文件 │ │ │ │ │ │ │ │ 系统 │ │ │ │ 数据持久 │ │ 宿主机共享 │ │ 临时存储 │ │ │ └───────────┘ └───────────┘ └───────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘2. Docker 存储类型存储类型存储位置生命周期适用场景容器层/var/lib/docker随容器删除临时数据Volume/var/lib/docker/volumes独立于容器数据库、持久数据Bind Mount宿主机任意路径独立于容器配置共享、开发tmpfs内存随容器删除敏感数据、缓存3. Volume数据卷3.1 基础操作# 创建数据卷dockervolume create myvol# 列出数据卷dockervolumelsdockervolumels-fdanglingtrue# 过滤未使用的# 查看数据卷详情dockervolume inspect myvol# 使用数据卷运行容器dockerrun-d-vmyvol:/app/data--nameapp nginx# 只读挂载dockerrun-d-vmyvol:/app/data:ro nginx# 删除数据卷dockervolumermmyvol# 清理未使用的数据卷dockervolume prunedockervolume prune-f# 删除所有未使用的卷dockervolume prune-a3.2 数据卷类型# 1. 匿名卷Anonymous Volumedockerrun-d-v/app/data nginx# 卷名随机生成不便于管理# 2. 命名卷Named Volumedockervolume create app-datadockerrun-d-vapp-data:/app/data nginx# 3. 主机卷Host Volume# 已废弃使用 bind mount 替代3.3 数据卷驱动# 查看卷驱动dockervolume inspect myvol|grepDriver# 使用本地驱动默认dockervolume create--driverlocalmyvol# 使用 NFS 驱动dockervolume create--driverlocal\--opttypenfs\--optdevice:/path/to/nfs\--optoaddr192.168.1.100,rw,nfsvers4\nfs-volume# 使用第三方驱动如 REX-Ray、Flockerdockervolume create--driverrexray/ebs myvol# 查看支持卷插件的驱动dockerinfo|grepPlugins4. Bind Mount绑定挂载4.1 基础用法# 挂载宿主机目录dockerrun-d-v/host/data:/app/data nginx# 使用 --mount 语法推荐dockerrun-d--mounttypebind,source/host/data,target/app/data nginx# 只读挂载dockerrun-d--mounttypebind,source/host/config,target/app/config,readonly nginx# 挂载单个文件dockerrun-it--mounttypebind,source/host/config.txt,target/app/config.txt alpinesh# 使用 $PWD 相对路径dockerrun-d-v$(pwd)/data:/app/data nginx4.2 权限管理# 指定用户 IDdockerrun-d-v/host/data:/app/data--user1000:1000 nginx# 修改挂载目录权限sudochown-R1000:1000 /host/data# 使用 :Z 标志SELinuxdockerrun-d-v/host/data:/app/data:Z nginx# 使用 :z 标志共享dockerrun-d-v/host/data:/app/data:z nginx5. tmpfs内存文件系统# 使用 tmpfs 挂载dockerrun-d--tmpfs/app/tmp:rw,noexec,nosuid,size100m nginx# 使用 --mount 语法dockerrun-d--mounttypetmpfs,destination/app/tmp,tmpfs-size100m nginx# 查看 tmpfs 使用dockerexeccontainer_namedf-h/app/tmp# 适用场景# - 临时文件# - 缓存数据# - 密钥等敏感信息不写入磁盘6. 数据备份与恢复6.1 备份数据卷# 备份 Volume 到宿主机dockerrun--rm-vmyvol:/source-v$(pwd):/backup alpine\tarczf /backup/myvol-backup.tar.gz-C/source.# 备份使用 bind mount 的容器dockerrun--rm-v/host/data:/source-v$(pwd):/backup alpine\tarczf /backup/data-backup.tar.gz-C/source.# 使用 docker cp不建议用于大数据dockercpcontainer_name:/app/data ./backup/6.2 恢复数据卷# 创建新卷dockervolume create myvol-new# 从备份恢复dockerrun--rm-vmyvol-new:/target-v$(pwd):/backup alpine\tarxzf /backup/myvol-backup.tar.gz-C/target# 验证恢复dockerrun--rm-vmyvol-new:/data alpinels-la/data6.3 容器间数据迁移# 从旧容器复制数据到新卷dockerrun--rm--volumes-from old-container-vnewvol:/target alpine\cp-a/source/data/. /target/# 使用临时容器迁移dockerrun-it--rm-voldvol:/old-vnewvol:/new alpine\sh-ccp -a /old/. /new/7. 数据卷管理最佳实践7.1 命名规范# 推荐命名格式项目-环境-用途-版本# 示例# - myapp-prod-db-data# - myapp-prod-logs# - myapp-dev-config7.2 数据卷标签# 创建带标签的卷dockervolume create\--labelprojectmyapp\--labelenvironmentproduction\--labelbackuptrue\myapp-data# 根据标签过滤dockervolumels--filterlabelprojectmyappdockervolumels--filterlabelbackuptrue7.3 数据卷清理策略# 定期清理未使用的卷cron# 0 2 * * * docker volume prune -f# 清理特定标签的卷dockervolume prune--filterlabeltemptrue# 查找并删除特定模式的卷dockervolumels-q--filternametemp-|xargsdockervolumerm8. 容器存储原理8.1 容器存储位置# Docker 数据根目录dockerinfo|grepDocker Root Dir# /var/lib/docker# 容器数据目录结构ls-la/var/lib/docker/# ├── containers/ # 容器配置和日志# ├── image/ # 镜像元数据# ├── overlay2/ # 镜像层数据# └── volumes/ # 数据卷# 查看容器存储路径CONTAINER_ID$(dockerinspect-f{{.Id}}container_name)ls-la/var/lib/docker/containers/$CONTAINER_ID/8.2 写时复制Copy-on-Write# 验证 CoW 机制# 1. 启动容器dockerrun-it--nametestalpinesh# 2. 容器内创建文件/# echo test data /data.txt/# exit# 3. 查看容器层变化CONTAINER_ID$(dockerinspect-f{{.Id}}test)UPPER_DIR$(dockerinspect-f{{.GraphDriver.Data.UpperDir}}test)ls-la$UPPER_DIR/# 4. 镜像层只读dockerrun-it--rmalpinesh/# touch /test.txt # 这会在容器层不是镜像层9. 数据卷对比特性VolumeBind Mounttmpfs位置Docker 管理任意位置内存持久性是是否容器删除后保留保留删除备份容易容易不需要跨主机需要驱动需要共享存储不支持性能好好最快权限管理自动手动N/A10. 实战演练# 1. 创建 WordPress 数据卷dockervolume create wordpress-dbdockervolume create wordpress-files# 2. 启动 MySQL 容器dockerrun-d\--namemysql\-vwordpress-db:/var/lib/mysql\-eMYSQL_ROOT_PASSWORDroot\-eMYSQL_DATABASEwordpress\mysql:8.0# 3. 启动 WordPress 容器dockerrun-d\--namewordpress\-p8080:80\-vwordpress-files:/var/www/html\--linkmysql:mysql\wordpress:latest# 4. 验证数据持久化dockerstop wordpress mysqldockerstart mysql wordpress# 数据依然存在# 5. 备份数据库卷dockerrun--rm-vwordpress-db:/source-v$(pwd):/backup alpine\tarczf /backup/wordpress-db-backup.tar.gz-C/source.# 6. 清理测试dockerrm-fwordpress mysqldockervolume prune11. 存储驱动配置# /etc/docker/daemon.json{storage-driver:overlay2,storage-opts:[overlay2.override_kernel_checktrue,overlay2.size20G],data-root:/data/docker,exec-root:/data/docker-exec}# 更改 Docker 数据目录sudosystemctl stopdockersudomv/var/lib/docker /data/dockersudoln-s/data/docker /var/lib/dockersudosystemctl startdocker12. 常用命令速查操作命令创建卷docker volume create列出卷docker volume ls查看卷docker volume inspect删除卷docker volume rm清理卷docker volume prune备份卷docker run --rm -v vol:/source -v .:/backup alpine tar czf /backup/backup.tar.gz -C /source .恢复卷docker run --rm -v vol:/target -v .:/backup alpine tar xzf /backup/backup.tar.gz -C /target13. 常见问题Q1: Volume 数据在哪里存储# 默认位置/var/lib/docker/volumes/volume-name/_dataQ2: 如何查看容器使用的卷dockerinspect container_name|grep-A10Mountsdockerinspect-f{{json .Mounts}}container_name|jqQ3: 多个容器可以共享同一个卷吗# 可以使用相同的卷挂载dockerrun-d-vshared-data:/data--nameapp1 nginxdockerrun-d-vshared-data:/data--nameapp2 nginxQ4: 如何迁移 Volume 到另一台主机# 源主机备份dockerrun--rm-vmyvol:/source-v$(pwd):/backup alpine\tarczf /backup/myvol.tar.gz-C/source.# 目标主机恢复dockervolume create myvoldockerrun--rm-vmyvol:/target-v$(pwd):/backup alpine\tarxzf /backup/myvol.tar.gz-C/target14. 小结VolumeDocker 管理数据持久化推荐使用Bind Mount宿主机路径开发调试tmpfs内存存储临时数据容器层数据随容器删除而丢失Volume 独立于容器生命周期支持卷驱动实现远程存储Volume 备份恢复简单高效合理使用标签管理数据卷