1Panel 跨机迁移 PostgreSQL:不要用面板导入
1Panel 自带的「导入数据库」对跨机、单库迁移并不稳:面板走的是 SQL 文本导入,容易撞编码、角色、ACL,也吃不消 -Fc 自定义格式。更可靠的做法是:在源机 docker exec 里 pg_dump,把 dump 文件拷到目标机,再 pg_restore 进空库。stdout / stdin 直接落到当前目录,不用 docker cp。
本文以 Crispy(Payload CMS + PostgreSQL)单库为例,流程适用于任何 1Panel 托管的 PostgreSQL 容器。
先记住三条坑
- 不要加 -t。
docker exec -it会把 TTY 混进管道,破坏-Fc自定义格式的二进制 dump。只用-i。 - 1Panel 容器里通常没有 postgres 角色。
-U必须用该库自己的用户(1Panel 数据库列表里的用户名),不要想当然写成-U postgres。 - 目标机先建空库和用户,再 restore。应用连接串用目标机的用户名和库名,不要沿用源机凭据。
查容器名:
1docker ps --format '{{.Names}}' | grep -i postgres
常见名字类似 1Panel-postgresql-xxxx。
源机导出
在要保存 dump 文件的目录执行:
1docker exec -i 1Panel-postgresql-xxx \2 pg_dump -U 源库用户 -O --no-acl --encoding=UTF8 -Fc 源库名 \3 > crispy.dump
参数含义:
-O/--no-owner:不绑定源机 owner,目标机用户才能顺利接管对象。--no-acl:丢掉源机 ACL,避免 restore 时因角色不存在而失败。-Fc:自定义压缩格式,体积小、可并行 restore,也方便后面用-T跳表。--encoding=UTF8:避免中文内容在跨机时编码漂移。
如果报 role "postgres" does not exist,说明你仍在用 -U postgres。改用该库用户。管理员名也可以从容器环境变量确认:
1docker inspect 1Panel-postgresql-xxx \2 --format '{{range .Config.Env}}{{println .}}{{end}}' | grep POSTGRES_USER
向量表、前台缓存、权限缓存都可以重建,导出时可以跳过以缩小 dump:
1docker exec -i 1Panel-postgresql-xxx \2 pg_dump -U 源库用户 -O --no-acl --encoding=UTF8 -Fc \3 -T content_embeddings -T frontend_cache_entries -T authz_cache \4 源库名 \5 > crispy.dump
把 crispy.dump 拷到目标机(scp 或 1Panel 文件上传均可)。
目标机导入
先在 1Panel 建好空库和用户,再在 dump 所在目录执行:
1docker exec -i 1Panel-postgresql-xxx \2 pg_restore -U 目标库用户 --no-owner --no-acl --if-exists -d 目标库名 \3 < crispy.dump
空库上出现 DROP ... does not exist、role "user_xxx" does not exist 可以忽略——--if-exists 和跨机角色差异都会产生这类噪声。以行数为准,不要以 restore 的 stderr 是否干净为准。
1docker exec -i 1Panel-postgresql-xxx \2 psql -U 目标库用户 -d 目标库名 \3 -c 'SELECT count(*) FROM posts; SELECT count(*) FROM pages; SELECT count(*) FROM media; SELECT count(*) FROM users;'
把核心业务表的行数和源机对一下。对得上,库就算迁完了。
应用侧还要改两处
数据库只是一半。Crispy / Payload 的连接串必须换成目标机用户和库名(DATABASE_URI 或等价环境变量)。生产环境保持 DATABASE_PUSH=false,用 pnpm cli db:migrate 管 schema,不要在新机上对已 restore 的库做 schema push。
媒体文件不在 PostgreSQL 里。本机上传目录需要另拷;若已改走 S3 / 对象存储,确认新机的 bucket 与凭证即可。
pgvector:默认镜像往往没有
1Panel 常用的 PostgreSQL 镜像经常没装 vector 扩展。分两种情况:
不需要语义搜索: .env 设 PGVECTOR_ENABLED=false,应用启动时跳过向量相关逻辑。
需要语义搜索: dump 时用 -T content_embeddings 跳过旧向量;新机装好 pgvector、确认扩展可用后,再重建:
1pnpm cli ai:backfill
不要指望把源机的 content_embeddings 原样 restore 进一台没有 vector 的目标库——扩展不存在时,整次 restore 会卡在这张表上。
小结
面板导入留给同机、小 SQL 文件。跨机单库迁移走这条链路:
- 源机
docker exec -i+pg_dump -Fc(-U用库用户,不要-t) - 拷
*.dump到目标机 - 目标机建空库,
pg_restore --no-owner --no-acl - 用
posts/pages/media/users行数验收 - 改连接串、拷媒体或切 S3;按需处理 pgvector
做完后再启动应用。库是空的、角色对不上、向量扩展缺失,这三件事占了 1Panel 跨机翻车的绝大多数。
暂无评论,来抢沙发吧。