第七篇:《Docker 存储:Volume、Bind Mount 与 tmpfs》

容器默认的文件系统是临时的------容器删除后,其中所有数据都会丢失。对于数据库、日志、配置等需要持久化的数据,Docker 提供了三种存储方式:Volume、Bind Mount 和 tmpfs。本文将详细讲解三者的原理、适用场景以及具体操作方法,帮助你正确管理容器数据。

一、容器存储的临时性问题

Docker 容器的可写层与容器生命周期绑定:

容器运行时,所有对文件系统的修改都写入容器的可写层(位于宿主机 /var/lib/docker/overlay2/...)。

容器被删除时,可写层随之删除,数据永久丢失。

即使使用 docker commit 将容器保存为新镜像,也只能保留当时的状态,不适合频繁变化的数据。

因此,需要独立于容器生命周期的存储方案。

二、Docker 的三种存储挂载类型

三、Volume(卷)

Volume 是 Docker 推荐的持久化方式,由 Docker 完全管理,独立于容器。

3.1 基本操作

bash 复制代码
# 创建卷
docker volume create mydata

# 列出卷
docker volume ls

# 查看卷详情
docker volume inspect mydata

# 删除卷(只有未被任何容器使用才能删除)
docker volume rm mydata

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

3.2 使用卷挂载容器

bash 复制代码
# 运行容器时挂载卷(如果卷不存在,会自动创建)
docker run -d --name db -v mydata:/var/lib/mysql mysql

# 使用 --mount 语法(更显式)
docker run -d --name db --mount source=mydata,target=/var/lib/mysql mysql

# 只读挂载
docker run -d --name web --mount source=config,target=/etc/nginx/conf.d,readonly nginx

3.3 卷的备份与恢复

bash 复制代码
# 备份:启动一个临时容器,挂载源卷和目标目录,打包
docker run --rm -v mydata:/source -v $(pwd):/backup alpine tar czf /backup/mydata-backup.tar.gz -C /source .

# 恢复:创建一个新卷,解压备份文件
docker volume create newdata
docker run --rm -v newdata:/target -v $(pwd):/backup alpine tar xzf /backup/mydata-backup.tar.gz -C /target

3.4 适用场景

数据库(MySQL、PostgreSQL、MongoDB)的数据目录。

应用需要持久化的用户上传文件、日志文件。

需要在多个容器之间共享数据(例如一个卷挂载到多个容器)。

四、Bind Mount(绑定挂载)

Bind Mount 将宿主机上的任意目录或文件挂载到容器中。它依赖宿主机文件系统结构,因此可移植性较差,但在开发环境中非常方便。

4.1 基本用法

bash 复制代码
# 将当前目录挂载到容器的 /app
docker run -d --name dev -v $(pwd):/app node:18

# 使用 --mount 语法(推荐)
docker run -d --name dev --mount type=bind,source="$(pwd)",target=/app node:18

# 只读绑定
docker run -d --name dev --mount type=bind,source="$(pwd)",target=/app,readonly node:18

4.2 开发环境典型用法

在开发 Web 应用时,将代码目录挂载到容器内,修改代码后容器内立即生效(无需重建镜像):

bash 复制代码
# 项目结构
./myapp/
├── index.html
├── app.js
└── Dockerfile

# 启动容器,挂载代码目录
docker run -d -p 3000:3000 -v $(pwd):/app node:18 npm start

4.3 注意事项

路径必须使用绝对路径:$(pwd) 或完整路径。

文件权限:容器内进程的用户 ID 可能与宿主机不同,可能导致权限错误。可以通过 --user 或调整宿主机文件权限解决。

性能:Bind Mount 在 macOS/Windows 下通过文件共享机制(如 VirtioFS、gRPC FUSE)可能比 Volume 慢,但对开发来说影响不大。

五、tmpfs 挂载

tmpfs 将数据存储在内存中,不写入磁盘。容器停止或删除后,tmpfs 中的数据会丢失。

5.1 基本用法

bash 复制代码
# 挂载 tmpfs 到容器的 /tmp
docker run -d --name temp --tmpfs /tmp:rw,noexec,nosuid,size=100m alpine

# 使用 --mount 语法(仅 Linux)
docker run -d --name temp --mount type=tmpfs,destination=/tmp,tmpfs-size=100m alpine

5.2 适用场景

存放临时敏感数据(如 session、密码),避免写入磁盘。

提高频繁读写临时文件的性能(如编译缓存)。

测试环境中需要隔离文件系统但又不想持久化。

六、三种方式对比与选择

选择建议:

生产环境持久化数据 → Volume

开发环境代码热加载 → Bind Mount

临时敏感数据或缓存 → tmpfs

七、实战:MySQL 数据持久化与备份恢复

bash 复制代码
`# 1. 创建数据卷
docker volume create mysql-data

# 2. 启动 MySQL 容器
docker run -d --name mysql \
  -v mysql-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=root \
  mysql:8.0

# 3. 插入测试数据
docker exec -i mysql mysql -uroot -proot <<EOF
CREATE DATABASE test;
USE test;
CREATE TABLE t(id INT);
INSERT INTO t VALUES(1);
EOF

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

# 5. 删除原容器和卷(模拟灾难)
docker stop mysql && docker rm mysql
docker volume rm mysql-data

# 6. 创建新卷并恢复
docker volume create mysql-data-new
docker run --rm -v mysql-data-new:/target -v $(pwd):/backup alpine \
  tar xzf /backup/mysql-backup.tar.gz -C /target

# 7. 启动新容器验证数据
docker run -d --name mysql-new -v mysql-data-new:/var/lib/mysql mysql:8.0
docker exec -it mysql-new mysql -uroot -proot -e "SELECT * FROM test.t`"

八、常见问题与解决

九、小结

本文详细介绍了 Docker 的三种存储方式。Volume 是生产环境持久化的首选;Bind Mount 适合开发调试;tmpfs 用于临时内存数据。理解它们的特性和适用场景,能够帮助你设计出数据可靠、易于管理的容器化应用。

相关推荐
handler0115 小时前
【Linux】五种IO模型详解
linux·运维·服务器·c语言·网络·笔记·php
xingyuzhisuan1 天前
网络 Token 常见故障原理,基础排查科普
运维·服务器·网络·php
APIshop1 天前
Python 获取 1688 商品采集 API 接口 | 工厂货源自动化对接商品信息 | 无需选品
运维·python·自动化
wljy11 天前
二、进制状态转换
linux·运维·服务器·c语言·c++
handler011 天前
【MySQL】常用命令总结(库与表增删查改)
运维·数据库·mysql·命令·总结
week@eight1 天前
Linux - Doris
linux·运维·数据库·mysql
tellmewhoisi1 天前
项目部署docker(指令解析和docker-compose基础指令)
docker·容器
dinl_vin1 天前
FastAPI 系列 ·(十二):生产部署——Docker + 配置管理(系列完结)
docker·容器·fastapi
看到代码头都是大的1 天前
CentOS环境下手动升级openssl、openssh
linux·运维·centos