250901-BookStack跨服务器从Rootless-Docker到Rootful-Docker的备份迁移及服务启动

在这里插入图片描述

下面给你一套「可离线、最小停机」的迁移步骤,从 A(rootless)搬到 B(rootful)。思路是:停 A → 打包数据卷 → 传到 B → 还原 → 用同版本镜像启动 → 验证。整套操作不依赖公网,只用你已有的离线镜像 tar 包即可。


1) 在服务器 A 上准备与备份

假设你的 docker-compose.yml/opt/bookstack/,并且里面的相对目录 ./data/app./data/db 就在这个目录下。

# 进入 compose 目录
cd /opt/bookstack# 停止容器(确保数据一致)
docker compose down# ⭐ 方法1:打包数据(含 app 与 db 两个持久化目录), 有权限问题
# tar -czf bookstack_backup_$(date +%F).tgz data# ⭐ 方法2:从容器里面拷贝,绕开权限问题# 从容器里把 /config 拷到当前目录
docker cp bookstack_db:/config ./db_copy
docker cp bookstack:/config ./app_copy# 再打包
tar -czf bookstack_data_$(date +%F).tgz app_copy db_copy# ⭐ 可选:额外做一次数据库逻辑备份(双保险):
docker compose up -d bookstack_db
docker exec bookstack_db sh -c 'mysqldump -ubookstack -pbookstackpass --databases bookstackapp' > bookstackapp_dump_$(date +%F).sql
docker compose down

bookstack_backup_YYYY-MM-DD.tgz(以及可选的 bookstackapp_dump_YYYY-MM-DD.sql)拷到服务器 B,比如放到 /opt/bookstack/


2) 在服务器 B 上准备运行环境

(1) 放置目录与文件

mkdir -p /opt/bookstack
cd /opt/bookstack# 拷贝 A 来的备份包
# scp/sftp/rsync 均可,这里假设已经放到了当前目录
tar -xzf bookstack_backup_YYYY-MM-DD.tgz# 确保目录结构如下:
# /opt/bookstack/
#   ├─ docker-compose.yml   (你会在下一步创建/粘贴)
#   └─ data/
#       ├─ app/             (BookStack 应用配置与上传)
#       └─ db/              (MariaDB 数据)

(2) 离线导入镜像(你已经有 tar 包)

docker load -i /path/to/ghcr.io_linuxserver_bookstack-amd64.tar
docker load -i /path/to/ghcr.io_linuxserver_mariadb-amd64.tar

导入后用 docker images | grep linuxserver 看看对应 tag,确保 compose 用的 image: 与本地 tag 一致(不带 tag 默认拉 latest,离线环境建议显式写 tag,见下方示例)。

(3) SELinux 与权限(RHEL 关键点)

  • RHEL 通常 SELinux=Enforcing,建议在 卷挂载后缀:Z,或对目录执行 chcon。我推荐在 compose 的 volumes 里直接用 :Z
  • linuxserver.io 镜像用 PUID/PGID 控制容器内文件属主。你用的是 1000:1000,那就确保宿主机目录也是这个属主,避免写入报错:
  • 恢复数据的脚本如下:
cd /opt/bookstack# 1) 先建目标目录
mkdir -p data/app data/db# 2) 把 app_copy 的内容拷到 data/app
#   兼容两种结构:app_copy/config/... 或 app_copy/直接就是内容
if [ -d app_copy/config ]; thencp -a app_copy/config/. data/app/
elsecp -a app_copy/.        data/app/
fi# 3) 把 db_copy 的内容拷到 data/db
#   同样兼容 db_copy/config/... 或 db_copy/直接就是内容
if [ -d db_copy/config ]; thencp -a db_copy/config/. data/db/
elsecp -a db_copy/.        data/db/
fi# 4) 修正属主(linuxserver 镜像要求 1000:1000)
chown -R 1000:1000 data/app data/db# 如 RHEL/SELinux 处于 Enforcing,且你没有在 compose 里用 :Z,
# 可以加上这行给目录打上容器可读写的类型(两者选其一即可):
# chcon -Rt svirt_sandbox_file_t data/app data/db# 5) 清理临时目录(可选)
rm -rf app_copy db_copy
  • 最终启动并访问http://<服务器B的IP>:6875
docker compose up -d

(4) 防火墙(RHEL)

如果要从外部访问 6875/tcp

firewall-cmd --permanent --add-port=6875/tcp
firewall-cmd --reload

3) 在服务器 B 上的 docker-compose.yml(示例)

把下面内容保存为 /opt/bookstack/docker-compose.yml。和你在 A 上的几乎一致,只是:

  • 更新了 APP_URL 为服务器 B 的地址(或你的域名、HTTPS);
  • 给两个卷都加了 :Z 以适配 SELinux;
  • 可选:显式写镜像 tag(把 <TAG> 换成你 docker images 里看到的实际 tag;如果你确认是 latest,也可保留 latest)。
services:bookstack:image: ghcr.io/linuxserver/bookstack:<TAG>container_name: bookstackenvironment:- PUID=1000- PGID=1000- APP_URL=http://<服务器B的IP或域名>:6875- APP_KEY=base64:w+nAsQLJ1Q/EPxIx5JXXnJ/USqOG/cR21vIGvyFLIeU=   # 保持不变- DB_HOST=bookstack_db- DB_PORT=3306- DB_USERNAME=bookstack- DB_PASSWORD=bookstackpass- DB_DATABASE=bookstackappvolumes:- ./data/app:/config:Zports:- "6875:80"restart: unless-stoppeddepends_on:- bookstack_dbbookstack_db:image: ghcr.io/linuxserver/mariadb:<TAG>container_name: bookstack_dbenvironment:- PUID=1000- PGID=1000- MYSQL_ROOT_PASSWORD=bookstackpass- TZ=Asia/Shanghai- MYSQL_DATABASE=bookstackapp- MYSQL_USER=bookstack- MYSQL_PASSWORD=bookstackpassvolumes:- ./data/db:/config:Zrestart: unless-stopped

说明:

  • APP_KEY 一定要沿用原值,这样原有上传、会话等不会失效。
  • 如果 B 上将来走反向代理/HTTPS,记得把 APP_URL 改成 https://你的域名,必要时添加 APP_TRUSTED_PROXIES=*

4) 启动与验证

cd /opt/bookstack
docker compose up -d# 先看数据库是否健康
docker logs -f bookstack_db# 再看应用
docker logs -f bookstack

打开浏览器访问:http://<服务器B的IP>:6875
确认历史页面、图片/附件、用户、权限等都在。


5) 常见坑与排查

  1. 权限被拒绝(Permission denied)

    • 大多是宿主目录属主不对或 SELinux。先 chown -R 1000:1000 /opt/bookstack/data/*,再确保卷挂载后缀 :Z,或用 chcon -Rt svirt_sandbox_file_t ...
  2. 容器一直重启,App 连接不上 DB

    • depends_on 只保证顺序不保证“可用”。再等等,或看 bookstack_db 日志;数据库初始化首次启动会花点时间。必要时重启应用容器:docker restart bookstack
  3. 访问 6875 不通

    • 检查 docker ps 端口映射、firewall-cmd、以及宿主机上是否有别的服务占用 6875。
  4. 镜像版本不匹配

    • 离线导入的镜像 tag 最好与 compose 对齐;若不清楚,运行前 docker images 看清楚 tag。
  5. APP_URL 更换导致外链/回调异常

    • 换了 IP/域名就更新 APP_URL,否则某些重定向、文件 URL 可能不正确。

6) 可选:用 SQL 备份恢复(当你不想拷贝整个 db 卷时)

如果只想迁移应用卷 + 用 mysqldump 恢复:

# 在 B 上:启动空库
docker compose up -d bookstack_db# 导入 A 导出的 SQL
docker exec -i bookstack_db sh -c 'mysql -ubookstack -pbookstackpass bookstackapp' < bookstackapp_dump_YYYY-MM-DD.sql# 再启动应用
docker compose up -d bookstack

一句话总结

  • 把 A 的 data/appdata/db 原样带到 B;
  • B 上用相同或兼容的镜像、相同的 APP_KEY 与 DB 账号;
  • RHEL 要注意 SELinux(:Z)目录属主(1000:1000)
  • 更新 APP_URL,放行端口,启动即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/95114.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95114.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(Redis)Redis 分布式锁及改进策略详解

一、为什么需要分布式锁在单机应用中&#xff0c;synchronized 或 ReentrantLock 足以解决并发问题。但在 分布式系统 中&#xff0c;多台服务器之间共享同一个资源时&#xff0c;如果没有锁&#xff0c;很可能出现 超卖、重复扣减、数据不一致 等问题。 因此&#xff0c;分布式…

Linux应用开发-windows,linux环境下相关工具

VS Code Remote - SSH 虚拟机部分的操作 sudo systemctl status sshsudo apt update sudo apt install openssh-server sudo systemctl start ssh sudo systemctl enable ssh # 设置开机自启hostname -IVS Code部分的操作 安装 Remote - SSH 插件 vscode右下角出现&#xff…

Java泛型通配符详解:搞懂?/extends/super用法,避开集合操作踩坑点

上次跟你们聊了泛型的基础用法&#xff0c;今天接着往下说 —— 泛型里还有个挺重要的概念叫 “通配符”&#xff0c;就是那个问号 “?”&#xff0c;很多人第一次见都懵&#xff1a;这玩意儿跟普通泛型有啥区别&#xff1f;为啥有时候非得用它不可&#xff1f;小索奇当初也卡…

EXCEL开发之路(二)跨表交互模拟—仙盟创梦IDE

在车辆租赁行业&#xff0c;数据的高效管理与分析对于企业的运营决策、资源调配及客户服务优化至关重要。自建 Excel 实现多表统计交互&#xff0c;如同为行业装上了效能驱动引擎&#xff0c;助力企业在复杂多变的市场环境中稳健前行。一、精准资源管理&#xff0c;优化车辆调配…

医疗AI时代的生物医学Go编程:高性能计算与精准医疗的案例分析(八)

5.4 性能测试与结果分析 为了评估GoEHRStream的性能,我们设计测试模拟真实的医院数据流场景,并测量关键指标。 5.4.1 实验环境 硬件: CPU: Intel Xeon E-2288G (8 cores, 16 threads) RAM: 32 GB DDR4 Storage: 512 GB NVMe SSD (用于GoEHRStream和BadgerDB) Network: 1 G…

开关电源设计“反馈回路”部分器件分析

目录 主要分析问题如下&#xff1a; 一、问题1 二、问题二 分析电路如下&#xff1a; 主要分析问题如下&#xff1a; 1、分析TL431芯片1、2两引脚间并联电阻和电容&#xff08;RC电路&#xff09;的作用&#xff1f; 2、PC817A光耦输入两个引脚间并联电阻的作用&#xff1f;…

AI 编程新玩法:用 yunqi-saas-kit 框架制作小游戏,看广告变现轻松赚钱​

AI 编程新玩法&#xff1a;用 yunqi-saas-kit 框架制作小游戏&#xff0c;看广告变现轻松赚钱 在数字经济快速发展的当下&#xff0c;AI 技术正不断渗透到各个领域&#xff0c;其中 **#AI 编程凭借高效、便捷的优势&#xff0c;成为不少开发者和创业者的新选择。尤其是在小游戏…

Kafka 架构原理

一个kafka集群中包含一个或多个Producer、一个或多个broker、一个或多个ConsumerGrop以及一个Zookeeper集群。kafka通过Zookeeper管理kafka集群配置、leader副本的选举、生产者的负载均衡等。Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消…

用 PyTorch 搭建 CNN 实现 MNIST 手写数字识别

在图像识别领域&#xff0c;卷积神经网络&#xff08;CNN&#xff09; 凭借其对空间特征的高效提取能力&#xff0c;成为手写数字识别、人脸识别等任务的首选模型。而 MNIST&#xff08;手写数字数据集&#xff09;作为入门级数据集&#xff0c;几乎是每个深度学习学习者的 “第…

CTFshow系列——命令执行web61-68

本篇文章介绍了不同了方法进行题目的解析以及原因讲解。 文章目录Web61尝试了一下&#xff0c;被过滤的payload如下&#xff1a;所以&#xff0c;根据上述思路&#xff0c;这里尝试过的payload为&#xff1a;Web62&#xff08;同Web61&#xff09;Web63&#xff08;同Web62&…

.Net程序员就业现状以及学习路线图(二)

一、.NET程序员就业现状分析 1. 市场需求与岗位分布 2025年.NET开发岗位全国招聘职位约1676个&#xff0c;占全国技术岗位的0.009%&#xff0c;主要集中在一线城市如深圳、上海等地。就业单位类型分布为&#xff1a;软件公司占43.3%&#xff0c;研发机构占33.1%&#xff0c;物联…

MTK Linux DRM分析(二十二)- MTK mtk_drm_crtc.c(Part1)

一、代码分析 mtk_drm_crtc.c以mtk_crtc_comp_is_busy函数为界限进行拆分分析 static const struct drm_crtc_funcs mtk_crtc_funcs = {.set_config = drm_atomic_helper_set_config,.page_flip = drm_atomic_helper_page_flip,.destroy = mtk_drm_crtc_destroy,.reset = mtk…

stm32f103c8t6 led闪灯实验

目录 闪灯原理 2种接线方式控制闪灯 使用推挽接法 使用开漏接法 看原理图 写代码 闪灯原理 LED灯有个2-10mA的电流就可以点亮 3.3/5100.006A6mA 2种接线方式控制闪灯 使用推挽接法 当设置推挽模式时&#xff0c;CPU控制寄存器写0&#xff0c;IO引脚输出低电压&#xff0…

“我同意”按钮别乱点——你的“职业EULA”漏洞扫描报告

尊敬的审核&#xff1a; 本人文章《“我同意”按钮别乱点——你的“职业EULA”漏洞扫描报告》 1. 纯属技术交流&#xff0c;无任何违法内容 2. 所有法律引用均来自公开条文 3. 请依据《网络安全法》第12条“不得无故删除合法内容”处理 附&#xff1a;本文结构已通过区块链存证…

Product Hunt 每日热榜 | 2025-09-01

1. A01 标语&#xff1a;你个人的新闻助手 介绍&#xff1a;A01 是你的新闻助手&#xff0c;可以帮你关注你关心的任何话题。只需告诉它你想了解什么&#xff0c;它就能为你带来最新的文章。 产品网站&#xff1a; 立即访问 Product Hunt&#xff1a; View on Product Hunt…

【OpenFeign】基础使用

【OpenFeign】基础使用1. Feign介绍1.1 使用示例1.2 Feign与RPC对比1.3 SpringCloud Alibaba快速整合OpenFeign1.3.1 详细代码1. Feign介绍 1.什么是 Feign Feign 是 Netflix 开发的一个 声明式的 HTTP 客户端&#xff0c;在 Spring Cloud 中被广泛使用。它的目标是&#xff…

访问相同的url,相同入参的请求,Apifox/Postman可以正常响应结果,而本地调用不行(或结果不同)

文章目录问题概述Apifox查看实际请求总结问题概述 开发中有一个需求需要去别的系统中拿数据&#xff0c;配置好相关参数后发起请求时发现响应结果和在Apifox上不同&#xff0c;Apifox上正常显示数据&#xff0c;而本地调用后返回数据不存在。 这就很奇怪了&#xff0c;想了很多…

数据结构(C语言篇):(七)双向链表

目录 前言 一、概念与结构 二、双向链表的实现 2.1 头文件的准备 2.2 函数的实现 2.2.1 LTPushBack( )函数&#xff08;尾插&#xff09; &#xff08;1&#xff09;LTBuyNode( ) &#xff08;2&#xff09;LTInit( ) &#xff08;3&#xff09;LTPrint( ) &#x…

从拿起简历(resume)重新找工作开始聊起

经济萧条或经济衰退在经济相关学术上似乎有着严格的定义&#xff0c;我不知道我们的经济是否已经走向了衰退或者萧条&#xff0c;但有一点那是肯定的&#xff0c;那就现在我们的经济肯定是不景气的。经济不景气会怎么样&#xff1f;是的&#xff0c;会有很多人失业&#xff0c;…

OS+MySQL+(其他)八股小记

鲁迅先生曾经说过&#xff0c;每天进步一点点&#xff0c;妈妈夸我小天才。 依旧今日八股&#xff0c;这是我在多个文档整合一起的&#xff0c;可能格式有些问题&#xff0c;请谅解。 操作系统 1.进程和线程的区别&#xff1f; 进程是代码在数据集合的一次执行活动&#xff0c;…