编辑
2025-12-28
Docker备份教学
00
请注意,本文编写于 174 天前,最后修改于 48 天前,其中某些信息可能已经过时。

目录

TeslaMate 数据备份及恢复
一句话结论
一、推荐方案:使用 bump 脚本自动备份
1. bump 方案在做什么
2. 备份前要不要停止 TeslaMate
3. 标准备份流程
方案 A:更稳妥,先停应用再备份
方案 B:不停机在线备份
4. 如何确认备份成功
5. 备份时建议顺手保存的内容
二、推荐恢复方案:使用 custom dump 恢复
1. 标准恢复流程
第一步:停止 TeslaMate
第二步:确认 dump 格式
第三步:清理目标库的 public 和 private schema
第四步:执行 custom dump 恢复
第五步:启动 TeslaMate
第六步:查看日志确认启动状态
2. 恢复完成后的检查方法
3. 哪些情况下不建议直接恢复到现有库
三、兼容旧教程:基础命令版备份与恢复
1. 备份
2. 恢复
四、最佳实践建议
五、一句话原则

title: TeslaMate 数据备份及恢复 category: Docker备份教学 updatedAt: 2026-05-03T09:20:00+08:00 createdAt: 2025-12-28T12:41:52.743Z

TeslaMate 数据备份及恢复

TeslaMate 数据备份及恢复

官方文档: Backup and Restore | TeslaMate

这篇文章把我之前博客里的基础备份恢复方法,以及最近实际在用的 bump 备份方案整合到一起。
如果你只是想快速上手,建议优先看前面的 bump 方案;如果你只是单机手动维护,也可以看后面的基础命令版。

一句话结论

  • 目前更推荐使用 PostgreSQL 的 custom format dump,也就是 pg_dump -Fc
  • 恢复时更推荐使用 pg_restore
  • 最稳妥的做法,是备份前先停止 teslamate 应用容器,数据库容器保持运行
  • 恢复前要清理 publicprivate 两个 schema,避免新版本迁移时出现 private.tokens 冲突
  • 如果你更看重不停机,也可以直接在线备份,通常也能正常使用
  • 除了数据库文件,最好把镜像版本、docker-compose.yml.env 一起保存

一、推荐方案:使用 bump 脚本自动备份

这是我现在更推荐的方案,适合长期运行、批量管理、远程自动备份。

1. bump 方案在做什么

bump 目录里的脚本,本质上做的是下面这些事情:

  1. 找到 TeslaMate 的 PostgreSQL 容器
  2. 使用 pg_dump -Fc 生成完整数据库备份
  3. 把备份文件复制到宿主机
  4. 上传到 WebDAV 等远程位置
  5. 多台机器时,可由总控脚本统一分发执行

相比早期直接导出 .bck 文本 SQL,这种方式有几个优点:

  • 同时包含数据库结构和数据
  • 更适合跨机器迁移
  • 更适合完整恢复
  • 恢复时更不容易遗漏对象
  • 更适合长期自动化备份

2. 备份前要不要停止 TeslaMate

建议做法:停止 teslamate 应用容器,再执行备份。

原因:

  • TeslaMate 运行时会持续写入 PostgreSQL
  • 停止应用后,备份结果更稳定
  • 可以减少备份过程中数据变化带来的不一致风险

推荐状态:

  • teslamate 容器:停止
  • postgres 容器:保持运行
  • grafanamosquittowemate:可停可不停

不过如果你不能接受短暂停机,也可以在线备份。pg_dump 本身支持一致性快照导出,所以不停机备份通常也是可用的,只是从运维稳妥性上略弱一些。

我现在的脚本已经支持这两种模式:

  • STOP_TESLAMATE_BEFORE_BACKUP=1:先停应用再备份
  • STOP_TESLAMATE_BEFORE_BACKUP=0:不停机直接在线备份

如果你只是给自己使用,并且更在意不中断服务,可以直接在线备份。
如果你准备给别人做迁移、恢复,或者希望尽量降低恢复翻车概率,还是建议先停应用再备份。

3. 标准备份流程

下面示例假设:

  • PostgreSQL 容器名:teslamate-database-1
  • TeslaMate 容器名:teslamate-teslamate-1
  • 数据库名:teslamate
  • 数据库用户:teslamate
  • 备份文件名:./teslamate.dump

方案 A:更稳妥,先停应用再备份

bash
docker stop teslamate-teslamate-1 docker exec teslamate-database-1 pg_dump -U teslamate -d teslamate -Fc -f /teslamate.dump docker cp teslamate-database-1:/teslamate.dump ./teslamate.dump docker exec teslamate-database-1 rm -f /teslamate.dump docker start teslamate-teslamate-1

方案 B:不停机在线备份

bash
docker exec teslamate-database-1 pg_dump -U teslamate -d teslamate -Fc -f /teslamate.dump docker cp teslamate-database-1:/teslamate.dump ./teslamate.dump docker exec teslamate-database-1 rm -f /teslamate.dump

参数说明:

  • -U teslamate:数据库用户
  • -d teslamate:数据库名
  • -Fc:使用 PostgreSQL 自定义格式导出
  • -f /teslamate.dump:在数据库容器中生成临时备份文件

4. 如何确认备份成功

备份完成后,先看文件是否存在、大小是否正常:

bash
ls -lh ./teslamate.dump

如果还想进一步验证备份结构,可以查看归档内容:

bash
pg_restore -l ./teslamate.dump

如果输出里能看到表、schema、索引等对象,通常说明这个备份文件结构上是有效的。

5. 备份时建议顺手保存的内容

除了数据库备份文件,建议再额外保存:

  • TeslaMate 镜像版本
  • PostgreSQL 镜像版本
  • docker-compose.yml
  • .env 或相关环境变量文件

原因很简单:很多恢复失败,不是备份文件坏了,而是恢复时直接用了不合适的新版本。

查看镜像版本可以用:

bash
docker ps --format 'table {{.Names}}\t{{.Image}}' docker inspect teslamate-teslamate-1 --format '{{.Config.Image}}' docker inspect teslamate-database-1 --format '{{.Config.Image}}'

推荐把这些信息和 teslamate.dump 放在同一个备份目录里。

二、推荐恢复方案:使用 custom dump 恢复

恢复时的核心原则:

  • 尽量恢复到一个全新的 PostgreSQL 数据卷中
  • 恢复时先不要让 TeslaMate 应用运行
  • 尽量先用和备份来源相同或接近的 TeslaMate 版本启动
  • 先确认旧数据恢复成功,再考虑升级到新版本

很多人恢复失败,根本原因不是“不会导入”,而是把下面三种状态混在了一起:

  • 旧备份数据
  • 新版本迁移结果
  • 半初始化状态的数据库结构

所以更稳妥的思路是:先恢复干净数据库,再启动 TeslaMate。

特别注意:新版 TeslaMate 会使用 private schema 存放部分敏感表。如果目标数据库之前已经被新版本启动过,或者迁移失败过,里面可能已经有 private.tokens。这时再恢复旧备份,TeslaMate 启动迁移时会尝试把 public.tokens 移到 private.tokens,然后报错:

text
ERROR 42P07 (duplicate_table) relation "tokens" already exists in schema "private"

解决方法不是改 compose,而是在恢复前明确清空 publicprivate 两个 schema。

1. 标准恢复流程

假设:

  • PostgreSQL 容器已经创建并运行
  • TeslaMate 应用容器先保持停止
  • 你要恢复的文件是 ./teslamate.dump

第一步:停止 TeslaMate

bash
docker stop teslamate-teslamate-1

如果你使用的是 docker compose,也可以这样停:

bash
docker compose stop teslamate grafana docker compose up -d database

第二步:确认 dump 格式

pg_dump -Fc 生成的 custom dump 文件开头通常是 PGDMP

bash
head -c 5 ./teslamate.dump echo

如果输出是 PGDMP,就用 pg_restore。如果输出是 -- 或者能看到 SQL 文本,那是普通 SQL dump,参考后面的“基础命令版恢复”。

第三步:清理目标库的 public 和 private schema

bash
docker exec -i teslamate-database-1 psql -U teslamate -d teslamate <<'SQL' DROP SCHEMA IF EXISTS public CASCADE; DROP SCHEMA IF EXISTS private CASCADE; CREATE SCHEMA public; CREATE EXTENSION IF NOT EXISTS cube WITH SCHEMA public; CREATE EXTENSION IF NOT EXISTS earthdistance WITH SCHEMA public; SQL

如果你使用的是 docker compose 服务名:

bash
docker compose exec -T database psql -U teslamate -d teslamate <<'SQL' DROP SCHEMA IF EXISTS public CASCADE; DROP SCHEMA IF EXISTS private CASCADE; CREATE SCHEMA public; CREATE EXTENSION IF NOT EXISTS cube WITH SCHEMA public; CREATE EXTENSION IF NOT EXISTS earthdistance WITH SCHEMA public; SQL

这一步是为了避免目标库残留新版本创建的 private.tokens,导致恢复后 TeslaMate 迁移失败。

第四步:执行 custom dump 恢复

方式 A:先复制到数据库容器内再恢复:

bash
docker cp ./teslamate.dump teslamate-database-1:/teslamate.dump docker exec teslamate-database-1 pg_restore -U teslamate -d teslamate --clean --if-exists --no-owner --role=teslamate /teslamate.dump docker exec teslamate-database-1 rm -f /teslamate.dump

方式 B:直接从当前目录管道恢复,适合 docker compose

bash
cat ./teslamate.dump | docker compose exec -T database pg_restore -U teslamate -d teslamate --clean --if-exists --no-owner --role=teslamate
  • pg_restore:恢复 pg_dump -Fc 生成的备份
  • --clean:恢复前按备份归档里的对象清理旧对象
  • --if-exists:对象不存在时忽略删除报错
  • --no-owner:不强制恢复原数据库对象 owner,跨机器迁移更稳
  • --role=teslamate:用当前环境里的 teslamate 角色创建对象
  • 前一步手动清理 private,是为了处理旧 dump 里没有 private schema、但目标库已经残留 private.tokens 的情况

第五步:启动 TeslaMate

bash
docker start teslamate-teslamate-1

如果使用 docker compose

bash
docker compose up -d

第六步:查看日志确认启动状态

bash
docker logs -f teslamate-teslamate-1

如果使用 docker compose

bash
docker compose logs -f teslamate

2. 恢复完成后的检查方法

先检查容器是否正常运行:

bash
docker ps

查看 TeslaMate 最近日志:

bash
docker logs --tail 100 teslamate-teslamate-1

如果要进一步检查 PostgreSQL 里的表和迁移记录:

bash
docker exec -it teslamate-database-1 psql -U teslamate -d teslamate

检查表:

sql
SELECT schemaname, tablename FROM pg_tables WHERE schemaname IN ('public', 'private') ORDER BY schemaname, tablename;

检查迁移记录:

sql
SELECT version FROM schema_migrations ORDER BY version;

3. 哪些情况下不建议直接恢复到现有库

以下情况,不建议直接往当前数据库硬导入:

  • 当前数据库已经被新版本 TeslaMate 初始化过
  • 当前数据库已经处于迁移失败状态
  • 你不确定目标库是不是空库
  • 目标环境已经出现 schema 和 migration 不一致的问题

更稳妥的做法是:

  • 删除旧 PostgreSQL 数据卷后重新创建
  • 或者新建一个全新的 PostgreSQL 容器或数据卷
  • 在 TeslaMate 启动前先完成恢复

三、兼容旧教程:基础命令版备份与恢复

如果你只是单机手动操作,也可以继续使用以前这种基础命令方式。
不过要注意,这种 .bck 方式本质是 SQL 文本导出,适合简单场景,不如 pg_dump -Fc 稳妥。

1. 备份

假设你的目录是:

bash
cd /home/pi/teslamate

执行备份:

bash
docker compose exec -T database pg_dump -U teslamate teslamate > ./teslamate.bck

如果当前目录生成了 teslamate.bck,说明备份已完成。

2. 恢复

先停止 TeslaMate:

bash
docker compose stop teslamate docker compose up -d database

重建 schema 和扩展。这里必须同时清理 publicprivate,否则新版本 TeslaMate 可能会因为 private.tokens 已存在而迁移失败:

bash
docker compose exec -T database psql -U teslamate -d teslamate <<'SQL' DROP SCHEMA IF EXISTS public CASCADE; DROP SCHEMA IF EXISTS private CASCADE; CREATE SCHEMA public; CREATE EXTENSION IF NOT EXISTS cube WITH SCHEMA public; CREATE EXTENSION IF NOT EXISTS earthdistance WITH SCHEMA public; SQL

进入备份目录:

bash
cd /home/pi/teslamate

导入备份文件:

bash
docker compose exec -T database psql -U teslamate -d teslamate < teslamate.bck

如果你的文件开头是 PGDMP,说明它不是文本 SQL,而是 pg_dump -Fc 生成的 custom dump。不要用上面的 psql < teslamate.bck,改用:

bash
cat teslamate.bck | docker compose exec -T database pg_restore -U teslamate -d teslamate --clean --if-exists --no-owner --role=teslamate

最后启动 TeslaMate:

bash
docker compose start teslamate

四、最佳实践建议

  • 每次升级 TeslaMate 或 PostgreSQL 前先做一次完整备份
  • 优先使用 pg_dump -Fcpg_restore
  • 尽量不要长期使用 latest 标签
  • 保留多个历史备份,不要总覆盖一个文件
  • 定期做一次恢复演练,不要只备份不验证
  • 如果备份比较旧,恢复后优先先用源版本启动,再考虑升级

五、一句话原则

使用 pg_dump -Fc 备份完整 PostgreSQL 数据库,恢复到干净的数据库环境中,并优先使用与备份来源一致或接近的 TeslaMate 版本启动,整体成功率会高很多。

本文作者:口水

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!