蓝空图床数据迁移

官方网站: https://www.lsky.pro

使用手册: https://docs.lsky.pro

仓库地址: https://github.com/lsky-org/lsky-pro

社区:https://bbs.lskypro.com/

环境说明

  • 使用1Panel部署

  • 软件版本:V 2.1

  • 采用 PostgreSQL 数据库 (不推荐用Mysql,CPU消耗极高)

使用1Panel搭建的应用,可在已安装应用中进入安装目录

image-20240825154738502

相关文件存储目录为:

/opt/1panel/apps/lsky-pro/lsky-pro/data

image-20240825150518860

图片文件路径为

/data/storage/app/uploads

image-20240825154645045

1Panel迁移步骤

可直接使用1Panel提供的应用及数据库备份功能进行备份,导入备份即可,下载下来的压缩包导入时无需解压

需要先创建一个空的数据库,数据库创建好后执行图床安装程序选择刚才创建的数据库

image-20241018000352972

然后本地导入备份,上传云端备份好的数据,点击恢复即可,导入前要确保表结构正确,数据库名最好一致

image-20241018000139079

数据库导入好后再导入应用备份

image-20240827130958922

导入后如下所示

image-20240827134658439

导入后我发现原来的文件并没有导入成功,也不知道是bug还是自己操作有误,登录后能看到预览图,但是点击图片还是原来的网址,改为当前服务ip后提示404,索性直接将备份包解压后上传。

image-20240827142914375

应用还原后注意检查下data/.env文件的数据库配置是否正确,这里我由于源数据库名与目标数据库名不一致,导致导入后无数据,检查后发现数据导入到了目标数据库里,配置的数据库名却是导入过来的源数据库名,所以需要改一下使用的数据库名称。

image-20240827134936473

手动迁移步骤

应用安装好以后将目标容器停止,待数据库迁移完以后再启动。

  1. 备份源数据中的data/storage文件夹和data/public目录下的缩略图文件夹thumbnails

  2. 备份源数据中的data/.env文件和installed.lock文件。

  3. 在目标数据环境中安装好Lsky Pro以及数据库。

  4. 数据库迁移

​ 可以使用Navicat的数据同步功能进行迁移,也可直接执行sql脚本。

image-20240827122505983

选择数据库源及目标

image-20240827122738368

点击比较,对比两个数据库之间的差异

image-20240827123645830

对差异数据选择插入或更新,例如此处我两个环境的超级管理员账号密码不相同,我更新为原来的账号密码

image-20240827123941603

点击下一步,检查sql语句,确认无误后开始执行

image-20240827124130428

执行完成后显示同步结果

image-20240827124224684

数据类型为SQLite时无需部署数据库,备份database.sqlite文件即可。

image-20240827121403484

  1. 修改数据库配置信息

打开备份好的源数据中的.env文件,修改其中数据库的配置信息。注意文件下载下来可能为env不包含点image-20240827124843208

  1. 修改完.env文件后,将先前备份的文件和文件夹一起替换至目标文件和文件夹。
  2. 替换完以后再启功目标容器,打开兰空图床的登录界面,使用原来的用户名和密码进行登录即可。

我使用的策略

由于1Panel直接导入应用可能会失败,至少我是没成功过,但备份数据库的功能还是很方便的,所以我采用使用1Panel导出数据库 + 手动备份文件的策略

下面演示下我将服务从云端迁移至本地的步骤

停止本地服务

手动停止本地蓝空图床服务

image-20241018163854867

图片文件备份与恢复

云端导出文件

1、导出/data/storage目录

选中storage目录 -> 更多 -> 压缩 -> 名称重命名,可以添加备份时的日期

image-20241018164700487

2、导出/data/public/thumbnails目录

经过测试,该目录不备份好像也没有影响

image-20241018165134125

本地恢复文件

直接删除/data/storage目录和/data/public/thumbnails目录

上传备份的压缩包文件到相应目录,解压到当前目录即可

数据库备份与恢复

此处我使用的是 PostgreSQL

云端导出备份

选择使用的数据库 备份列表 -> 备份

image-20241018163940830

本地导入备份

导入前,需要先创建同名数据库

经测试,不删除原数据也可以,导入后数据不会重复插入

如果之间已经恢复过,可以先清空本地数据库所有数据,注意清除时不要用Drop删除表结构,否则导入会失败

1
TRUNCATE TABLE images,users,group_strategy,groups,albums,migrations,personal_access_tokens,failed_jobs,strategies,configs,password_resets;

选择使用的数据库 导入备份 -> 恢复

image-20241018164026720

这样数据库就还原好了

检查数据库配置

如果不是第一次迁移备份数据,下面的操作一般不需要处理

1、检查/data/.env文件

主要修改以下配置

1
2
3
4
5
6
DB_CONNECTION=pgsql
DB_HOST=192.168.10.128
DB_PORT=5432
DB_DATABASE=LskyPro
DB_USERNAME=LskyPro
DB_PASSWORD=xxxxxxxxxxxxx

下面分别时云端和本地的详细配置,可作为参考

云端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
APP_NAME="Lsky Pro"
APP_ENV=prod
APP_KEY=base64:O2fUKAslGK7tgIE/21au94eSvU933La2DPcNENjUON8=
APP_DEBUG=false
APP_URL=http://localhost

LOG_CHANNEL=daily
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=pgsql
DB_HOST=1Panel-postgresql-NbwT
DB_PORT=5432
DB_DATABASE=LskyPro
DB_USERNAME=LskyPro
DB_PASSWORD=xxxxxxxxxxxxx

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=public
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

IGNITION_SHARING_ENABLED=false

本地:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
APP_NAME="Lsky Pro"
APP_ENV=prod
APP_KEY=base64:O2fUKAslGK7tgIE/21au94eSvU933La2DPcNENjUON8=
APP_DEBUG=false
APP_URL=http://localhost

LOG_CHANNEL=daily
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=pgsql
DB_HOST=192.168.10.128
DB_PORT=5432
DB_DATABASE=LskyPro
DB_USERNAME=LskyPro
DB_PASSWORD=xxxxxxxxxxxxx

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=public
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

IGNITION_SHARING_ENABLED=false

2、检查installed.lock文件

此处我的该文件没有数据,文件大小为0B

启动服务并调整配置

如调整存储策略的访问网址

效果展示

上传

数据迁移好之后,如果域名有调整,可以修改下存储策略的访问网址

image-20241018162724780

这样图片上传时返回的访问路径就是最新域名的地址了,例如此处我调整为本地服务ip

image-20241018162910141

预览

所有图片均可正常显示

image-20240827135521294

使用当前IP访问图片

image-20240827143212180

拓展:pgSQL备份迁移

清除数据时需先停止蓝空图床容器,否则会出500错误,若出现此错误重启应用即可

仅数据

可以借助Navicat导出每张表的数据

数据备份

可以批量导出,但是只保存数据,不保存表结构

image-20241017210555004

选中表右键 -> 导出向导

image-20241017205915841

选择要导出的表及导出的位置

image-20241017210039549

选择每张表要导出的字段,默认全选即可

image-20241017210137215

附加选型,默认即可

image-20241017210206381

点击开始按钮开始导出

image-20241017210239303

查看导出结果

image-20241017210308458

一共11张表,对应11个sql文件

image-20241017210359559

数据恢复

由于备份的SQL文件仅有数据,保存的只是一些插入语句,为了避免数据重复或错误,恢复前需要先清空表数据

清空表数据

你可以使用以下 SQL 查询来获取数据库中所有表的名称:

1
2
3
4
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_type = 'BASE TABLE';

你可以将所有表名存储在一个变量中,然后使用 TRUNCATE 命令结合 CASCADE 选项来清空所有表。

1
2
3
4
5
6
7
8
9
10
11
12
13
DO $$
DECLARE
table_name text;
BEGIN
FOR table_name IN
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_type = 'BASE TABLE'
LOOP
EXECUTE 'TRUNCATE TABLE ' || quote_ident(table_name) || ' CASCADE';
END LOOP;
END $$;

以下是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
DO $$
DECLARE
tbl_name text;
BEGIN
FOR tbl_name IN
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_type = 'BASE TABLE'
LOOP
EXECUTE 'TRUNCATE TABLE ' || quote_ident(tbl_name) || ' CASCADE';
END LOOP;
END $$;

注意事项

  • 数据丢失:这个操作会删除所有表中的数据,请确保你确实需要这样做。
  • 权限:执行这个操作需要足够的权限。
  • 触发器TRUNCATE 命令不会触发 DELETE 触发器,因此如果你依赖这些触发器来执行某些操作,请注意这一点。

导入数据

在表上右键 -> 运行SQL文件

image-20241017205703980

执行时有一定顺序要求,因为受到外键约束,需要先导致外键的数据,不然可能会出错

image-20241017205334166

导入时可按照下面的顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

SELECT * FROM groups; -- 用户组

SELECT * FROM strategies; -- 存储策略

SELECT * FROM group_strategy;

SELECT * FROM users; -- 用户

SELECT * FROM configs; -- 配置信息

SELECT * FROM migrations;

SELECT * FROM personal_access_tokens; -- token信息

SELECT * FROM images; -- 数据最多,存储的是图片信息

SELECT * FROM password_resets;

SELECT * FROM failed_jobs;

SELECT * FROM albums;

检查数据

以下是一个 PL/pgSQL 代码块,用于查询所有表的名称以及每个表中的数据量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DO $$
DECLARE
tbl_name text;
row_count bigint;
BEGIN
FOR tbl_name IN
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_type = 'BASE TABLE'
LOOP
EXECUTE 'SELECT COUNT(*) FROM ' || quote_ident(tbl_name) INTO row_count;
RAISE NOTICE 'Table: %, Row Count: %', tbl_name, row_count;
END LOOP;
END $$;

执行效果如下:
image-20241017205424043

数据和结构

导出数据时,也可以选择转储数据和结构,但Navicat不支持批量导出操作

数据备份

选中要导出的表右键 -> 转储SQL文件 -> 结构和数据,选择保存位置保存即可

image-20241017214114332

这样操作导出的数据是包含表结构信息的

image-20241017214803212

数据恢复

但是由于表之间的依赖问题,删除表时可能会出错

image-20241017224353966

所以仍需先删除以下表

1
DROP TABLE images,users,group_strategy,groups,albums,migrations,personal_access_tokens,failed_jobs 

另外,由于创建表时nextval 函数用于获取序列的下一个值,所以我们还需需要创建所需的序列

image-20241017224556692

创建语句如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE SEQUENCE users_id_seq;

CREATE SEQUENCE groups_id_seq;

CREATE SEQUENCE strategies_id_seq;

CREATE SEQUENCE migrations_id_seq;

CREATE SEQUENCE personal_access_tokens_id_seq;

CREATE SEQUENCE albums_id_seq;

CREATE SEQUENCE images_id_seq;

CREATE SEQUENCE failed_jobs_id_seq;

最后,由于表之间的依赖关系,仍需按照如下顺序导入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT * FROM groups; -- 用户组

SELECT * FROM strategies; -- 存储策略

SELECT * FROM group_strategy;

SELECT * FROM users; -- 用户

SELECT * FROM configs; -- 配置信息

SELECT * FROM migrations;

SELECT * FROM personal_access_tokens; -- token信息

SELECT * FROM albums;

SELECT * FROM images; -- 数据最多,存储的是图片信息

SELECT * FROM password_resets;

SELECT * FROM failed_jobs;

选中表右键 -> 运行SQL文件,选择

image-20241017215123327

选择要执行的文件,点击开始即可

image-20241017215419886

借助pg_dump工具

pg_dump 是 PostgreSQL 自带的一个命令行工具,可以帮助我们备份和恢复数据库。

数据备份

查看目录映

然后,我们需要知道postgresql的Docker容器和Linux主机的目录映射关系

image-20241017225524719

可以看到,默认情况下通过 1Panel 安装的 postgresql挂载的本机目录为

1
/opt/1panel/apps/postgresql/postgresql/data

容器目录为:

1
/var/lib/postgresql/data

导出数据

1、查看postgresql容器名

可以直接通过1Panel查看

image-20241017230232979

也可以通过docker ps 命令

1
2
3
4
5
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
032d6380f22c postgres:16.4-alpine "docker-entrypoint.s…" 7 weeks ago Up 4 hours (healthy) 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp 1Panel-postgresql-urmB
cbd06c58fe8f mysql:8.4.2 "docker-entrypoint.s…" 7 weeks ago Up 4 hours 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp 1Panel-mysql-m6wQ
fa06851b2b21 1panel/openresty:1.21.4.3-3-3-focal "/usr/local/openrest…" 7 weeks ago Up 4 hours 1Panel-openresty-WhD9

可以看到此处我的postgresql容器名为 1Panel-postgresql-urmB

2、进入docker容器内部

使用下面的命令进入容器内部

1
docker exec -it <container_id/container_name> /bin/bash

例如此处我的为

1
docker exec -it 1Panel-postgresql-urmB /bin/bash

切换到与主机挂载的目录内

1
cd /var/lib/postgresql/data

使用 ls -l 查看当前目录内文件

image-20241017231212475

可以和1Panel目录对比下,两者是一致的,这样,我们导出的SQL文件就可以通过1Panel直接下载了

image-20241017231150905

3、导出数据

可以使用下面的命令导出数据

1
pg_dump -U your_username -d your_database_name -f backup_file.sql
  • -U your_username: 指定数据库用户名。
  • -d your_database_name: 指定要备份的数据库名称。
  • -f backup_file.sql: 指定输出文件名。

例如此处,我的用户名为 LskyPro, 要导出的数据库为LskyPro,指定导出的文件名为LskyPro_backup.sql

1
pg_dump -U LskyPro -d LskyPro -f LskyPro_backup.sql

导出文件后,我们可以直接在1Panel面板内下载

image-20241017231650207

备份特定表

如果你只想备份特定的表,可以使用 -t 选项:

1
pg_dump -U your_username -d your_database_name -t your_table_name -f backup_file.sql

假设你要备份 mydatabase 数据库中的 users 表,可以使用以下命令:

1
pg_dump -U postgres -d mydatabase -t users -f users_backup.sql

备份到压缩文件

你可以将备份文件压缩以节省空间,使用 -Fc 选项来生成压缩的备份文件:

1
pg_dump -U your_username -d your_database_name -Fc -f backup_file.dump

假设你要备份 mydatabase 数据库并生成压缩文件 mydatabase_backup.dump,可以使用以下命令:

1
pg_dump -U postgres -d mydatabase -Fc -f mydatabase_backup.dump

数据恢复

1、上传备份文件到映射目录

先将导出的备份文件上传到本地映射目录:

1
/opt/1panel/apps/postgresql/postgresql/data

2、创建数据库或清除已有数据

如果你还没有目标数据库,可以使用以下命令创建:

1
createdb -U your_username your_database_name

如果目标数据库已存在,在恢复备份之前,清空目标数据库中的所有表数据。你可以使用 TRUNCATE 命令来清空表,或者使用 DROP TABLE 命令删除表并重新创建。

使用 TRUNCATE 命令:

1
TRUNCATE TABLE images,users,group_strategy,groups,albums,migrations,personal_access_tokens,failed_jobs,strategies,configs,password_resets;

使用 DROP TABLE 命令:

1
DROP TABLE images,users,group_strategy,groups,albums,migrations,personal_access_tokens,failed_jobs,strategies,configs,password_resets;

要恢复备份,可以使用 psqlpg_restore 命令。

使用 psql 恢复 SQL 文件

1
psql -U your_username -d your_database_name -f backup_file.sql

假设你要恢复 mydatabase_backup.sql 文件到 mydatabase 数据库,可以使用以下命令:

1
psql -U postgres -d mydatabase -f mydatabase_backup.sql

例如此处我要执行的命令为:

1
psql -U LskyPro -d LskyPro -f LskyPro_backup.sql

使用 pg_restore 恢复压缩文件

1
pg_restore -U your_username -d your_database_name backup_file.dump

假设你要恢复 mydatabase_backup.dump 文件到 mydatabase 数据库,可以使用以下命令:

1
pg_restore -U postgres -d mydatabase mydatabase_backup.dump

参考

【折腾笔记】兰空图床数据迁移