Docker 持久化数据迁移
将现有 Docker 数据安全迁移到当前持久化布局
新版本统一了容器内的持久化布局。Docker 不会自动把已有命名卷的数据复制到新的命名卷,因此,从旧版 Docker 配置升级时需要迁移一次。
迁移会保留 SnowLuma 配置、OneBot 配置、QQ 登录状态和 QQ 本地数据。整个过程不会删除旧数据卷。
开始前
- 保留旧容器,先不要执行
docker compose down或删除容器。 - 不要执行
docker compose down -v,它会删除 Compose 管理的数据卷。 - 迁移时需要停止容器,请预留短暂停机时间。
- 宿主机应留有足够空间,迁移期间新旧数据会同时存在。
1. 确认旧容器
以下命令默认容器名是 snowluma。如果你修改过容器名,请替换第一行。
CONTAINER=snowluma
docker inspect "$CONTAINER" >/dev/null
docker inspect "$CONTAINER" \
--format '{{range .Mounts}}{{printf "%-24s %-8s %s\n" .Destination .Type .Name}}{{end}}'输出中应能看到以下三个容器路径:
/app/snowluma-data
/app/.config
/app/.local/share如果缺少任一路径,请停止迁移并检查原部署配置。
2. 停止容器
停止容器可以避免配置数据库或 QQ 登录数据在复制过程中继续变化。
docker stop "$CONTAINER"不要删除这个容器。后续复制会直接读取它当前挂载的数据,因此不需要猜测 Compose 自动生成的卷名。
3. 创建当前数据卷
docker volume create qq-gateway-data
docker volume create qq-client-config
docker volume create qq-client-data确认三个目标卷都是空的:
docker run --rm \
-v qq-gateway-data:/check/gateway \
-v qq-client-config:/check/config \
-v qq-client-data:/check/share \
alpine:3.21 sh -ec '
for path in /check/gateway /check/config /check/share; do
[ -z "$(ls -A "$path")" ] || {
echo "目标数据卷不是空的:$path" >&2
exit 1
}
done
'如果这里报错,请不要覆盖目标卷。先确认它是否来自之前未完成的迁移。
4. 复制并校验数据
下面的命令以只读方式挂载旧容器的数据卷,将数据复制到当前数据卷,并逐文件校验内容。首次运行可能需要下载体积较小的 alpine 镜像。
docker run --rm \
--volumes-from "${CONTAINER}:ro" \
-v qq-gateway-data:/migration/gateway \
-v qq-client-config:/migration/config \
-v qq-client-data:/migration/share \
alpine:3.21 sh -ec '
copy_tree() {
source_path="$1"
target_path="$2"
label="$3"
[ -d "$source_path" ] || {
echo "缺少源目录:$source_path" >&2
exit 1
}
(cd "$source_path" && tar -cf - .) |
(cd "$target_path" && tar -xpf -)
(cd "$source_path" && find . -type f -exec sha256sum {} \; | sort) > "/tmp/${label}.source"
(cd "$target_path" && find . -type f -exec sha256sum {} \; | sort) > "/tmp/${label}.target"
cmp "/tmp/${label}.source" "/tmp/${label}.target"
echo "已校验:$label"
}
copy_tree /app/snowluma-data /migration/gateway gateway
copy_tree /app/.config /migration/config config
copy_tree /app/.local/share /migration/share share
'命令应依次输出:
已校验:gateway
已校验:config
已校验:share任何一步失败都应停止迁移,不要继续启动新配置。旧数据仍保留在原数据卷中。
5. 更新 Compose 配置
将服务的数据卷挂载改为:
services:
snowluma:
volumes:
- qq-gateway-data:/app/data
- qq-client-config:/app/.config
- qq-client-data:/app/.local/share
volumes:
qq-gateway-data:
name: qq-gateway-data
qq-client-config:
name: qq-client-config
qq-client-data:
name: qq-client-data然后拉取并启动当前镜像:
docker compose pull
docker compose up -d如果使用 docker run,先删除已停止的旧容器,再用相同端口和环境变量重新创建容器,并使用下面三个挂载:
-v qq-gateway-data:/app/data \
-v qq-client-config:/app/.config \
-v qq-client-data:/app/.local/share6. 验证迁移结果
迁移完成后依次确认:
- 容器保持运行,日志中没有持续出现启动错误。
- WebUI 可以使用原凭据登录,原有设置仍然存在。
- QQ 保持原登录状态,不需要重新扫码。
- OneBot 的监听端、令牌和机器人连接均与迁移前一致。
- 实际收发一条测试消息,确认事件接收和消息发送正常。
docker ps --filter "name=${CONTAINER}"
docker logs --tail 100 "$CONTAINER"保留回滚能力
确认服务稳定前,请保留旧容器配置和旧数据卷。需要回滚时,停止当前容器,恢复升级前的 Compose 文件和镜像版本,再重新启动即可。
旧数据卷不会被本流程自动删除。建议至少完成一次容器重启并再次确认登录状态后,再自行决定是否清理。
绑定目录与多账号
使用宿主机目录
如果第一步显示挂载类型为 bind,数据已经位于宿主机目录,不需要复制 Docker 命名卷。保留原宿主机目录,只将应用数据的容器目标从 /app/snowluma-data 改为 /app/data;QQ 的两个目标路径保持不变。
多账号
额外 QQ 账号的挂载路径仍是 /app/qq-acct2、/app/qq-acct3 等。如果希望同时更换这些命名卷,请为每个账号创建独立的新卷,重复第四步的复制与校验流程,并确保一个账号只挂载一个独立的完整 HOME。
这篇文档有帮助吗?
最后更新于