1. 这套审核平台到底解决了什么问题先交代一下背景。Archery 这个项目全称我习惯叫它 SQL 审核系统GitHub 上开源的一套工具核心作用是把数据库的“上线操作”从口口相传、群里吼一嗓子变成一条有记录、有审批、有回滚的流程。简单说它就是一个跑在 Web 界面里的 SQL 工单系统开发提交一条 SQLDBA 在 Archery 里审核、确认影响行数、执行上线、保留回滚语句整个过程全程留痕。我第一次接触 Archery 的时候团队规模还不大MySQL 实例也就七八个但开发天天来问“这个表加个索引能上吗”“这个大查询会不会锁表”一个人根本忙不过来。后来我花了一个下午用 Docker 把 Archery 部署到测试机让开发自己提交 SQL、自己看影响行数直接把“审核”这件事从前置口头沟通变成了自助服务人力瞬间解放。这篇博文就围绕一条主线在一台干净的 Linux 机器上用 Docker Compose 把 Archery 完整跑起来让它能同时纳管 MySQL、PostgreSQL、ClickHouse 三类数据源并说清楚每一类数据源实际能干什么、不能干什么。适合谁看被乱改表结构、慢 SQL 频频上线的 DBA 和运维工程师。解决了什么SQL 变更不可控、线上操作无记录、多套数据库没有一个统一管理入口的问题。我能给到的内容不只有“照抄就能跑”的命令还会把踩过的坑、为什么这么配置、哪些配置改错了会导致系统起不来都讲一遍。2. 为什么我要坚持用 Docker 部署2.1 组件多到不适合裸机安装Archery 不是一个大单体它由好几块拼起来Archery 主程序基于 Python Django。元数据库用来存工单、用户、实例配置信息用的是 MySQL。Redis用来做缓存和异步任务队列。goInception一个专门干“假装执行 SQL、返回影响行数”审核工作的组件。一个负责解析和模拟执行的 SQL 审核引擎。如果不用 Docker你得手动装 Python 环境、装 MySQL、装 Redis、装 goInception还要费劲调端口冲突。我当年裸装过一次光环境问题就折腾了两个小时后来彻底转向 Docker 部署一条docker compose up -d解决所有依赖。2.2 版本可控、可回滚Docker 的镜像本身把代码、运行环境、依赖库全部固定在了一起。我部署任何开源项目都习惯用固定版本 tag而不是latestArchery 也不例外。一旦升级出了幺蛾子直接把镜像 tag 指回旧版本重新启动容器系统就回到了之前可用的状态。这个习惯在 Archery 这种经常更新、且更新可能伴随数据库表结构变动的项目里特别重要。你想想如果裸机部署升级失败后想回滚代码好回滚依赖库和数据库迁移就麻烦了。用 Docker 镜像整个“代码依赖”的维度是可回滚的。2.3 依赖关系一目了然Archery 的官方 Docker 编排文件里写清楚了所有服务之间的依赖关系Archery 启动前必须等 MySQL 就绪、Redis 就绪。任何一个服务挂了主程序都会启动失败或功能残缺但在 Docker Compose 的视角下这些服务的启动顺序、网络互通、数据卷挂载都在一个文件里管理非常清楚。3. 部署前要明确的几件事3.1 硬件和系统要求按我的经验Archery 这套系统不太吃配置真正的消耗来自 goInception 执行 SQL 审核时的内存开销以及 Archery 定期从业务实例采集表结构、慢日志时的额外消耗。最低配置 2 核 4GB 内存50GB 磁盘可以跑一个几十人团队的审核平台。推荐配置 4 核 8GB 内存100GB SSD。这个配置可以支撑较大规模的使用因为要在同一个环境里跑多个容器。操作系统 Ubuntu 20.04 以上、CentOS 7.9 以上都可以。内核版本不要太老否则 Docker 的部分功能受限。Docker 版本 20.10 以上Docker Compose V2 插件模式。我之前在一台 1 核 2GB 的云主机上试过一次 MySQL 审核大表加索引的 SQLgoInception 内存压力就上来了平台会明显卡顿。如果你们团队几十个人同时用还是老老实实给够 8GB。3.2 端口规划Archery 容器内部 Django 服务默认监听 8000 端口docker-compose 文件里一般会把宿主机某个端口映射到容器 8000。我个人习惯把宿主机端口映射成 8000 或 80这样访问路径好记。还需要注意的就是MySQL 元数据库不要轻易暴露宿主机端口它只给 Archery 内部用。同理Redis 更不要暴露公网端口否则会被扫描爆破。3.3 数据目录规划无论把容器部署在哪个目录我都建议把 compose 文件所在的目录固定下来因为后面升级、备份、排查日志都依赖这个路径。我习惯在/data/archery目录下操作把 git 克隆下来的项目文件放进去数据目录通过 docker volume 或 bind mount 挂载到宿主机。从实际运维角度建议至少确认这几个数据不要因为容器删除而丢失Archery 元数据库数据。Archery 生成的 SQL 工单附件和回滚 SQL 文件。日志文件。在后面的配置里我会专门说明数据卷挂载点。4. 手把手部署步骤4.1 获取项目文件和基础镜像首先克隆 Archery 项目代码。这里注意一个大原则不要用master或main分支跑生产要切换到最新的 release tag。mkdir -p /data/archery cd /data/archery git clone https://github.com/hhyo/Archery.git cd Archery git checkout 最新release tag比如我部署时锁定的版本是 1.9.0就用git checkout 1.9.0。如果你不想 clone 整个 git 历史也可以直接下载对应 tag 的源码包解压后进入目录。4.2 调整 docker-compose.yml 的关键配置Archery 项目根目录下有一个docker-compose.yml文件打开它里面定义了 mysql、redis、archery 等几个服务。我逐个说明需要改哪些地方。以我常用的配置为例version: 3 services: mysql: image: mysql:5.7 container_name: archery-mysql environment: MYSQL_ROOT_PASSWORD: archery-mysql MYSQL_DATABASE: archery TZ: Asia/Shanghai volumes: - ./data/mysql:/var/lib/mysql command: --character-set-serverutf8mb4 --collation-serverutf8mb4_unicode_ci healthcheck: test: [CMD, mysqladmin, ping, -h, 127.0.0.1, -proot] interval: 5s timeout: 5s retries: 20 redis: image: redis:7.0 container_name: archery-redis command: redis-server --requirepass archeryredis archery: image: hhyo/archery:1.9.0 container_name: archery depends_on: mysql: condition: service_healthy ports: - 8000:8000 environment: MYSQL_HOST: mysql MYSQL_PORT: 3306 MYSQL_USER: root MYSQL_PASSWORD: archery-mysql MYSQL_DATABASE: archery REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: archeryredis TZ: Asia/Shanghai volumes: - ./data/download:/opt/archery/download几个要点说明。第一MySQL 元数据库镜像版本建议用 5.7。Archery 官方长期兼容 MySQL 5.7虽然新版也支持 MySQL 8.0但 5.7 的配置最省心。第二连接认证。Archery 连接的 MySQL 是这个元数据库不是你们业务库。业务库是在 Archery 界面后填进去的所以这里环境变量改的是内部元数据库不要搞混。另外注意不要用排除了 MYSQL_ROOT_HOST 限制的配置否则远程连接会被拒。第三download目录挂载。这个目录存的是 Archery 自己的 SQL 文件、慢日志分析文件、以及一部分导入导出的临时文件属于“丢了不致命但会很麻烦”的数据。我第一次部署没挂这个目录容器重启后工单里的附件文件全丢了血的教训。挂载到宿主机目录比较稳妥。第四时区。TZ: Asia/Shanghai必加。Docker 容器默认 UTC 时区不设置的话工单创建时间、审核时间都会差 8 小时排查问题的时候非常容易误判。4.3 初始化系统数据库Archery 新版本镜像在容器启动时会自动执行数据库的 migration但为了保险我还是习惯按照官方流程执行一遍初始化动作。先启动除 Archery 之外的基础服务docker compose up -d mysql redis等 MySQL 健康检查通过再启动 Archery 主服务docker compose up -d archery这时看日志确认迁移是否正常执行docker logs -f archery正常日志里会看到类似Applying archery.00xx_xxx... OK的迁移记录。如果你用的镜像是老版本或者自定义构建的可能需要手动进入容器执行 migrationdocker exec -it archery /bin/bash python3 manage.py migrate但是我建议优先使用官方镜像自动初始化的方式手动 migration 只作为镜像没有自动执行时的兜底操作。4.4 创建管理员账号当 Archery 容器起来并且日志里能看到 Django 服务正在监听 8000 端口后进入容器创建管理员。docker exec -it archery /bin/bash source /etc/profile python3 manage.py createsuperuser按提示输入用户名、邮箱、密码。我习惯用admin作为超级管理员密码长度至少 12 位并且不要用团队所有机器共用的那个默认密码。4.5 接入 goInception 审核组件Archery 的 MySQL 审核功能依赖 goInception正常来说 goInception 是作为独立容器运行并纳入同一个 Docker 网络。在 docker-compose.yml 里加上一个 goInception 服务就好goinception: image: hanchuanchuan/goinception:latest container_name: archery-goinception environment: TZ: Asia/Shanghai然后在 Archery 的 Web 界面里把 goInception 的地址配置成goinception端口默认是 4000。这一步很多人会漏掉Archery 的配置里如果没有把 “审核引擎” 和 goInception 关联起来前端提交 SQL 工单时点了“审核”按钮会报一个奇怪的连接错误。配置位置在 Archery 菜单的“系统管理” - “配置管理”里搜索goInception把实际地址填进去即可。由于 docker compose 内部网络默认互通容器之间直接用服务名访问不需要写宿主机 IP。5. 给 Archery 接上真正的业务数据库5.1 资源组先行实例后建Archery 的权限设计里资源组是一个核心概念。你得先建资源组再把实例加进资源组再把用户加入资源组这三者之间是关联的。举个例子我负责一个支付项目组、一个数据中台项目组那我会建两个资源组pay-group、middle-ground-group。支付组下面挂 MySQL 主库、PostgreSQL 数据库数据中台组下面挂 ClickHouse 集群节点。这么做的好处是权限天然隔离支付项目组的开发只能看到支付组下的实例数据中台的开发看不到支付组的任何表。5.2 添加 MySQL 实例进入“实例管理”菜单点击“添加实例”填写数据库类型、主机地址、端口、用户名、密码。Archery 对 MySQL 实例的连接串比较讲究主机地址业务 MySQL 的实际 IP比如10.20.1.15。端口默认 3306如果你通过 proxy 连接就用 proxy 的端口。用户名建议给 Archery 分配独立账号不要直接用 root。权限按需给查询账号给SELECT、SHOW DATABASES、SHOW VIEW等只读权限审核执行账号再单独给ALTER、CREATE、DROP、INDEX等权限。扩展参数如果业务库 MySQL 版本是 8.0可能需要在“扩展参数”里配置连接认证插件。Archery 默认驱动对caching_sha2_password支持不太友好建议在 MySQL 侧给 Archery 独立账号时指定使用mysql_native_password或者调整驱动参数。配置完点击“测试连接”Archery 会主动发起一次真实连接。如果失败页面会直接给出连接错误信息。添加 MySQL 实例之后还要为该实例配置审核执行连接。Archery 的工单流程实际上有两层连接普通连接用于展示表结构、查询数据、获取影响行数预估。审核执行连接用于真正执行线上变更通常交给 goInception 来执行。我在实际使用中普通连接给只读账号审核执行连接给变更权限账号两套账号分开便于审计和追责。5.3 PostgreSQL 实例接入的注意点Archery 新版本支持 PostgreSQL 实例的接入。在添加实例时数据库类型选PostgreSQL填入连接信息即可。PostgreSQL 接入时有几个容易踩的坑PostgreSQL 默认端口 5432不要填错。如果 PostgreSQL 侧开启了 SSL要在“扩展参数”里配置sslmoderequire之类的选项否则 Archery 连不上。PostgreSQL 的连接驱动问题。Archery 内置的驱动对高版本 PostgreSQL 支持良好但如果你连的是极老版本9.x需要额外测试兼容性。另外要提前有预期PostgreSQL 的接入主要是查询、元数据管理和一定程度的工单审核能力复杂 DDL 的模拟审核不如 MySQL 那么精细。因为 goInception 主要面向 MySQL 生态PostgreSQL 天然没有这么细的“模拟执行”逻辑。5.4 ClickHouse 实例接入ClickHouse 的接入方式和 PostgreSQL 类似在实例管理里添加数据库类型选ClickHouse。ClickHouse 的连接端口要注意它有 8123HTTP和 9000TCP两层协议Archery 连接 ClickHouse 通常使用 HTTP 端口 8123。还有一个细节如果你配置的是一个多节点 ClickHouse 集群建议填负载均衡或代理的地址。Archery 本身不做集群拓扑发现它只按普通数据库实例方式连接。ClickHouse 接入后能干什么查询表结构。执行查询并做脱敏控制。慢查询/审计方面只能做有限支持。这和标题里说的“审核”可能略有出入。我不是想泼冷水而是想让大家明白Archery 对 MySQL 的审核能力强因为它背后有 goInception 针对 MySQL 语法的完整解析和标量评估PostgreSQL 和 ClickHouse 目前更偏向“查询、权限、工单流程管理”的范畴。5.5 多数据库权限和脱敏策略Archery 的权限粒度可以按实例、按库表、按 SQL 类型来配。比如对 ClickHouse 实例普通开发只给查询权限甚至只允许查询default库下的几张报表表而对运维角色才放开 DDL 执行权限。数据脱敏这块值得单独说。只要是给开发开放的查询权限我建议一律开启脱敏规则。Archery 支持按字段正则匹配脱敏比如身份证号、手机号、邮箱这些字段查询结果会自动打码。配置一次之后所有通过 Archery 产生的查询结果都按这个规则走开发就不能再绕过审计直接连生产库了。6. 日常使用与团队落地经验6.1 让开发流程真正跑起来Archery 部署好只是第一步真正让它发挥价值的是把团队流程迁上去。我会在实际落地上这样做开发提交 SQL 工单在 Archery 上选择目标实例粘贴 SQL 或上传 SQL 文件。点击“审核”Archery 调用 goInception 对 SQL 做语法解析、影响行数评估如果检测到DROP TABLE、不带 WHERE 的DELETE等高危操作审核勾选会直接标红。DBA 或审批人复核在工单里查看审核结果确认无误后点击“上线”。系统自动执行并生成回滚 SQL。工单归档所有操作留痕后续可以随时查询某一个实例、某一段时间内谁执行了什么 SQL。我在我们团队落地后效果最明显的是“大表加索引”这个场景。以前开发想加索引先在群里问一句DBA 回复“你自己执行吧”然后开发自己登生产执行出了问题没人知道。现在开发自己提交工单goInception 会明确告诉他影响行数以及是否可能锁表很多低级风险直接被拦截在审核环节。6.2 定时扫描和巡检Archery 还带定时巡检功能。可以配置每天自动扫描已接入的 MySQL 实例的慢查询、表结构元数据然后在系统里以报表形式展示。这个功能对 DBA 的价值在于不用定期手动跑一堆命令平台的定时任务会自动把巡检结果沉淀下来。我一般会把巡检时间定在凌晨两点到四点之间避开业务高峰期。不过注意Archery 的定时任务依赖 celery worker如果容器里没有正常启动 worker定时任务不会执行。检查方式是在 Archery 日志里看有没有 celery 相关的任务执行记录。6.3 数据安全合规方面的经验Archery 天然就是一套审计系统但审计的前提是接入数据库的账号权限最小化。Archery 查询业务实例的账号不应该有 DELETE 权限。Archery 执行变更的账号应该限制只能操作指定业务库。Archery 本身所在服务器不要开放 22 端口的公网访问。元数据库 MySQL 的 root 密码不要复用其他环境的密码。这些看着是基础操作但我见过不少团队部署完 Archery 后把业务库的 root 给了 Archery结果 Archery 一旦被入侵等同所有业务库裸奔。7. 高频问题排查与避坑手册7.1 Docker 或容器启动类问题问题一访问不了 Archery 页面先检查容器是否在运行docker ps如果容器一直在 restart 或退出查看日志docker logs --tail 100 archery最常见的日志错误是连接 MySQL 或 Redis 失败。排查思路确认 MySQL 容器健康检查是否通过。健康检查失败会导致 archery 一直等待因为depends_on里配置了condition: service_healthy。确认 docker-compose.yml 里的MYSQL_HOST是否为mysql而不是localhost。Docker 容器内访问另一个容器要用服务名不能用localhost。确认 Redis 密码和连接配置一致。如果你在 Redis 服务里设置了requirepass那 Archery 的连接配置里也要带密码。问题二Windows Docker Desktop 下虚拟化报错热词里经常刷到 virtualization support not detected 这类报错主要发生在 Windows 上用 Docker Desktop 跑容器的情况。这个问题的根因是 BIOS 里的 Intel VT-x / AMD-V 没有开启或者 Windows 的 Hyper-V / WSL2 功能没有启用。我在生产环境不会用 Docker Desktop 跑 Archery但在本地测试时确实遇到过。解决方法是在 BIOS 里开启虚拟化并确保 Windows 启用了 WSL2wsl --status如果 WSL2 不可用按提示开启 Windows 功能“适用于 Linux 的 Windows 子系统”和“虚拟机平台”重启后再启动 Docker Desktop。问题三端口冲突如果宿主机上已经有一个服务占用了 8000 端口Archery 的端口映射会失败。改 docker-compose.yml 里的端口映射即可比如宿主机用 8080 映射容器 8000ports: - 8080:80007.2 数据库连接和审核类问题问题四MySQL 实例连接测试失败确认业务 MySQL 是否允许 Archery 所在主机访问。很多云数据库默认白名单机制需要加白。确认账号是否有权限。确认认证插件问题。如果 Archery 页面报Authentication plugin caching_sha2_password cannot be loaded就是认证插件不兼容建议在业务 MySQL 里把该账号改为mysql_native_password或调整 Archery 连接串。问题五goInception 审核失败或报错先看 Archery 系统配置里 goInception 地址是否可连通telnet goinception容器IP或服务名 4000在 docker compose 网络内直接用goinception解析。还有一个常见坑goInception 版本和 Archery 版本不匹配。Archery 升级后建议同时升级 goInception 镜像否则接口字段不一致审核时可能返回异常结构。问题六提交的 SQL 审核后影响行数为 0 或不准确这个通常是 goInception 没办法拿到表的统计信息导致的。确认业务 MySQL 库表结构是否能被 Archery 读取。goInception 是否配置了正确的连接信息。是不是用了临时表或视图goInception 对临时表的解析能力较弱。7.3 数据与备份问题问题七Archery 自身元数据库备份Archery 的元数据库是整个系统的核心工单记录、权限、实例配置全在它里面。我建议每天做一次逻辑备份docker exec archery-mysql mysqldump -uroot -parchery-mysql --databases archery /backup/archery_$(date %F).sql保留最近 30 天备份即可。这个备份的重要程度不亚于业务库备份因为一旦丢失所有审计记录就没了。问题八容器时间与宿主机不一致容器默认 UTC如果你没配TZAsia/Shanghai工单时间会差 8 小时。出现这个问题的处理方式是修改 docker-compose.yml添加环境变量environment: TZ: Asia/Shanghai然后重建容器docker compose up -d --force-recreate7.4 一个实用的排查速查表症状可能原因排查命令或位置Archery 容器反复重启MySQL 未就绪或账号密码错docker logs archery登录页面白屏Redis 连接失败或密码错docker logs archery实例测试连接失败网络不通、账号无权限、认证插件不符Archery 页面报错信息工单审核报 goInception 错误goInception 配置地址错误查看 Archery 配置管理定时任务不执行Celery worker 未启动docker exec archery ps aux时间差 8 小时未设置 TZ 环境变量修改 compose 并重建附件或下载文件丢失download 目录未挂载检查 compose volumes 配置8. 最后补充几句经验Archery 这种系统部署本身不难难在怎么和团队现有流程结合。我部署过几次之后最想说的一条经验是不要上来就追求多数据库全接入先只接 MySQL把工单审批流程、权限分配、脱敏规则跑顺等团队养成“SQL 上线必须走 Archery”的习惯后再逐步扩展 PostgreSQL 和 ClickHouse。一次铺开多个数据库类型维护成本和用户培训成本都会翻倍。还有个小技巧我在 Archery 前面加了一层 Nginx 反向代理配置 HTTPS 证书让团队通过统一域名访问而不是直接暴露IP:8000。这么做一方面解决了明文传输问题另一方面方便后续做单点登录对接。如果你也想在正式环境好好用这一步建议别省。Archery 后续还可以做二次开发比如对接内部工单系统、自动同步企业微信或钉钉通知。Docker 部署带来的标准化环境让这些扩展都不会太折腾只要保留好宿主机上的数据卷随时可以回滚或迁移。我的实践就是这样先把基础平台稳定跑起来再逐步迭代细节。
