← 返回首页

Docker 数据放哪里:命名卷与 bind mount 的实用选择

容器重启后文件还在,不等于部署已经做好持久化。重启通常仍使用同一个容器;删除并重新创建容器则是另一件事。准备部署笔记服务或小型数据库时,应先回答:应用把数据写到哪个路径,这个路径有没有挂载到容器之外?本文使用独立演示数据,命令未在你的环境实测。

三种位置,三个不同责任

容器可写层属于容器自身,删除容器会失去其中的数据。命名卷由 Docker 管理,可以在删除使用它的容器后继续保留;bind mount 则把宿主机指定路径直接映射进容器,适合需要在宿主机编辑的文件。Docker 存储概览。

一个容易执行的选择是:应用自己维护的数据使用命名卷,开发源码和手工配置使用绑定挂载。不是说数据库绝不能使用绑定挂载,而是后者要求你同时照顾宿主路径、权限及迁移方式。也不要把“卷还在”理解成数据绝不会丢失,删除卷、程序误写、磁盘故障仍会影响它。

用一次重建验证命名卷

以下命令面向已安装 Docker 的 Linux 容器环境。首次使用可能下载 Alpine 镜像;先确认网络与磁盘空间,卷名应避免与现有项目重名。

docker volume create persistence_demo
docker run --rm --mount type=volume,src=persistence_demo,dst=/data alpine:3.22 sh -c 'echo hello > /data/note.txt'
docker run --rm --mount type=volume,src=persistence_demo,dst=/data,readonly alpine:3.22 cat /data/note.txt

第一只容器退出后由 --rm 删除,第二只新容器从同一个命名卷读取文件。预期输出为 hello,这才直接检验了数据没有仅停留在第一只容器里。这里使用的是命名卷,不要据此推断匿名卷在所有清理方式下都具有相同保留行为。命名卷生命周期与用法。

需要直接编辑文件时用绑定挂载

在 Linux 或 macOS 的 shell 中,先建立专用演示目录,再只读挂载:

mkdir -p ./mount-demo
printf 'local config\n' > ./mount-demo/settings.txt
docker run --rm --mount type=bind,src="$(pwd)/mount-demo",dst=/config,readonly alpine:3.22 cat /config/settings.txt

如果同名文件已经存在,请换一个全新的演示目录再执行,避免覆盖自己的配置。预期能读取宿主机刚创建的文本。readonly 限制容器通过该挂载写入;需要写入时才移除它,并把范围缩到应用必需的目录,切勿顺手挂载整个个人目录。

这里使用 --mount 是为了让路径错误更明显:源路径不存在时,默认会报错,而不是悄悄生成一个空目录。远程 Docker 的绑定源路径位于守护进程所在机器,并非当前终端所在电脑。绑定挂载说明。

上线前检查实际挂载,而非只看配置

对自己的运行中容器执行:

docker inspect YOUR_CONTAINER --format '{{json .Mounts}}'

将 YOUR_CONTAINER 换成实际名称,检查类型、来源、容器内目标路径及读写状态。然后对照应用文档,确认数据库文件或上传目录确实写入这个目标,而不是看起来相似的另一层目录。

常见误区是挂载覆盖了镜像原有目录,导致原来的文件暂时不可见;这不等于它们被删除。另一个误区是看到权限报错就给目录开放所有权限。应先确认容器运行用户与目录权限,再做最小调整。

最后,更新部署时保留相同卷名与挂载目标。不要为了“清理旧容器”随手执行删除卷的命令。先在演示数据上练习重建,再把同样的检查步骤应用到真实服务,远比只确认容器能启动更可靠。

延伸阅读

持久化不等于独立备份;规划重要数据保护时,可参考3-2-1 备份思路。

写于此,留待再读。