容器重建后数据还在吗?数据卷与目录挂载的使用方法

容器被重新创建时,写在容器可写层里的文件会随旧容器消失;已经挂载的命名卷和宿主机目录由各自的存储位置保存。判断数据是否安全,关键是应用把文件写到了哪里,以及新容器有没有挂回同一处存储。下面用一份测试文本实际验证,不接触正式业务数据。

先分清三种位置

数据位置 容器移除后 检查重点
容器可写层 原容器里的改动会丢失 应用真正的数据路径有没有配置挂载。
命名卷 通常仍保留,可挂给新容器 卷的实际名称、挂载目标,以及是否被单独删除。
宿主机目录挂载 宿主目录仍在 绝对路径、文件权限,以及应用有没有写到该路径。

在 Linux 宿主机上先按Docker安装教程准备环境。以下代码在同一个终端依次执行,变量记录本次实验的目录、卷和辅助镜像。不要把实验路径替换为已有数据库或客户网站目录。

BL_WORK=$(mktemp -d "$HOME/baole-volume-demo.XXXXXX")
BL_VOL=$(basename "$BL_WORK")
printf '实验目录:%s\n实验卷:%s\n' "$BL_WORK" "$BL_VOL"
sudo docker volume create "$BL_VOL"
sudo docker pull alpine:3
BL_TOOL=$(sudo docker image inspect --format '{{index .RepoDigests 0}}' alpine:3)

删除一个容器后,让新容器读同一份文件

sudo docker run --rm \
  --mount "type=volume,source=$BL_VOL,target=/data" \
  "$BL_TOOL" sh -c 'printf "baole-volume-ok\n" > /data/check.txt'

sudo docker run --rm \
  --mount "type=volume,source=$BL_VOL,target=/data,readonly" \
  "$BL_TOOL" cat /data/check.txt

第一个容器写完就被 --rm 删除,第二个是新容器。第二次仍应读到 baole-volume-ok,说明文件来自共同挂载的命名卷,而不是旧容器的可写层。后一个挂载加了 readonly,只允许读取。

把宿主机目录挂进容器

mkdir "$BL_WORK/host-files"
printf 'baole-bind-ok\n' > "$BL_WORK/host-files/check.txt"
sudo docker run --rm \
  --mount "type=bind,source=$BL_WORK/host-files,target=/data,readonly" \
  "$BL_TOOL" cat /data/check.txt

这次应读到 baole-bind-ok,文件实际保存在宿主机的 host-files 目录。使用 --mount 时,源目录不存在会报错,便于发现路径写错。把一个目录挂到容器已有目录上,会遮住该位置原先可见的内容;看到文件突然“不见了”,应先检查挂载,不能直接认定文件已删除。

备份到宿主目录,再恢复到一个新卷

下面备份的是已经停止写入的实验文本。正式数据库应使用适合其版本的一致性备份流程,不能在数据库持续写入时打包整个数据目录,就认为能安全恢复。

mkdir "$BL_WORK/backup"
sudo docker run --rm \
  --mount "type=volume,source=$BL_VOL,target=/source,readonly" \
  --mount "type=bind,source=$BL_WORK/backup,target=/backup" \
  "$BL_TOOL" tar czf /backup/volume.tar.gz -C /source .
sudo tar -tzf "$BL_WORK/backup/volume.tar.gz"

BL_RESTORE="$BL_VOL-restore"
sudo docker volume create "$BL_RESTORE"
sudo docker run --rm \
  --mount "type=volume,source=$BL_RESTORE,target=/target" \
  --mount "type=bind,source=$BL_WORK/backup,target=/backup,readonly" \
  "$BL_TOOL" tar xzf /backup/volume.tar.gz -C /target

sudo docker run --rm \
  --mount "type=volume,source=$BL_VOL,target=/data,readonly" \
  "$BL_TOOL" sha256sum /data/check.txt
sudo docker run --rm \
  --mount "type=volume,source=$BL_RESTORE,target=/data,readonly" \
  "$BL_TOOL" sha256sum /data/check.txt

先确认压缩包能列出 check.txt,再比较原卷和新卷的 SHA256,结果应一致。恢复使用新卷,避免覆盖源数据;正式应用还要核对目录权限,并用应用实际读取、写入和重启后复测。

Compose重建后找不到数据,按这里检查

  • 从 sudo docker ps -a 找到实际容器,再运行 sudo docker inspect --format '{{json .Mounts}}' 容器名,其中“容器名”需要替换;看 Type、Source、Name 和 Destination 是否对应原数据位置。
  • 确认应用真实写入路径等于挂载目标。把卷挂在 /data,并不能保护实际写在 /app/uploads 的文件。
  • Compose 项目名改变时,自动生成的卷名也可能改变。更换工作目录、-p 参数或顶层 name 后,先找到原卷,再决定如何接入,不重复初始化。
  • docker compose down 默认移除该项目的容器和网络;加 -v 会额外删除声明的命名卷等数据资源。日常更新不要把删卷当成固定步骤。
  • 重建后变成空站点时,先保留新旧卷和当前日志。若旧数据卷仍在,问题可能只是挂载错了;如果卷已经删除,就要转向独立备份恢复。

实验结束后,可以核对终端打印的卷名,只删除本次生成的两个实验卷;备份目录按需要保留。不要对整台服务器执行全局清理来结束这次实验。