Dokku 应用部署成功后访问报 Bad Gateway 怎么排查?
2026/9/12 11:14:12 网站建设 项目流程

Dokku 应用部署成功后访问报 Bad Gateway 怎么排查?

【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku

在 Dokku 上最常见的“假性部署失败”是:git push全程无报错、deploy 阶段也全部走完,但用浏览器或 curl 访问应用域名时却返回502 Bad Gateway。出现这个现象时,问题通常不在构建,而在 nginx 代理与应用容器之间。

Dokku 用 nginx 做默认代理,请求被转发到应用的web进程容器。官方文档给出了两个与 502 直接相关的事实:

  • 自 0.38.0 起,当一个应用尚未部署、没有web进程类型、或没有运行中的 web 进程时,Dokku 会生成一个最小 nginx 配置,直接返回502 Bad Gateway,以便域名可解析、监控工具能探测到非 200 状态码;
  • 排障文档则指出,部署成功但访问报Bad Gateway时,常见原因是应用没有使用 Dokku 分配的PORT端口,或只监听了127.0.0.1而没有绑定0.0.0.0

下面的排查顺序对应这两类原因:先确认 web 进程在跑,再看日志,然后核对端口映射与监听,最后检查 nginx 侧配置和错误日志。所有命令在 Dokku 主机上执行,文中以文档示例中的应用名node-js-app为例,请替换成你的实际应用名。

先确认:是否有运行中的 web 进程

Dokku 的 nginx 代理默认只代理web进程(其他进程类型需要自定义nginx.conf.sigil处理)。如果web进程不在,502 就是上面说的预期行为。另外要注意:dokku ps:stop停掉应用后访问返回 502 也是文档明确记载的正常现象,此时用ps:start恢复即可。

先用ps:report看应用状态:

dokku ps:report node-js-app

文档示例输出(注意其中会随应用状态变化的字段):

=====> node-js-app ps information Deployed: false Processes: 0 Ps can scale: true Ps computed restart policy: on-failure:10 Restore: true Running: false

重点看DeployedRunning两项。也可以只取单个值:

dokku ps:report node-js-app --deployed dokku ps:report node-js-app --running

DeployedfalseRunningfalse时,说明当前根本没有可代理的 web 容器,先解决进程问题再谈端口。可以用ps:scale查看 formation 里web的数量:

dokku ps:scale node-js-app

文档示例输出:

-----> Scaling for python proctype: qty --------: --- web: 1

如果web计数为 0,按你的部署方式处理:

  • Procfile没有声明web进程类型:补充web行并重新部署。初始部署时 Dokku 默认只把web进程自动扩到 1 个实例,其他进程类型需要显式声明或ps:scale
  • 进程被停掉了:dokku ps:start node-js-app
  • 容器启动后又退出:dokku ps:restart node-js-app web只重启 web 进程类型,再结合下一步的日志看退出原因。Dokku 默认对非零退出的容器应用on-failure:10重启策略,即同一个容器最多自动重启 10 次,超过后需要介入。

查看 web 进程日志,判断容器为何起不来

进程存在但反复退出、或者根本没监听端口,日志里通常能看到原因:

# 查看应用日志 dokku logs node-js-app # 持续跟踪 web 进程日志 dokku logs node-js-app -t -p web # 查看上一次失败部署的日志 dokku logs:failed node-js-app

注意dokku logs是“live tailing”,历史部署的日志通常拿不到;logs:failed保存的日志在默认 docker-local 调度器下也只保留到下一次部署或旧容器被垃圾回收为止,需要留档的话应接入日志转发。

如果日志指向配置或环境问题,还可以直接进容器排查:

# 进入 web 进程容器 dokku enter node-js-app web

核对应用监听的端口与绑定地址

这是排障文档对Bad Gateway给出的两个主要结论:

  1. 应用应当使用 Dokku 设置的PORT环境变量,而不是写死端口。文档给出的示例写法:

    var port = process.env.PORT || 3000
  2. 应用应当绑定到所有接口(0.0.0.0)。很多框架默认只监听127.0.0.1,容器在跑但 nginx 从宿主机连不进去,表现就是 Bad Gateway。

端口映射侧的文档依据(来自 Port Management 文档):

  • buildpack 部署的应用必须遵循PORT环境变量。Dokku 通常将其设为5000但不保证固定;如果不遵循,容器会启动、但服务在容器外不可访问。
  • 未使用EXPOSE指令的 Dockerfile 应用默认走5000端口(与 buildpack 行为一致);使用了EXPOSE的应用会在相同端口号上公开监听。
  • 不要手动覆盖PORT环境变量,Dokku 通过端口映射来设置它的值,手动覆盖可能造成路由问题。

确认当前端口映射是否如预期:

dokku ports:list node-js-app

文档示例输出:

-----> Port mappings for node-js-app -----> scheme host port container port http 80 5000

或者用 report 形式,同时显示“检测到的映射”(来自EXPOSE或运行容器)与“配置的映射”:

dokku ports:report node-js-app
=====> node-js-app ports information Port map detected: http:80:5000 Port map: http:80:5000 https:443:5000

根据结果修正:

  • 应用代码没读PORT:修改代码(见上面的process.env.PORT写法)后重新部署。

  • Dockerfile 用EXPOSE暴露了非预期端口(例如EXPOSE 1234导致映射成http:1234:1234,访问 80 端口自然不通):按文档推荐做法调整映射:

    # add a port mapping to port 80 dokku ports:add node-js-app http:80:1234 # remove the incorrect port mapping dokku ports:remove node-js-app http:1234:1234
  • 端口映射被误配成其他值(例如http:5000:5000):用ports:set重新指定,例如dokku ports:set node-js-app http:80:5000,映射格式为scheme:host-port:container-port

  • 确认无误但映射已被清掉:dokku ports:clear会清除全部映射,重新部署前不要误用;需要整体重设时用ports:set

另一个容易混淆的现象:如果访问看到的是nginx 默认页而不是 502,排障文档把它归为另一类问题(多为 nginx 的server_names_hash_bucket_size或 Dockerfile 中EXPOSE引起),处理方式见 排障文档,不要与 502 混在一起排查。

检查 nginx 配置与错误日志

前面两步都正常、应用确实在监听正确端口时,问题可能出在 nginx 侧。Dokku 为每个应用生成独立的 nginx 配置,访问日志和错误日志默认写在/var/log/nginx/${APP}-access.log/var/log/nginx/${APP}-error.log

# 查看该应用 nginx 错误日志(-t 可持续跟踪) dokku nginx:error-logs node-js-app # 查看该应用生成的 nginx 配置 dokku nginx:show-config node-js-app # 查看 nginx 属性报告(超时、绑定地址等) dokku nginx:report node-js-app

在主机上直接验证 nginx 整体配置:

nginx -t

排障文档给出的示例:配置不合法时会得到类似nginx: [emerg] could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32的报错,此时编辑/etc/nginx/nginx.conf,在http段加入server_names_hash_bucket_size 64;,然后:

dokku nginx:stop dokku nginx:start

Dokku 也提供了封装好的验证命令:

dokku nginx:validate-config node-js-app

注意文档说明:各应用配置实际运行在共享上下文中,某个应用配置单独验证不合法、但在全局上下文中合法的情况是存在的,所以该命令的退出码取的是nginx -t对服务器真实配置的退出码。

如果怀疑代理配置漂移(比如 web 容器重建后 nginx 还指向旧地址),可以强制重建该应用的代理配置:

dokku proxy:build-config node-js-app

文档提醒:当应用当前没有 web 监听器时,这条命令可能失败。也就是说,如果这里直接报错,反过来印证问题仍在 web 进程侧,回到第一步继续查。

验证恢复

修改后,用文档中同样的方式确认代理链路通了:

curl http://node-js-app.dokku.me

Port Management 文档的示例输出(仅为文档示例,实际内容取决于你的应用):

Hello World!

返回应用自身响应而不是 502 页面,即代表代理到 web 容器的链路已恢复。

边界与限制

  • 0.38.0 起,“没有运行中的 web 进程 = 返回 502”是刻意设计的最小配置,不是故障。该 502 错误页自带自动重试脚本,应用恢复后会自行刷新。如果你的监控系统依赖非 200 状态码探测,这个行为正好可用。
  • 使用自定义nginx.conf.sigil模板的用户注意:0.38.0 起,DOKKU_APP_WEB_LISTENERS变量在没有运行中 web 进程的应用上可能为空,模板需要自行处理(例如用条件判断在空时return 502),细节见 0.38.0 迁移指南。
  • 如果web进程成功启动而其他进程部署失败,nginx 可能最终停止路由请求,文档给出的处理是回滚代码,或手动执行dokku proxy:build-config <app>让请求路由到新 web 容器。

参考文档:排障文档、Nginx 代理、端口管理、进程管理、代理管理、日志管理、进入容器。

【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询