Archery部署实战:基于Docker Compose搭建SQL审核平台并接入三种数据库
做数据库运维的同学应该都有这种体会公司里一旦过了几十个开发、几百张表数据库变更就开始失控了。开发提了一条SQL过来到底是好是坏、有没有索引失效、会不会锁表全靠DBA肉眼去“人肉审计”。更麻烦的是执行完没留痕、想回溯找不到记录、账号权限也分不清楚谁动了哪张表。Archery就是来解决这个问题的它是一个开源的SQL审核查询平台把“提交SQL、规则校验、DBA审核、在线执行、结果回滚、日志审计”整条链路全部Web化支持MySQL、PostgreSQL、ClickHouse等多种数据库而且全部操作留痕。这篇教程我想把从零开始用Docker Compose把它完整部署起来、再把三种数据库实例接入的过程一步步讲清楚。整个实操下来你会发现这东西部署起来并没有想象中复杂反而是实例接入和权限配置更值得花心思。1. Archery核心价值与方案选型思路1.1 Archery到底解决了什么问题先说一个真实场景。早些年我在一家电商公司做DBA每周最头疼的事情就是收开发发来的SQL变更申请通常是Excel或者聊天消息写得乱七八糟。“给xx表加个索引”“某条UPDATE忘写WHERE了能帮我回滚吗”这种消息天天有。人工审核有两个致命问题第一不可追溯。SQL到底是谁提交的、什么时候执行的、执行前有没有人审过全靠邮件和聊天记录出事只能靠猜。第二规则不一致。同一个DBA今天心情好放过了一条没走索引的SQL明天另一个DBA审核时直接打回。开发完全不知道标准是什么流程形同虚设。Archery的定位就是把这件事标准化。它不是一个GUI工具而是一个“平台”核心功能包括SQL审核内置规则引擎对提交的SQL做语法解析、索引分析、规范校验比如检测到全表DELETE、无WHERE条件的UPDATE、大表DDL等高风险操作会直接拦截或告警。工单流转开发提交SQL后生成工单DBA在Web界面审核通过后可以手动执行、定时执行执行过程自动记录。查询能力开发可以在线查询但管理员可以控制查询权限、限制返回行数、敏感字段脱敏。审计日志谁在什么时间执行了什么SQL一律留痕。多数据库支持当前主流的MySQL、PostgreSQL、ClickHouse都能接入这也是这篇教程选这三种数据库的原因。拿它和其他开源方案横向比一比平台SQL审核工单流程多数据库支持查询/脱敏社区活跃度Archery强完整MySQL/PostgreSQL/ClickHouse等支持高Yearning中完整主要MySQL部分中CloudBeaver弱无多种支持但不克制中Kebinet中部分主要MySQL不支持低Archery的优势在于“审核流程查询审计”是一条完整的闭环而不是只做了其中某一个点。这也是我当年最终选它的核心理由。1.2 为什么选择Docker Compose部署Archery自身是基于Django开发的Web应用依赖的东西不算少Python运行时、系统库、MySQL它自己的元数据库、Redis缓存和异步队列、Django Q异步任务调度再加上各类数据库驱动和工具包。如果用裸机部署光是把这些依赖在干净环境里装一遍就能消耗掉大半天时间。更崩溃的是不同版本的Python和MySQL之间还有兼容性问题换个机器就是一场新的灾难。用Docker Compose部署的好处非常直接环境隔离所有依赖都封装在镜像里宿主机上装了什么乱七八糟的Python、库都不影响。一条命令拉起docker compose up -d搞定不再需要手写初始化脚本。升级回滚方便镜像版本切来切去配合数据卷挂载数据还在。三个角色一个镜像Archery容器可以按启动参数分成web、task、scheduler不同角色实际部署时可以用一个镜像跑多个容器。当前这套部署方案的整体架构大致是这样的web容器Django应用本体提供Web界面和API端口默认8080。task容器异步任务执行器处理SQL执行、工单状态变更等后台任务。scheduler容器定时任务调度负责周期性的清理、巡检、统计等任务。MySQL容器Archery的系统元数据库存放用户、实例、工单、规则等数据。Redis容器缓存与异步队列。搞清楚这个架构后面看docker-compose配置文件就不会一头雾水了。2. 环境准备与前置条件2.1 Docker与Docker Compose的安装检查工欲善其事必先利其器。不管你是Linux服务器还是Windows/macOS笔记本先把Docker环境跑起来。LinuxCentOS/Ubuntu/Debian我建议直接用官方脚本安装简洁省事curl -fsSL https://get.docker.com | bash systemctl enable --now docker docker --version装完Docker之后确认一下Compose插件docker compose version现在新版Docker都自带Compose V2插件不需要单独装docker-compose这个独立二进制了。如果执行报错说明版本太老建议把Docker升级到20.10以上。Windows / macOSWindows上首推Docker Desktop。但很多人在安装后启动时遇到过一个问题提示virtualization support not detected或者虚拟化支持没有检测到容器根本跑不起来。这个问题一般不是Docker的锅而是宿主机的虚拟化开关没开排查路径按这个顺序来打开任务管理器 - 性能 - CPU确认“虚拟化”这一项是不是“已启用”。如果显示“已禁用”需要进BIOS开启Intel VT-x或AMD-V。这一步网上各种教程写得很多我不展开。确认Windows功能里“适用于Linux的Windows子系统”和“虚拟机平台”两个选项都勾上了然后重启。如果依然报错打开PowerShell管理员执行wsl --version确认WSL2内核是否完整。Windows下如果Docker Desktop实在启动不了还有一个保底方案用WSL2里装Docker Engine。但那是另一个话题本节的目标是先确认Docker和Docker Compose两条命令能正常输出版本号。验证环境是否就绪docker info docker compose version两个命令不报错就可以继续了。2.2 资源规划与端口规划Docker部署虽然省事但资源需求不能忽视。Archery本身是Java都不用的轻量级应用但它要同时跑MySQL和Redis还要执行一些SQL审核任务所以资源底线不能太低。我的建议是节点角色最低配置推荐配置单机部署本教程4核8GB内存8核16GB内存磁盘50GB100GB以上为什么内存要求不低因为MySQL系统库本身就要吃内存加上Django进程、Redis缓存以及执行审核任务时的临时开销8GB以下会明显感觉卡顿工单提交多了还可能OOM。端口规划也比较重要。Archery的Web端口默认是8080系统库MySQL默认3306Redis默认6379。这几条端口在部署前就要想清楚服务默认端口用途注意点Archery Web8080浏览器访问平台宿主机端口可映射为自定义端口系统MySQL3306存储Archery元数据如果宿主机已有MySQL建议改映射端口Redis6379缓存与异步队列内网使用不建议暴露公网本机如果已经有服务占用这些端口docker compose启动时会报port is already allocated。我的习惯是如果宿主机3306已经被MySQL占用就把容器里的MySQL映射到13306:3306完全不影响Archery内部通信因为容器之间走的是Docker网络不依赖宿主机端口映射。2.3 工作目录与数据目录规划部署前最好先规划一个干净的工作目录把配置、数据、日志都放在一个地方后面对比排查会省很多事。mkdir -p ~/archery cd ~/archery在这个目录下我们会创建docker-compose.yml同时会有两个数据卷目录mysql-data和redis-data分别挂载系统库的MySQL数据和Redis持久化数据。这样即使容器删了重建数据也不会丢。我的工作目录结构大概是这样的~/archery ├── docker-compose.yml ├── mysql-data/ └── redis-data/Docker的细节很多人容易忽略一定要把数据卷挂载出来。不挂载的话容器删了数据就没了Archery里面的用户、工单、实例配置全部归零那种感觉比环境没装好还要崩溃。3. 从零部署编写并启动docker-compose3.1 获取Archery部署文件与镜像版本选择部署Archery之前先到它的GitHub Releases页面拿到最新的release包。二进制包里除了Docker配置文件还包括初始化SQL脚本、Dockerfile、示例配置等。我习惯把整个release包解压到刚才的~/archery目录里官方推荐的做法是保留它自带的docker-compose.yml再按需修改。镜像的话官方Docker Hub有构建好的镜像仓库名一般是hhyo/archery。我建议直接使用官方镜像不要自己从头构建。自己构建要拉Python、编译依赖、装MySQL客户端、装ClickHouse驱动一套下来耗时很久而且配置容易出错。直接用官方镜像省去这些繁琐步骤。拉镜像的命令docker pull hhyo/archery:latest如果网络拉取比较慢可以考虑配置国内镜像加速器这个按自己的网络环境处理即可。3.2 编写docker-compose.yml核心配置逐行解读这里我给出一个经过我实际验证可用的docker-compose.yml这个文件同时也适合多数中小型团队直接抄作业version: 3.8 services: archery: image: hhyo/archery:latest container_name: archery-web restart: unless-stopped ports: - 8080:8080 environment: MYSQL_HOST: mysql MYSQL_PORT: 3306 MYSQL_USER: archery MYSQL_PASSWORD: ArcheryPass2024 MYSQL_DATABASE: archery REDIS_HOST: redis REDIS_PORT: 6379 TZ: Asia/Shanghai volumes: - ./data:/app/data depends_on: - mysql - redis mysql: image: mysql:8.0 container_name: archery-mysql restart: unless-stopped ports: - 13306:3306 environment: MYSQL_ROOT_PASSWORD: RootPass2024 MYSQL_DATABASE: archery MYSQL_USER: archery MYSQL_PASSWORD: ArcheryPass2024 TZ: Asia/Shanghai command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_unicode_ci volumes: - ./mysql-data:/var/lib/mysql redis: image: redis:7 container_name: archery-redis restart: unless-stopped ports: - 16379:6379 volumes: - ./redis-data:/data各个配置的作用我逐条解释一下archery 服务核心应用容器。端口8080映射到宿主机浏览器访问http://localhost:8080就是Archery的登录页。MYSQL_环境变量*告诉Archery去连哪台MySQL。这里的mysql是compose网络内的服务名Docker内部的DNS会自动解析到这个MySQL容器不需要写IP。REDIS_环境变量*同理指定Redis服务地址。depends_on保证MySQL和Redis先于Archery启动。但这里有个坑MySQL容器起来不等于数据库初始化完成所以后面首次启动后需要等几秒钟再初始化Archery。mysql 服务Archery的系统库。ports映射我用的是13306:3306避免和宿主机已有的MySQL冲突。同时指定了utf8mb4字符集避免中文乱码。redis 服务缓存和消息队列。3.3 首次启动与初始化从拉取镜像到创建管理员配置完成后第一次启动不要急着直接初始化按这个顺序操作第一步启动容器cd ~/archery docker compose up -d这个命令会依次拉取镜像并启动三个容器。第一次拉取可能需要一段时间取决于网络。启动后用docker compose ps查看状态docker compose ps看到三个容器状态都是Up说明容器层面没问题了。第二步等MySQL初始化完成MySQL容器首次启动时需要初始化数据目录和系统表这个过程通常需要10到30秒。直接执行下面的命令确认MySQL能正常连上docker exec -it archery-mysql mysql -uarchery -pArcheryPass2024 -e select 1;如果能返回1说明数据库已经可用。如果报连接失败等一下再试。第三步初始化Archery系统表并加载数据Archery的release包中自带初始化脚本通常位于sql/目录下。把release包里的init.sql文件复制到容器中执行或者直接用docker exec进入容器执行迁移docker exec -it archery-web python3 manage.py migrate这一步会创建Archery运行所需的全部数据表。如果执行时报错说连不上MySQL大概率是MySQL还没准备好重新执行一次即可。随后加载初始化数据docker exec -it archery-web python3 manage.py dbshell sql/init.sql初始化数据会写入内置规则、默认资源组、管理员账号等基础数据。第四步创建超级管理员docker exec -it archery-web python3 manage.py createsuperuser按提示输入用户名、邮箱、密码建议用户名直接用admin密码设置复杂一点。这一步创建的账号是超级管理员可以登录平台做所有配置。第五步访问平台浏览器打开http://localhost:8080用刚创建的超级管理员账号登录。看到登录页说明整套系统已经跑起来了。到这里Archery的部署已经完成。很多教程会在这里收尾但实战中真正花时间的往往是后面的实例接入和权限配置这也是接下来我要重点展开的部分。4. 系统配置与三种数据库实例接入4.1 登录后台后的基础配置用超级管理员登录Archery之后第一件事不是急着加数据库实例而是把系统的整体配置过一遍。进入“系统管理”-“系统配置”建议优先调整以下几项平台名称改成自己公司的名称开发人员登录后知道进的是哪个平台。工单超时时间设置一个合理的审核超时限制避免工单被DBA遗忘。邮箱SMTP配置如果希望工单提交、审核时有邮件通知这里必须配置。没有邮件服务可以先跳过不影响核心流程。LDAP/LDAP对接公司有统一认证的话可以对接小团队可以暂时忽略。基础配置完成后接下来就是重头戏把三种数据库实例接入进来。Archery的实例管理入口在“实例管理”-“新增实例”。接入的过程虽然界面相似但每种数据库在权限和连接参数上有些细微差异逐个来说。4.2 接入MySQL实例最顺手也最需要细心MySQL是Archery支持得最完善的数据库类型也是绝大多数团队的第一选择。新增实例时关键参数这样填数据库类型选MySQL实例名称建议用“环境业务角色”的命名方式比如生产-订单库-主库主机地址与端口填MySQL实例所在的IP和端口。这里必须是Archery容器能访问到的地址不能填localhost否则Archery连的是它自己的容器网络连不到你的MySQL。这是新手最容易踩的坑。数据库账号与密码Archery连接MySQL执行审核和执行操作需要一个专用的账号不要直接用root。建议按下面的SQL创建一个账号CREATE USER archery% IDENTIFIED BY YourPass2024; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, CREATE VIEW, SHOW VIEW, PROCESS, SUPER ON *.* TO archery%; FLUSH PRIVILEGES;这里为什么需要PROCESS和SUPER权限因为Archery做SQL审核时需要获取当前数据库的线程列表和会话信息以便判断当前是否存在长事务、锁等待等高危场景。没有这两个权限功能会部分失效。测试连接填完参数后点击“测试连接”Archery会尝试连接目标库并校验账号权限。如果提示连接失败优先检查网络连通性和账号权限。MySQL接入完成后建议提交一条最简单的SELECT查询工单验证一遍完整流程开发提交查询申请DBA审核通过执行并返回结果。流程走通说明这个实例真正可用了。4.3 接入PostgreSQL实例注意schema与权限PostgreSQL在复杂查询、地理信息等场景下非常受欢迎Archery对它的支持也比较成熟。新增实例时类型选PostgreSQL主机端口默认填5432。接入PostgreSQL时有三个细节需要特别留意第一账号权限模型和MySQL完全不同。PostgreSQL使用“角色”体系建议为Archery单独创建专用角色CREATE USER archery WITH PASSWORD YourPass2024; GRANT CONNECT ON DATABASE yourdb TO archery; GRANT USAGE ON SCHEMA public TO archery; GRANT SELECT ON ALL TABLES IN SCHEMA public TO archery; GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO archery;如果还要执行DDL需要额外授予相应的权限。很多人在这里图省事直接给了超级用户权限我不推荐一是审计留痕会混淆操作者二是一旦账号被滥用影响范围太大。第二schema的选择。PostgreSQL默认是public但很多业务会自建schema。在Archery实例配置中指定正确的schema否则会出现“表不存在”的问题。第三驱动兼容性。Archery通过psycopg2连接PostgreSQL如果实例是PostgreSQL 12以上版本驱动一般没问题。如果是老版本建议升级Archery镜像到最新版本避免驱动兼容性报错。4.4 接入ClickHouse实例分析场景的另类玩法ClickHouse接入Archery的场景通常是大数据部门做OLAP分析开发需要跑一些查询但这些查询可能很重会对ClickHouse集群造成压力。这时候用Archery做审核和限流就非常有价值。新增ClickHouse实例时关键配置和MySQL/PostgreSQL略有不同数据库类型选ClickHouse端口ClickHouse有HTTP端口默认8123和Native端口默认9000Archery通常走HTTP端口。填8123即可不需要填9000。账号权限ClickHouse的权限控制比较特殊可以为Archery单独建一个账号只授予只读权限并根据需要限制查询的内存和超时。CREATE USER archery IDENTIFIED WITH plaintext_password YourPass2024; GRANT SELECT ON *.* TO archery;如果ClickHouse开启了readonly1Archery执行查询不会有问题但执行DDL或INSERT类工单会被拒。这是正常的ClickHouse的生产环境通常也是这种安全模式。ClickHouse接入有一个特别值得注意的点Archery的审核规则是基于MySQL语法规则设计的ClickHouse的SQL语法和一些函数跟MySQL有差异。所以ClickHouse实例的“审核”能力会比MySQL弱一些更多是流程管理和查询权限控制。这一点在团队内推广的时候要提前说明避免开发误以为CRC代码审查层面的规则也能完全覆盖ClickHouse。4.5 资源组与用户权限让合适的人做合适的事实例接入完成后还差最后一步把实例和用户绑定到资源组。Archery的权限模型是“用户 - 资源组 - 实例”只有把用户加入某个资源组用户才能在该资源组下的实例上提交工单或发起查询。进入“资源组”页面新增一个资源组比如“订单业务组”然后把刚才接入的三个实例都加入这个资源组再把开发人员和DBA账号加入进来。注意用户权限分两种DBA角色可以审核和执行工单权限较大严格控制人数。开发角色只能提交工单和发起查询不能审核自己的工单。我见过很多团队部署完Archery所有账号都给超级管理员权限结果审计日志完全失去意义。规范的做法是超级管理员只留1到2个人其余人都按角色分配DBA负责审核开发负责提交。5. 常见问题与排查技巧实录5.1 高频问题速查表把这几年用Archery过程中遇到的典型问题整理成一张速查表部署时遇到问题可以直接对照问题现象可能原因解决方法Docker Desktop启动失败提示virtualization support not detected宿主机虚拟化没开启或WSL2未正确安装进BIOS开启VT-x/AMD-V开启“虚拟机平台”和WSL2功能docker compose up报端口已占用宿主机端口被已有服务占用修改docker-compose.yml中的端口映射Archery容器启动后立刻退出环境变量配置错误或MySQL还没就绪docker logs archery-web查看日志确认MYSQL_HOST、MYSQL_PASSWORD正确python3 manage.py migrate报连接MySQL失败MySQL尚未完成初始化或者MYSQL_HOST配置错误等待MySQL就绪后重试确认容器间使用服务名通信新增实例测试连接失败网络不通、账号权限不足、端口填错从Archery容器内ping目标实例检查账号权限和端口连接MySQL 8.0时报认证协议错误目标库的认证插件是caching_sha2_passwordArchery驱动不支持创建账号时指定IDENTIFIED WITH mysql_native_password BY 密码工单提交后一直处于等待执行状态task容器没起来或Redis没连上检查task容器状态确认Redis环境变量配置正确ClickHouse实例能查但执行DDL失败账号只读权限或ClickHouse只读模式按需调整账号权限或在ClickHouse配置中关闭readonly页面中文乱码系统库字符集不是utf8mb4在MySQL容器启动命令中增加--character-set-serverutf8mb45.2 实操中踩过的几个大坑坑一容器名和实例地址混为一谈新增MySQL实例的时候如果你填的是localhost:3306从Archery容器内部访问到的不是宿主机的MySQL而是容器自己。宿主机上的数据库要从容器内访问需要填宿主机的内网IP或者把端口映射出来用宿主机IP访问。这个细节是新手最常见的失误菜鸟教程里几乎没人提。坑二MySQL 8.0的认证插件兼容问题MySQL 8.0默认的认证插件是caching_sha2_password但Archery内置的MySQL驱动在某些版本下对它有兼容问题表现为“测试连接失败”或者“认证插件不支持”。解决方案是创建专用账号时显式指定CREATE USER archery% IDENTIFIED WITH mysql_native_password BY YourPass2024;这个坑我在第一次部署时折腾了将近一个下午最后查驱动源码才定位到。现在每个环境接入MySQL我都直接用这个写法省事很多。坑三容器启动顺序导致初始化失败docker-compose的depends_on只保证服务启动顺序不保证MySQL“可用”。如果MySQL容器还在初始化数据目录Archery就已经开始连数据库必然报错。init时不要急先用docker logs archery-mysql查看MySQL日志看到类似ready for connections的日志再执行Archery的迁移命令。坑四忘挂载数据卷有同事把Archery部署在测试环境用了一个月后来为了升级镜像删掉容器结果所有配置、工单、审计记录灰飞烟灭。Archery的元数据全在系统MySQL里如果MySQL容器没有把数据目录挂载到宿主机删容器删数据。所以我强烈建议在部署开始时就把数据卷挂载做好这比任何高级配置都重要。5.3 日常维护与备份建议Archery上线之后日常维护主要围绕三件事第一定期备份系统库。Archery的元数据库是整个平台的“大脑”所有用户、实例、工单、审计记录都在里面。我的习惯是每天凌晨用mysqldump做一次全量备份保留7天。命令行可以直接写在宿主机cron里docker exec archery-mysql mysqldump -uarchery -pArcheryPass2024 archery /backup/archery_$(date %F).sql第二观察容器状态。上线初期最容易出现task容器内存飙升的情况尤其是大量工单同时执行时。用docker stats看一眼实时资源如果内存持续偏高考虑给task容器加上内存限制。第三升级前先看变更记录。Archery迭代速度还算快但每次升级数据库表结构可能都有变化。升级前一定先备份然后用新镜像启动一个测试容器验证没问题再替换生产环境。直接在生产环境硬升级万一数据迁移脚本有问题工单和审计记录很可能出问题。结尾一个老DBA的心里话最后再分享一点个人经验。Archery这套系统部署起来不难难的是让它真正在团队里落地。我第一次部署的时候流程跑通了但开发根本不乐意用觉得在Web上提SQL比直接连数据库麻烦多了。后来我们做了两件事扭转了局面一是把审核规则和开发团队公开对齐让规则透明二是让DBA在工单里写清楚驳回原因不搞一言堂。工具是死的流程是活的。Archery能把“数据库变更”这件高风险的事变得有章可循但真正让它发挥价值还是靠团队一起把规范立起来。希望这篇教程能帮你少走一些弯路少踩几个坑。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →