BookStack 数据库兼容性测试套件(Database Testing Suite)实战指南:基于 Docker 的 MySQL/MariaDB 多版本矩阵测试方案

发布时间:2026/11/11 6:04:39

BookStack 数据库兼容性测试套件(Database Testing Suite)实战指南:基于 Docker 的 MySQL/MariaDB 多版本矩阵测试方案 BookStack 数据库兼容性测试套件Database Testing Suite实战指南基于 Docker 的 MySQL/MariaDB 多版本矩阵测试方案【免费下载链接】BookStackNOW MANAGED ON CODEBERG项目地址: https://gitcode.com/gh_mirrors/bo/BookStackBookStack 在发布涉及数据库 schema 变更或查询逻辑重大调整的版本前需要确保其在所有支持的 MySQL 与 MariaDB 主要版本上都能正常工作。为此项目在 dev/docker/db-testing 目录下提供了一套完整的 Docker 数据库测试套件通过run.sh一键构建包含指定 BookStack 分支的镜像并在 8 个数据库版本上依次执行迁移、填充与完整 PHP 测试套件。读完本文你将掌握这套测试套件的设计思路、运行方式、分支选择、镜像构建细节、数据库版本矩阵与失败处理机制并能结合源码理解其底层实现。这套测试套件的定位与适用场景按照 dev/docker/db-testing/readme.md 的说明这套 Docker 环境专门用于针对 BookStack 支持的每个主要数据库版本覆盖 MySQL 与 MariaDB运行 BookStack 测试套件目的是确认兼容性并在正式发布前提前暴露潜在问题。它有两个鲜明的设计特征面向发布前的手动回归整个过程相当缓慢且开销较重需要依次拉起 8 个数据库容器并各跑一遍完整测试因此并非日常 CI 流程的一部分而是设计为在发布前手动运行。触发时机明确仅当本次发布包含数据库 schema 变更或对数据库查询逻辑有显著改动时才有必要运行。也就是说这是一把发布前的重型检查武器而非频繁使用的日常工具。从脚本实现看这套流程的所有编排都收敛在 dev/docker/db-testing/run.sh 一个脚本中配合 dev/docker/db-testing/Dockerfile 构建应用镜像逻辑非常集中。整体架构与运行流程概览套件由三个文件组成各司其职文件作用dev/docker/db-testing/run.sh编排脚本构建镜像、循环数据库版本、执行测试、处理失败与清理dev/docker/db-testing/Dockerfile构建内置 BookStack 分支副本 PHP 运行环境的应用镜像dev/docker/db-testing/readme.md使用说明文档run.sh的核心流程如下可选地接受一个 BookStack 分支作为测试目标默认development从Dockerfile构建 Docker 镜像镜像内会内置所选分支的完整代码副本依次循环遍历每个受支持的主要数据库版本对每个版本执行artisan migrate迁移数据库使用mysql_testing连接artisan db:seed用DummyContentSeeder填充测试数据vendor/bin/phpunit运行完整 PHP 测试套件若某个数据库版本出现失败脚本会提示你选择继续还是中止测试每个版本测试结束后清理数据库容器与网络进入下一个版本。快速开始从目录运行脚本文档明确要求脚本必须在db-testing目录内运行命令如下# 进入该目录 cd dev/docker/db-testing # 默认针对 development 分支运行 ./run.sh # 针对指定分支运行 ./run.sh v25-11注意./run.sh v25-11这种用法位置参数$1即目标分支名例如v25-11。若省略参数脚本内部BRANCH${1:-development}会将其回退为development。运行前请确保宿主机已安装 Docker 并具备构建镜像的权限因为脚本的第一步就是docker build。应用镜像构建Dockerfile 逐层解读dev/docker/db-testing/Dockerfile 以ubuntu:24.04为基础镜像主要做了三件事1. 安装 PHP 运行时与 BookStack 所需的扩展FROM ubuntu:24.04 RUN apt-get update \ apt-get install -y \ git \ wget \ zip \ unzip \ php \ php-bcmath php-curl php-mbstring php-gd php-xml php-zip php-mysql php-ldap \ \ rm -rf /var/lib/apt/lists/*这里安装的扩展与 BookStack 运行时依赖一一对应php-mysqlPDO MySQL 驱动测试必须、php-mbstring多字节字符串处理、php-gd图片处理、php-xmlXML 解析、php-ldapLDAP 认证模块、php-bcmath、php-curl、php-zip导出/导入 ZIP 功能等。2. 通过构建参数注入分支克隆并安装 BookStackARG BRANCHdevelopment RUN mkdir -p /var/www \ git clone https://codeberg.org/bookstack/bookstack.git --branch $BRANCH --single-branch /var/www/bookstack \ cd /var/www/bookstack \ wget https://raw.githubusercontent.com/composer/getcomposer.org/f3108f64b4e1c1ce6eb462b159956461592b3e3e/web/installer -O - -q | php -- --quiet --filenamecomposer \ php composer install这里有两个关键点--branch $BRANCH --single-branch只克隆指定分支使镜像精确包含所选版本的代码php composer install在构建阶段就把 PHP 依赖装好测试运行时无需联网保证可重复性。3. 固定工作目录与入口命令WORKDIR /var/www/bookstack ENTRYPOINT [/bin/php]入口点被设置为php解释器因此后续run.sh中以docker run ... bookstack:db-testing artisan migrate ...的形式运行容器时等价于在/var/www/bookstack目录下执行php artisan migrate ...。另外注意构建参数--no-cache的使用见下文 run.sh确保每次测试都从零构建避免缓存导致分支代码不新鲜。run.sh 核心实现数据库版本矩阵与测试循环dev/docker/db-testing/run.sh 是整套测试的指挥中心下面按执行顺序拆解。1. 分支参数与镜像构建BRANCH${1:-development} docker build --no-cache --build-arg BRANCH$BRANCH -t bookstack:db-testing . if [ $? -eq 1 ]; then echo Failed to build app container for testing exit 1 fi构建失败时立即退出退出码 1。镜像固定命名为bookstack:db-testing后续所有容器运行都引用这个名字。2. 受支持的数据库版本矩阵脚本维护了一个显式的容器镜像数组这就是 BookStack 当前测试覆盖的全部数据库主要版本containers( mysql:8.0 mysql:8.4 mysql:9.5 mariadb:10.6 mariadb:10.11 mariadb:11.4 mariadb:11.8 mariadb:12.0 )可以看到覆盖 3 个 MySQL 主版本8.0 / 8.4 / 9.5和 5 个 MariaDB 主版本10.6 / 10.11 / 11.4 / 11.8 / 12.0。这一矩阵直接体现了 readme.md 中每个主要数据库版本的描述——任何新增/移除支持版本的发布都需要同步更新此数组。3. 预清理docker stop bs-dbtest-db docker network rm bs-dbtest-net每次运行先尝试停止上一次遗留的数据库容器、删除自定义网络。这两条命令即使对象不存在也会输出错误但不会中断脚本没有set -e起到尽力清理的作用。4. 对每个数据库版本执行测试循环for img in ${containers[]}; do echo Starting tests with $img... docker network create bs-dbtest-net docker run -d --rm --name bs-dbtest-db \ -e MYSQL_DATABASEbookstack-test \ -e MYSQL_USERbookstack \ -e MYSQL_PASSWORDbookstack \ -e MYSQL_ROOT_PASSWORDpassword \ --networkbs-dbtest-net \ $img sleep 20 APP_RUNdocker run -it --rm --networkbs-dbtest-net -e TEST_DATABASE_URLmysql://bookstack:bookstackbs-dbtest-db:3306 bookstack:db-testing $APP_RUN artisan migrate --force --databasemysql_testing $APP_RUN artisan db:seed --force --classDummyContentSeeder --databasemysql_testing $APP_RUN vendor/bin/phpunit ...这个循环有几个值得注意的设计独立网络隔离每个版本测试时都创建独立的bs-dbtest-netDocker 网络应用容器与数据库容器通过该网络通信避免端口冲突数据库容器参数MYSQL_DATABASEbookstack-test创建库、MYSQL_USERbookstack/MYSQL_PASSWORDbookstack设置账号密码、MYSQL_ROOT_PASSWORDpassword设置 root 密码容器名为固定的bs-dbtest-db端口映射为容器内默认 330620 秒等待sleep 20给数据库容器留出初始化首次启动 MySQL/MariaDB 通常需要初始化数据目录的时间连接串通过环境变量注入TEST_DATABASE_URLmysql://bookstack:bookstackbs-dbtest-db:3306以宿主机名bs-dbtest-db解析到数据库容器与 app/Config/database.php 中mysql_testing连接的url env(TEST_DATABASE_URL)直接对应三条测试命令依次执行migrate结构迁移→db:seed填充数据→phpunit完整测试。5. 失败处理与继续/停止选择if [ $? -eq 0 ]; then echo $img - Success else echo $img - Error read -p Stop script? [y/N] ans [[ $ans [yY] ]] exit 0 fi docker stop bs-dbtest-db docker network rm bs-dbtest-net done这里$?取的是vendor/bin/phpunit的退出码成功则打印Success并继续失败则打印Error并通过read -p Stop script? [y/N] 交互式询问是否中止。回答y/Y立即退出退出码 0回答其他默认 N则继续测试下一个数据库版本——这正是文档所述如果某个数据库版本失败脚本会提示你是否继续或停止测试的实现。无论成败每个版本结束后都会docker stop数据库容器并删除网络为下一轮测试腾出干净环境。数据库连接配置mysql_testing 连接深度解析测试全程使用 Laravel 配置文件中名为mysql_testing的数据库连接。在 app/Config/database.php 中定义如下mysql_testing [ driver mysql, url env(TEST_DATABASE_URL), host 127.0.0.1, database bookstack-test, username env(MYSQL_USER, bookstack-test), password env(MYSQL_PASSWORD, bookstack-test), port $mysqlPort, charset utf8mb4, collation utf8mb4_unicode_ci, prefix , prefix_indexes true, strict false, ],解读URL 优先url env(TEST_DATABASE_URL)是 Laravel 连接配置的连接串入口当设置了TEST_DATABASE_URL时其中包含的用户名、密码、主机、端口、库名会覆盖下方的独立字段。run.sh正是通过注入TEST_DATABASE_URL来动态切换测试目标数据库的fallback 默认值若未设置TEST_DATABASE_URL则回退到127.0.0.1、库bookstack-test、用户/密码默认bookstack-test环境变量MYSQL_USER/MYSQL_PASSWORD可覆盖编码与行为utf8mb4utf8mb4_unicode_ci与生产mysql连接一致strict false保持宽松模式prefix为空与 app/Config/database.php 中关于表前缀半支持、不稳定的注释一致测试时不引入前缀干扰。同时phpunit.xml 中通过server nameDB_CONNECTION valuemysql_testing/将整个 PHPUnit 测试套件的默认连接固定为mysql_testing这也是为什么run.sh中运行vendor/bin/phpunit时无需再指定连接——测试代码统一走mysql_testing。测试内容迁移、填充与完整测试套件循环内的三条命令分别承担不同职责$APP_RUN artisan migrate --force --databasemysql_testing--force跳过生产环境确认提示--databasemysql_testing显式指定在测试连接上执行所有迁移。BookStack 的迁移历史位于 database/migrations从 2014 年的用户表一直演进到近期的 slug 历史、mention 历史、实体表重构等迁移能否在某个数据库版本上无错跑通是兼容性的第一道检验。$APP_RUN artisan db:seed --force --classDummyContentSeeder --databasemysql_testingDummyContentSeeder位于 database/seeders/DummyContentSeeder.php它构建了一套能充分触发各类查询与权限逻辑的测试数据创建 editor编辑者与 viewer查看者两个角色的用户并给 editor 额外附加receive-notifications、comment-create-all权限生成 5 本书每本书 3 个章节、每章节 3 个页面另有大书Large book 随机后缀200 个页面、50 个章节生成 10 个书架并与大书关联为 editor 角色附加access-api权限并创建 API Tokentoken_id为apitoken、secret 为password的哈希最后调用JointPermissionBuilder::rebuildForAll()重建全部联合权限、SearchIndex::indexAllEntities()重建全量搜索索引。从 seed 内容可以推断这套数据的意图是让权限评估、搜索索引、分页查询等重查询逻辑在真实数据规模200 页面上得到验证。$APP_RUN vendor/bin/phpunit最后执行完整 PHP 测试套件。测试代码覆盖 tests 下 Activity、Api、Auth、Commands、Entity、Exports、Permissions、Search、Sorting、Uploads、User、View 等全部目录任何数据库方言差异如日期函数、聚合查询、JSON 处理、外键约束行为都会在这里暴露。手动替换测试库的备选方案如果你希望脱离run.sh手动搭建测试数据库仓库还提供了 dev/docker/init.db/01.sql# create test database CREATE DATABASE IF NOT EXISTS bookstack-test; # grant rights GRANT ALL PRIVILEGES ON bookstack-test.* TO bookstack-test%;该 SQL 创建bookstack-test数据库并将全部权限授予bookstack-test用户——这与mysql_testing连接的 fallback 默认值用户bookstack-test、库bookstack-test完全吻合可作为将初始化脚本挂载进数据库容器如放入/docker-entrypoint-initdb.d/时的标准初始化内容。本地调试辅助Xdebug 配置若测试过程中需要断点调试dev/docker/php/conf.d/xdebug.ini 提供了开箱即用的 Xdebug 配置zend_extensionxdebug [xdebug] xdebug.modedebug xdebug.client_hosthost.docker.internal xdebug.start_with_requestyes xdebug.client_port9090其中xdebug.client_hosthost.docker.internal让容器内的 PHP 连接到宿主机上的 IDExdebug.client_port9090指定调试端口xdebug.start_with_requestyes表示每次请求都启动调试会话。将conf.d挂载进容器即可在调试模式下重现某个数据库版本上的失败用例。运行前检查清单与注意事项结合文档说明与脚本实现运行这套测试套件前建议确认以下几点在正确目录执行必须cd dev/docker/db-testing后运行./run.sh脚本依赖当前目录下的DockerfileDocker 可用且资源充足一次运行要依次拉起 8 个数据库容器并各跑一遍完整 PHPUnit耗时较长磁盘与内存需预留足够空间明确测试分支默认测试development分支若要验证某个发布候选分支如v25-11直接作为第一个参数传入网络与代码托管可达构建阶段需要git clonecodeberg 上的 BookStack 仓库以及下载 Composer 安装器需要网络连通理解失败交互行为某个数据库版本失败不会立即中止整个流程脚本会等待你输入y停止或任意其他键继续适合无人值守与人工介入两种场景仅用于发布前回归正如 readme.md 强调的这是慢而重的手动流程仅在 schema 或查询逻辑有重大变更的发布前运行即可不必每次提交都执行。小结BookStack 的数据库测试套件用约 50 行 Shell 脚本加一个 Dockerfile就实现了一套可重复的、覆盖 8 个 MySQL/MariaDB 版本的发布前兼容性回归方案run.sh负责构建内置指定分支代码的镜像、编排迁移 → 填充 → 全量测试三步流程并通过TEST_DATABASE_URL环境变量将应用容器动态指向每个版本数据库mysql_testing连接与DummyContentSeeder则保证了测试的确定性。理解这套机制后你不仅可以按文档一键运行也能在其基础上扩展新的数据库版本、调整测试数据规模甚至接入自己的 CI 流程做更频繁的回归验证。【免费下载链接】BookStackNOW MANAGED ON CODEBERG项目地址: https://gitcode.com/gh_mirrors/bo/BookStack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/11 6:02:51

德保电工证复审怕考不过白交培训费?官方回应来了

德保电工证复审怕考不过白交培训费?官方回应来了 怕考不过白交培训费?德保电工证复审的小伙伴们,这事儿真不是闹着玩的。去年我在鹤壁一家建筑工地当电工时,亲眼看到一个老电工因为复审考试没过,不仅白花了3000块培训费,还被单位辞退了。这事儿让我…

2026/11/11 6:02:51

电工证费时间吗 上岗必须这个证吗 官方报名入口在这里

电工证费时间吗 上岗必须这个证吗 官方报名入口在这里 证书过期了不知道怎么复审延期,这种焦虑感很多电工从业者都经历过。特别是像你这样长期在一线作业的人员,一个不小心,证书一过期,就可能面临停工、被处罚甚至失去岗位的风险。这时候,找到一个…

2026/11/11 6:02:51

学校电工证多少钱?考前押题助你轻松通过考试

学校电工证多少钱?考前押题助你轻松通过考试 找工作找不到门路,说到底就是缺个证。眼下不少工地、学校、工厂都在招人,但 急需特种作业证才能上岗找工作 ,特别是电工证,是很多岗位的准入门槛。如果你正在找电工相关的工作,那就得先搞清楚,…

2026/11/11 6:02:51

真正的电工证是哪个证复审延期怎么办理

电工证到底考哪个才靠谱?真实经历告诉你怎么避坑 你是不是也担心自己学历不高,根本报不上名?别急,今天我就从濮阳培训机构的老学员角度,跟你聊聊【真正的电工证是哪个证】这个话题,顺便把复审延期怎么办理也给你讲明白。…

2026/11/11 6:02:51

电工证6年过后换证通过率揭秘:外省证能转吗?

电工证6年过后换证通过率揭秘:外省证能转吗? 之前考的证在外省能不能转过来?这个问题是很多电工朋友在换证时最关心的,尤其是在外省工作或曾经在外省考取证件的人。 电工证6年过后换证…

2026/11/11 5:57:51

电工证报名需要提前 通过率揭秘全攻略 转岗人员必看

电工证报名需要提前 通过率揭秘全攻略 转岗人员必看 你是不是也遇到过这种情况?找了个中介报名,结果交了钱连报名表都没拿到;或者是听说了某个培训中心,去了才发现根本不靠谱,浪费时间和钱不说,关键是耽误了工作安排。现在越来越多的转岗人员开始考虑…

2026/11/10 8:12:38

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/11 0:02:26

考低压电工证通过率考试真题与备考技巧

低压电工证通过率高不高?学历不高也能考,值不值得考? 你是不是总听说电工证能帮你找高薪工作,但又担心自己学历不够,考不上?其实,低压电工证考试门槛并没有你想象中那么高,关键是方法对不对。这篇文章就告诉你, 考低压电工证通过率到底有多高 ,…

2026/11/11 0:02:26

低压电工证学时千万别踩坑,濮阳毕业生怎么避坑报名

低压电工证学时千万别踩坑,濮阳毕业生怎么避坑报名 你是不是也和我一样,刚毕业就听说低压电工证学时必须达标才能上岗?可一打听,发现报名机构五花八门,价格参差不齐, 不知道去哪报名怕被中介坑…

2026/11/10 20:08:15

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/10 10:29:37

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑