腾讯TCA代码分析平台docker部署问题排查实战记录

📅 2026/6/27 8:00:31
腾讯TCA代码分析平台docker部署问题排查实战记录
TCA 代码分析平台私有化部署踩坑实录从零到跑通的十四场硬仗如果你也在折腾 TCA腾讯代码分析平台的私有化部署这篇文章可能能帮你少走不少弯路。从环境配置、容器启动、数据库连接到文件服务器认证、数据格式兼容我踩了一个又一个坑最后终于跑通了。这篇文章把整个过程完整记录下来希望对同样在部署 TCA 的朋友有所帮助。前言TCATencent Code Analysis是腾讯开源的代码分析平台支持代码规范、重复代码、圈复杂度等多种分析维度。功能很强大但私有化部署的坑也不少它的开源仓库地址是GitHub - Tencent/CodeAnalysis: Static Code Analysis - 静态代码分析 · GitHub我按照官方文档一步步部署以为能顺利跑起来结果遇到一连串的问题从 BOM 字符导致配置解析失败到数据库密码格式错误再到文件服务器认证、数据格式兼容……这篇文章不是什么高深的技术分享就是一份完整的踩坑实录。一共十四场硬仗咱们从头说起。第一阶段部署启动 —— 最基础的问题也是最烦人的第一场节点资源找不到 —— 工具没地方跑问题现象刚部署完创建代码分析任务直接报当前项目配置的运行环境标签[Codedog_Linux]没有机器资源可以运行工具[cpd(None);lizard(None);codecount(None)]意思是没有机器注册到这个标签下工具找不到执行环境。排查思路TCA 的执行架构是主节点 分析节点分析节点需要注册并关联标签主节点才能把任务分配过去。解决方案在分析节点上执行注册操作把节点关联到Codedog_Linux标签确认节点服务已启动在节点管理页面注册节点给节点添加Codedog_Linux标签注册成功后工具就能找到执行环境了。第二场docker-compose.yml 有 BOM 字符 —— 配置解析失败问题现象启动容器时环境变量怎么都不生效。明明在.env.local里配置了各种参数容器里却读不到。排查思路环境变量不生效可能是 docker-compose.yml 解析有问题。用编辑器打开一看文件开头有个奇怪的符号 ——BOM 字符BOMByte Order Mark是 UTF-8 编码的一个特殊标记有些编辑器会自动加上但 docker-compose 解析 YAML 时不认这个导致整份配置文件解析失败。解决方案用 PowerShell 去掉 BOM 字符(Get-Contentdocker-compose.yml-Raw)-replace^|Set-Contentdocker-compose.yml-NoNewline去掉 BOM 后重新启动容器环境变量终于生效了。第三场页面空白 502 Bad Gateway —— 容器没启动成功问题现象访问 Web 页面直接空白浏览器还报 502 Bad Gateway。排查思路502 意味着 Nginx 代理失败了。检查一下后端容器状态dockerps发现main-server容器根本没在运行找到真凶查看容器日志docker logs codeanalysis-main-main-server-1日志显示数据库连接失败容器启动就挂了。第四场数据库连接失败 —— 密码格式坑人问题现象main-server容器启动失败日志报Access denied for user rootmysql数据库密码认证失败。排查思路密码明明是对的怎么会认证失败仔细检查.env.local文件MAIN_DB_PASSWORDTCA!#2021好家伙密码周围有单引号Django 读环境变量的时候把引号也当密码的一部分了当然认证失败。解决方案去掉单引号MAIN_DB_PASSWORDTCA!#2021重启容器数据库连接成功页面终于能打开了。第五场Nginx 配置语法错误 —— if 语句里不能用带 URI 的 proxy_pass问题现象页面能打开了但访问文件服务器的 API 还是报错。检查 Nginx 日志发现 Nginx 启动失败。排查思路看 Nginx 配置文件有这么一段if ($http_authorization) { proxy_pass http://file-nginx:8004/api/files/; }Nginx 的 if 语句里不能直接用带 URI 的proxy_pass这是语法错误。解决方案用 set 指令定义变量避免直接在 if 中使用 URIset $target http://file-nginx:8004/api/files/; if ($http_authorization) { proxy_pass $target; }或者干脆不用 if用 location 匹配更清晰location /api/files/ { proxy_pass http://file-nginx:8004/api/files/; proxy_set_header Authorization $http_authorization; }第六场容器间 DNS 解析失败 —— nginx 主机名找不到问题现象修好 Nginx 配置后分析服务器还是报错DNS resolution failed for hostname: nginx分析服务器容器找不到nginx这个主机名。排查思路Docker 容器之间是通过 Docker 内部 DNS 解析主机名的。有时候 DNS 缓存有问题或者容器网络没正确连接。解决方案重启分析服务器容器刷新 DNS 缓存docker restart codeanalysis-main-analysis-worker-1重启后 DNS 解析正常容器之间能互相通信了。第七场文件服务器 URL 格式错误 —— bucket 名称不能少问题现象容器之间能通信了但访问文件服务器还是报错app只允许为数字和字母且长度不允许超过40排查思路这个错误是文件服务器校验 bucket 名称时报的。看环境变量FILE_SERVER_URLhttp://nginx:8000/api/files/URL 里没有 bucket 名称文件服务器期望 URL 格式是/api/files/{bucket}/。解决方案在 URL 里加上 bucket 名称codedogFILE_SERVER_URLhttp://nginx:8000/api/files/codedog/第八场环境变量没更新 —— 容器还在用旧配置问题现象改了环境变量但容器里还是旧值。排查思路Docker 容器的环境变量是在容器创建时读入的修改.env.local后容器不会自动更新。解决方案停止并删除容器用 docker-compose 重新创建docker-compose down docker-compose up-d或者直接重建特定容器dockerrm-f codeanalysis-main-analysis-worker-1 docker-compose up-d analysis-worker第二阶段任务执行 —— 文件服务器认证问题经过上面八场硬仗TCA 终于能启动了页面能打开了任务也能创建了。但运行任务时又遇到了新的问题。第九场文件服务器 401 —— Token 对不上号问题现象代码分析任务执行到一半报Fail to send result to file server! Error: HTTP Error 401: Unauthorized页面上弹出文件服务器异常的提示。排查思路401 Unauthorized认证失败。检查 Token 配置环境变量里FILE_SERVER_TOKEN657577ac0ef4c135a0d406b4433ce00b0fd28299文件服务器数据库里e91e0a1463f9a260f2b1efe756c2d0bfccbfb22a两个 Token 完全不一样可能是初始化脚本创建了默认 Token但我后来又配置了不同的 Token两边没同步。解决方案更新数据库里的 TokenDELETEFROMauthtoken_token;INSERTINTOauthtoken_token(key,created,user_id)VALUES(657577ac0ef4c135a0d406b4433ce00b0fd28299,NOW(),1);第十场文件服务器 403 —— 目录创建者为空问题现象Token 认证通过了但上传文件报 403 Forbidden“无操作权限”。排查思路403 是权限问题。文件服务器里的目录是有权限控制的fromapps.file.modelsimportAppUnit unitAppUnit.objects.get(namecodedog/public_server_temp)print(unit.creator)# 空字符串目录的创建者是空字符串导致codedog用户没有写权限。解决方案unit.creatorcodedogunit.save()第三阶段数据入库 —— 数据格式兼容问题文件服务器的问题解决了任务能执行了但到了数据入库环节又来了一连串的问题。第十一场result 数据藏在子对象里问题现象入库失败报KeyError: cloc_tuple_definition排查思路下载工具返回的结果数据{result:{files:{...},cloc_tuple_definition:[...]}}数据都在result子对象里不在顶层代码直接从顶层读字段当然找不到。解决方案修改codecounthandler.pydefdownload_result_data(self):raw_datadownload_and_load_json_file(self._task_result[result_data_url])self._result_dataraw_data.get(result,raw_data)第十二场last_modifier 字段集体失踪问题现象刚修好 codecountcpd 的入库又挂了KeyError: last_modifier排查思路cpd 工具返回的数据里压根没有last_modifier字段。可能老版本有新版本没了。解决方案把所有直接访问改成.get()加默认值duphandler.py里一共 6 处owneritem.get(last_modifier,)第十三场result_summary 字段也不全问题现象KeyError: duplication_rate解决方案self._dup_scan.duplicate_rateself._result_summary.get(duplication_rate,0)self._dup_scan.total_duplicate_line_countself._result_summary.get(total_duplicate_line_count,0)self._dup_scan.total_line_countself._result_summary.get(total_line_count,0)第十四场lizard 工具返回的不是 zip问题现象zipfile.BadZipFile: File is not a zip file排查思路cchandler.py默认把结果文件当 zip 解压但 lizard 返回的是 JSON不是 zip下载 lizard 的结果数据看看{result:{summary:{...},detail:[{path:xxx.c,issues:[...],...}]}}结构完全不一样解决方案这是最大的一次改动修改cchandler.py的多个方法download_result_data先判断是否有result字段有就是新格式直接读 JSON没有就是旧格式解压 zipread_cc_issue_data新格式直接遍历detail旧格式从文件逐行读字段访问全部加默认值验证通过 —— 终于跑通了所有修复完成后重新运行代码分析任务✅ codecount代码统计入库成功✅ cpd重复代码检测入库成功✅ lizard圈复杂度检测入库成功页面上也能正常看到分析结果了。下面这几张分析结果历史截图把整个心酸过程体现的淋漓尽致不过最终亮绿色标时的那种喜悦也是成就感满满v下面这张图就是第一次成功分析的结果截图啦经验总结折腾了这么多问题总结几条经验1. 细心检查配置文件格式BOM 字符、单引号包裹密码、YAML 语法错误这些细节问题最容易忽略但往往导致整个系统启动失败。2. 环境变量改了要重启容器Docker 容器不会自动读取新的环境变量必须停止并删除容器用 docker-compose 重新创建。3. 日志是最好的老师遇到问题别瞎猜先看日志。docker logs一看错误堆栈明明白白。4. 数据格式一定要确认工具升级后返回的字段可能增增减减。代码里最好都用.get()加默认值别直接dict[key]。5. 兼容新旧格式是个好习惯不确定数据格式会不会变就写兼容逻辑。raw_data.get(result, raw_data)这种写法既简单又安全。改动文件清单阶段文件/配置改动内容部署docker-compose.yml去掉 BOM 字符部署.env.local密码去掉单引号URL 加上 bucket 名称部署nginx.conf修复 if 语句语法错误运行数据库authtoken_token表更新 Token运行数据库AppUnit表设置目录创建者入库codecounthandler.py兼容新旧数据格式入库duphandler.py修复字段缺失问题入库cchandler.py兼容 lizard 工具的 JSON 格式写在最后私有化部署开源项目踩坑是难免的。这篇文章记录了从部署到运行到入库的十四个问题希望能帮到同样在折腾 TCA 的你。遇到问题别慌一个一个解决总能跑通的也可以关注私信我wei(软趴趴的工程师)