CodeCombat离线部署踩坑记:从循环跳转到VIP权限,我的避坑指南

张开发
2026/4/10 21:50:18 15 分钟阅读

分享文章

CodeCombat离线部署踩坑记:从循环跳转到VIP权限,我的避坑指南
CodeCombat离线部署踩坑记从循环跳转到VIP权限我的避坑指南去年夏天我在为本地编程兴趣小组搭建CodeCombat离线环境时遭遇了一系列令人抓狂的技术陷阱。本以为按照官方文档就能轻松搞定结果从首页无限循环跳转到关卡权限锁定几乎每一步都踩中了隐藏的深坑。这篇文章将分享我最终验证通过的完整解决方案特别是那些文档里没写的细节。1. 环境准备阶段的隐形陷阱很多人会直接跳过环境检查环节但这恰恰是后续问题的根源。我的服务器配置是Ubuntu 22.04 LTSDocker版本20.10.21。看似符合要求实则暗藏玄机。首先要注意的是端口冲突检测。执行以下命令检查3000和9485端口占用情况sudo lsof -i :3000 sudo lsof -i :9485如果发现已有服务占用要么修改映射端口如改为13000:3000要么停用冲突服务。我遇到过Nginx占用了3000端口导致容器启动失败的案例。另一个关键点是存储卷权限。创建目录时务必加上-pv参数确保父目录存在mkdir -pv /data/codecombat/{data,mongo}然后必须修正权限否则容器内部会因写入失败而崩溃chown -R 1000:1000 /data/codecombat注意这里的1000对应容器内coco用户的UID不同镜像可能不同2. 容器启动失败的深度排查当执行docker run命令后如果容器状态显示为Exited别急着删了重试。先用以下命令查看日志docker logs --tail 50 容器ID常见错误包括MongoDB连接失败检查mongo卷是否为空数据文件缺失确认dump.zip已解压到/data/codecombat/data权限不足重新执行chown修正权限我遇到最棘手的问题是dump文件版本不匹配。下载的离线包可能包含测试数据导致关卡加载异常。解决方法是用mongo shell清理旧数据use coco db.dropDatabase()然后重新导入纯净的dump数据。3. 循环跳转问题的终极解决方案文档里轻描淡写的建议本机部署背后其实是个大坑。当通过外网IP访问时会出现无限重定向到/login的问题。经过抓包分析发现是以下机制导致前端检测到host不是localhost时强制跳转到/login?redirect%2F但登录后仍判断host非法进入死循环治本方案是修改前端配置。进入容器内部docker exec -it 容器ID bash vi /home/coco/codecombat/server/config.coffee找到config.allowedHostnames部分添加你的外网域名或IPconfig.allowedHostnames [ localhost 127.0.0.1 你的域名或IP ]重启服务使配置生效supervisorctl restart all如果不想修改配置也可以用Nginx反向代理方案server { listen 80; server_name your-domain.com; location / { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }4. VIP权限解锁的完整指南默认注册的账号只能体验基础关卡要解锁全部内容需要修改用户权限。文档中的mongo命令有几个易错点db.users.update( {name:admin}, // 注意这里是name不是username { $set: { earned.gems: 9999999, permissions: [godmode,admin], permissionsBackup: [godmode,admin] // 关键补丁 } }, true, // upsert false // multi )常见问题排查表现象可能原因解决方案修改无效字段名错误确认用name而非username权限时有时无缺少backup字段添加permissionsBackup宝石不显示数据类型错误确保gems是Number类型更稳妥的做法是直接复制官方管理员账户的权限结构。先查询默认管理员db.users.findOne({permissions: {$in: [admin]}})然后将其权限结构复制到你的账户。5. 进阶配置与性能优化部署稳定后还可以通过以下调整提升体验关卡加载加速# 在容器内执行 mongo coco --eval db.levels.createIndex({slug: 1}) mongo coco --eval db.components.createIndex({original: 1})自定义关卡将自制关卡JSON放入/data/codecombat/data/levels在mongo中注册新关卡db.levels.insert({ name: 自定义关卡, slug: my-level, // 其他元数据 })多语言支持 修改config.coffee中的语言配置config.supportedLanguages [en, zh, es]6. 异常情况应急处理当出现异常时可以尝试以下诊断命令检查服务状态docker exec -it 容器ID supervisorctl status重置特定关卡db.level.sessions.update( {levelID: ObjectId(关卡ID)}, {$set: {state: {complete: false}}}, {multi: true} )清理僵尸进程# 在宿主机执行 docker exec -it 容器ID bash -c pkill -f node.*codecombat经过三天的反复调试这套离线环境最终稳定运行至今。最深刻的教训是每个看似简单的步骤背后都可能藏着需要特定处理方式的细节。现在我们的编程社团每周都会在这个平台上举办代码竞技活动看着学员们一边闯关一边掌握编程概念当初踩的那些坑都值得了。

更多文章