Dokku 进程管理完全指南:ps 插件详解与源码级原理剖析
【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku
导读
本文是 Dokku(基于 Docker 的 PaaS 平台)进程管理模块的完整技术指南,以官方文档 docs/processes/process-management.md 为骨架,结合 plugins/ps 插件的 Go 源码与 Shell 触发器逐层展开。你将掌握ps:scale、ps:restart、ps:rebuild、ps:report等全部 ps 命令族的实战用法,理解Procfile、app.jsonformation、重启策略(restart policy)与服务器重启自动恢复(ps:restore)的底层实现机制,并能针对多进程应用(web/worker 等)独立完成扩缩容、启停与故障恢复的运维工作。该功能自 0.3.14 引入,0.7.0 起大幅增强,是 Dokku 应用生命周期管理中承上启下的核心组件。
一、ps 命令族总览
ps 插件通过dokku ps:*命令统一管理应用的进程生命周期。所有子命令均可通过dokku help ps查看:
| 命令 | 作用 |
|---|---|
ps:inspect <app> | 输出应用容器的脱敏版docker inspect结果 |
ps:rebuild [--parallel count] [--all\|<app>] | 从源码重新构建应用 |
ps:report [<app>] [<flag>] | 输出一个或多个应用的进程报告 |
ps:restart [--parallel count] [--all\|<app>] [<process-name>] | 重启应用(或指定进程类型) |
ps:restore [<app>] | 启动此前正在运行的应用(如服务器重启后) |
ps:scale [--skip-deploy] [--format stdout\|json] <app> [<proc>=<count>...] | 读取/设置各进程类型运行实例数 |
ps:scale --replace [--skip-deploy] <app> <proc>=<count>... | 用指定进程类型整体替换现有 formation,未指定的进程类型归零 |
ps:scale --clear [--skip-deploy] <app> | 将 formation 重置为默认规模 |
ps:set <app> <key> <value> | 设置或清除应用的 ps 属性 |
ps:start [--parallel count] [--all\|<app>] | 启动应用 |
ps:stop [--parallel count] [--all\|<app>] | 停止应用 |
从源码结构看,这些命令的 CLI 入口位于 plugins/ps/subcommands.go(对应CommandInspect、CommandRebuild、CommandScale等函数),命令的 Schema 定义在 plugins/ps/plugin.toml,实际执行逻辑则下沉到 plugins/ps/ps.go 与 plugins/ps/functions.go 中,并通过 plugn trigger 机制调用 scheduler、proxy 等其它插件——这是理解整个命令族的关键前提。
二、查看应用运行状态
2.1 用ps:inspect安全地检查容器(0.13.0 新增)
管理员经常需要对应用容器执行docker inspect。直接操作 Docker CLI 容易出错,且未经处理会暴露敏感环境变量。Dokku 通过ps:inspect提供了安全包装:
dokku ps:inspect node-js-app该命令会收集应用的全部运行中容器 ID,调用docker inspect,并对输出做脱敏处理(sanitize),使其可以被安全地复制粘贴到其它地方。其实现位于 plugins/ps/subcommands.go 的CommandInspect:先通过common.VerifyAppName校验应用名,再调用scheduler-inspect触发器,把具体的 inspect 行为交给当前应用的调度器(如scheduler-docker-local)完成。
2.2 用ps:report查看进程报告(0.12.0 新增)
ps:report可以输出应用与 ps 相关的全部属性与运行状态:
dokku ps:report输出示例(针对多个应用):
=====> node-js-app ps information Deployed: false Processes: 0 Ps can scale: true Ps computed procfile path: Procfile2 Ps computed restart policy: on-failure:10 Ps global procfile path: Procfile Ps global restart policy: Ps restart policy: Ps procfile path: Procfile2 Restore: true Running: false =====> python-sample ps information ...也可以只查询单个应用:
dokku ps:report node-js-app还可以通过 flag 只输出某一项的值,方便脚本化解析:
dokku ps:report node-js-app --deployed关于ps:report的全部 flag 及其 JSON 输出格式,详见下文"九、属性系统与 ps:report 详解"。
三、重建与重启应用
3.1ps:rebuild:从源码重新构建
某些场景下需要手动重建应用,例如:某些命令本身不会触发重建,或者连续设置多个配置项后希望跳过中间重建、最后一次性重建。此时使用ps:rebuild:
dokku ps:rebuild node-js-app- 使用
--all标志重建所有应用:
dokku ps:rebuild --all- 默认情况下,重建所有应用是串行执行的。可用
--parallel控制并发度:
dokku ps:rebuild --all --parallel 2- 将
--parallel设为-1,worker 数量将自动取当前机器的 CPU 核数:
dokku ps:rebuild --all --parallel -1从源码看,CommandRebuild(plugins/ps/subcommands.go)在--all时通过common.RunCommandAgainstAllApps分发,单应用时最终调用 plugins/ps/ps.go 的Rebuild函数——它本质上是触发了receive-app触发器,即把应用重新当作一次新的 git 接收来走完整的构建流程。因此,重建期间若链接的服务容器缺失,将导致应用无法启动,请确保相关服务均已就绪后再执行重建。
3.2ps:restart:重启应用
重启单个应用:
dokku ps:restart node-js-app也可以指定单个进程类型(如web或worker)重启。注意:不支持指定某进程类型的单个实例,只能重启该进程类型的全部实例:
dokku ps:restart node-js-app web使用--all重启所有应用,该标志与指定进程类型互斥:
dokku ps:restart --all同样支持--parallel与--parallel -1(自动按 CPU 数并发):
dokku ps:restart --all --parallel 2 dokku ps:restart --all --parallel -1源码层面(plugins/ps/ps.go):Restart首先通过common.IsDeployed判断应用是否部署过;随后读取当前运行镜像的deployed-image-tag属性——若缺失则回退到完整的release-and-deploy流程,否则直接以appName + imageTag(可选processName)调用deploy触发器完成原地重启。CommandRestart中明确校验了"指定进程名时不能与--all同时使用"(见 plugins/ps/subcommands.go)。
与重建同理:缺失链接容器会导致应用启动失败,执行重启前应保证服务全部就绪。
四、启动与停止应用
4.1ps:stop:停止应用
停止应用会关闭其全部运行容器。对于默认的 nginx 代理实现,停止后的应用将返回502 Bad Gateway:
dokku ps:stop node-js-app停止所有应用:
dokku ps:stop --all同样支持--parallel控制并发(默认串行,-1自动按 CPU 数):
dokku ps:stop --all --parallel 2 dokku ps:stop --all --parallel -1实现上(plugins/ps/ps.go),Stop依次触发scheduler-stop与post-stop触发器。关键细节:post-stop触发器(plugins/ps/triggers.go)会把应用的restore属性写为false——这正是"手动停止的应用在服务器重启后不会被自动拉起"的机制来源。
4.2ps:start:启动应用
启动所有已停止的容器:
dokku ps:start node-js-appps:start与ps:restart的行为类似,但若应用容器已在运行则不会做任何操作。启动所有应用:
dokku ps:start --all dokku ps:start --all --parallel 2 dokku ps:start --all --parallel -1从源码(plugins/ps/ps.go)看,Start的完整调用链为:先触发pre-start钩子 → 通过scheduler-app-status判断运行状态(输出running/mixed/false)→ 若未完全运行则调用release-and-deploy→ 最后触发proxy-build-config重建代理配置。
五、进程扩缩容:ps:scale 全面解析
5.1 查看当前规模
不带任何进程参数的ps:scale输出当前应用的扩缩容属性:
dokku ps:scale node-js-app-----> Scaling for python proctype: qty --------: --- web: 1使用--format json可获取 JSON 格式的 formation,便于程序化消费,每个条目把进程类型映射到期望实例数:
dokku ps:scale node-js-app --format json[{"process_type":"web","quantity":1},{"process_type":"worker","quantity":4}]若应用从未设置过 scale,JSON 输出为空数组[]。此逻辑对应 plugins/ps/functions.go 的scaleReport:JSON 分支直接json.Marshal(formations),文本分支则按proctype=qty的格式右对齐输出。
5.2 通过 CLI 设置规模
dokku ps:scale node-js-app web=1可以同时设置多个进程类型:
dokku ps:scale node-js-app web=1 worker=1使用--skip-deploy跳过对应的部署阶段(即只改配置、不触发 deploy):
dokku ps:scale --skip-deploy node-js-app web=1重要:若应用的 formation 由
app.json中的formation键管理,则ps:scale的此项功能会被禁用(详见 5.5 节)。
5.3--replace:整体替换 formation
默认的ps:scale是把指定进程类型合并进现有 formation,未指定的进程类型保持原数量。而--replace会把指定的进程类型视为整个formation,所有未指定的进程类型数量归零:
dokku ps:scale --replace node-js-app web=1例如应用原来是web=2 worker=3,执行上述命令后变为web=1 worker=0,worker容器会在同一条命令内被停止。
注意:使用
--replace时必须至少指定一个进程类型;若只想重置 formation,请改用--clear。
5.4--clear:重置 formation
--clear把 formation 重置为新建应用时的默认规模——单个web进程,其它进程类型数量归零:
dokku ps:scale --clear node-js-app若应用的Procfile中没有定义web进程类型,则所有进程类型的数量都会被设为 0。
注意:
--clear不能与任何进程类型同时使用,也不能与--replace组合。
5.5 通过 app.json 管理 formation
用户也可以把扩缩容配置写进代码仓库,实现"配置即代码"。app.json中的formation键格式如下:
{ "formation": { "web": { "quantity": 1 }, "worker": { "quantity": 4 } } }关键行为:只要app.json中的formation键指定了任意quantity,ps:scale的扩缩容能力即被禁用;app.json未指定的进程类型其数量会被设为 0。删除formation键或从仓库移除app.json后,Dokku 会重新尊重ps:scale命令的设置;而此前通过app.json部署写入的 scale 值仍会保留生效。
app.json的存放位置与Procfile的查找规则类似,详见 app.json location 文档。
5.6 scale 的源码实现细节
- 参数校验:
CommandScale(plugins/ps/subcommands.go)依次校验:--clear与--replace互斥、--clear不能带进程类型、--replace必须至少带一个进程类型、以及应用是否允许手动扩缩容(can-scale属性)。 - 进程元组解析:
parseProcessTuples(plugins/ps/functions.go)负责把web=2形式的字符串拆分为ProcessType+Quantity,缺数量会报Missing count for process type,数量非数字会报Invalid count。 - 增量部署优化:
scaleSet默认deployOnlyChanged: true(见 plugins/ps/functions.go),只有数量发生变化的进程类型才会触发deploy触发器,未变化的进程类型不会无谓重启。 - 进程名校验:
updateScale会通过procfile-util list读取 Procfile 中的合法进程类型;尝试把不在 Procfile 中的进程类型扩到非零数量会直接报错xxx is not a valid process name to scale up。数量为 0 时则允许(用于缩容清理)。 - 默认 formation:
TriggerPostCreate(plugins/ps/triggers.go)在应用创建时写入web=1的默认 formation,这与ps:scale --clear重置到的默认规模一致。 - 与 app.json 的联动:
canScaleApp读取can-scale属性(默认true),当检测到app.json含 formation 键时,其它插件(如 app-json)会把该属性写为false,从而锁死ps:scale。
六、用 Procfile 定义进程
6.1 Procfile 语法与优先级
应用可以通过根目录的Procfile声明多个进程。Procfile是纯文本文件,每行定义一个进程类型,每种进程类型只能出现一次。Dokku 遵循 procfile-util 规范 中的Strict Mode(严格模式)解析规则。
<process type>: <command>关键规则:
- 优先级最高:无论镜像构建方式如何(Dockerfile 的
CMD、buildpack 的默认进程、或其它 builder 的默认命令),只要存在Procfile,它就优先于镜像默认命令。 - 不能为空:文件若存在则必须非空,空 Procfile 可能导致部署失败。
- 进程类型不可重复。例如有多个队列 worker 需要分别扩缩容时,可以通过不同进程类型来绕开"类型不可重复"的限制:
worker: env QUEUE=* bundle exec rake resque:work importantworker: env QUEUE=important bundle exec rake resque:work- ENTRYPOINT 交互:若构建产物声明了
ENTRYPOINT,Procfile中定义的命令会作为参数传给该 entrypoint——这对所有 Dockerfile、Docker Image 和 Cloud Native Buildpack 部署均成立。 - 校验时机:
TriggerCorePostExtract(plugins/ps/triggers.go)会在解包阶段用procfile-util check -P校验 Procfile 的合法性,非法内容将直接导致构建失败。
6.2web进程的特殊性
首次部署时,Dokku 默认启动一个web进程(可来自Procfile,也可来自 Dockerfile/Docker Image 部署的CMD)。web进程还有两个特殊约束:
- 内置的 nginx 代理实现默认只代理
web进程(其它进程类型如需对外提供服务,需自定义nginx.conf.sigil)。详见 nginx request proxying 文档。 - 只有
web进程可以绑定外部端口。
web与其它进程的扩缩容均通过ps:scale或app.json的formation键管理,且可在首次部署前后随时调整。
6.3release进程(发布阶段任务)
Procfile还支持特殊的release命令,行为类似 Heroku 的 Release Phase:在部署时先执行发布阶段任务(如数据库迁移),成功后才切换流量。具体机制见 Release deployment task 文档。
6.4 修改 Procfile 查找位置(procfile-path)
Procfile的默认查找目录取决于部署方式:
git:from-image与git:load-image部署:Docker 镜像的WORKDIR;- 其它部署(git push、
git:from-archive、git:sync):源码树根目录。
从 monorepo 部署等场景下,可以通过procfile-path属性为单个应用指定其它路径:
dokku ps:set node-js-app procfile-path .dokku/Procfile该值为相对于基准查找目录的路径,任何上下文中都不会被当作绝对路径处理。若仓库中不存在该文件,Dokku 会当作"没有 Procfile"继续构建。传空值恢复默认:
dokku ps:set node-js-app procfile-pathprocfile-path支持全局设置,全局默认值为Procfile,应用未设置时使用全局值:
dokku ps:set --global procfile-path global-Procfile dokku ps:set --global procfile-path七、自定义启动命令
针对不同 builder,可通过两个 ps 属性定制容器的启动命令:
- buildpack 构建的应用(启动命令通常来自
Procfile):设置start-cmd:
dokku ps:set node-js-app start-cmd "node server.js"- Dockerfile 构建的应用:设置
dockerfile-start-cmd,该值作为参数传给docker run,覆盖或补充镜像的CMD/ENTRYPOINT:
dokku ps:set node-js-app dockerfile-start-cmd "--harmony server.js"背景知识见 Dockerfile builder 文档。
任一属性均可通过传空值清除:
dokku ps:set node-js-app start-cmd八、重启策略(Restart Policies)
8.1 默认行为与策略值
默认情况下,Dokku 通过 Docker 的on-failure重启策略,自动重启以非零退出码退出的容器,最多10 次。该能力 0.7.0 引入,0.22.0 修改了命令格式。
支持的策略值:
# 容器退出后总是重启 dokku ps:set node-js-app restart-policy always # 永不重启已退出的容器 dokku ps:set node-js-app restart-policy no # 仅在 Docker 重启时重启(手动停止过的除外) dokku ps:set node-js-app restart-policy unless-stopped # 仅非零退出码时重启 dokku ps:set node-js-app restart-policy on-failure # 仅非零退出码时重启,最多 20 次 dokku ps:set node-js-app restart-policy on-failure:20恢复默认策略on-failure:10:
dokku ps:set node-js-app restart-policy设置全局默认策略(应用于所有未单独设置的应用):
dokku ps:set --global restart-policy always生效优先级:应用级值 → 全局值 → 内置默认on-failure:10。该计算值可通过ps:report的--ps-computed-restart-policyflag 查看。
重要:修改重启策略后,必须执行一次
ps:rebuild才能生效。
从源码看,策略的生效链路为:
- 合法性校验在
CommandSet中完成,isValidRestartPolicy(plugins/ps/functions.go)只接受no、always、unless-stopped、on-failure以及on-failure:<N>前缀形式; - 部署时
TriggerDockerArgsProcessDeploy(plugins/ps/triggers.go)在每次 deploy 时动态把计算后的--restart=<policy>注入到 Docker 参数中,不再持久化到 docker-options 存储; - 安装时
TriggerInstall会把旧版本遗留的--restart=Docker 选项迁移到restart-policy属性,并清理历史DOKKU_DOCKER_STOP_TIMEOUT、DOKKU_APP_RESTORE、DOKKU_START_CMD等配置变量的迁移逻辑(见 plugins/ps/triggers.go)。
8.2 重启策略与 dokku-event-listener
重启策略与服务器重启无关:服务器重启后 Dokku 总会尝试拉起应用,除非它们此前被手动停止。
此外,Dokku 通过系统 init 服务在后台运行dokku-event-listener监控容器状态,并执行两项动作:
- 若
web进程发生重启且其容器 IP 变化,则重建应用的代理配置; - 若某应用内进程的重启次数超过上限,则重建整个应用。
九、属性系统与 ps:report 详解
9.1 可设置属性(Settable Properties)
ps 插件通过ps:set管理一批属性。所有属性的默认值定义在 plugins/ps/ps.go 的DefaultProperties/GlobalProperties中:
| 属性 | 作用域 | 默认值 | Report flags | 说明 |
|---|---|---|---|---|
dockerfile-start-cmd | 仅应用 | 无 | --ps-dockerfile-start-cmd、--ps-computed-dockerfile-start-cmd | 覆盖 Dockerfile 应用的CMD |
procfile-path | 应用 + 全局 | Procfile | --ps-procfile-path、--ps-global-procfile-path、--ps-computed-procfile-path | Procfile 相对于构建根目录的路径 |
restart-policy | 应用 + 全局 | on-failure:10 | --ps-restart-policy、--ps-global-restart-policy、--ps-computed-restart-policy | 应用到部署容器的 Docker 重启策略(no、always、unless-stopped、on-failure[:max-retries]) |
restore | 仅应用 | true | --restore | 为true时,宿主重启后应用由ps:restore自动拉起 |
skip-deploy | 应用 + 全局 | false | --ps-skip-deploy、--ps-global-skip-deploy、--ps-computed-skip-deploy | 为true时,构建成功后跳过部署阶段 |
start-cmd | 仅应用 | 无 | --ps-start-cmd、--ps-computed-start-cmd | 覆盖 buildpack 应用的启动命令 |
stop-timeout-seconds | 应用 + 全局 | 30 | --ps-stop-timeout-seconds、--ps-global-stop-timeout-seconds、--ps-computed-stop-timeout-seconds | Docker 停止容器前等待的秒数,超时后发送SIGKILL(等价于kill -9)强制终止 |
Report flags 与 JSON 键名:
ps:report的 JSON 输出(--format json)中,键名为去掉--ps-前缀后的名称(如procfile-path、global-procfile-path、computed-procfile-path)。在 0.38.x 弃用窗口期内,带有ps-前缀的旧键名(如ps-procfile-path)也会一并输出,并将在未来的大版本中移除。
9.2 停止超时(stop-timeout-seconds)
stop-timeout-seconds控制docker stop命令的宽限期:若容器在该时间内未停止,则发送SIGKILL(或等价信号)强制终止。ps:stop与apps:destroy命令同样遵循该值;未设置时使用 Docker 对docker stop的默认值(30 秒)。注意:文档使用章节中的示例写法为stop-timeout,属性表的正式名称为stop-timeout-seconds,二者指向同一属性。
设置示例:
dokku ps:set node-js-app stop-timeout-seconds 60恢复默认值(传空值即可):
dokku ps:set node-js-app stop-timeout-seconds全局设置(应用未设置时生效):
dokku ps:set --global stop-timeout-seconds 60 dokku ps:set --global stop-timeout-seconds9.3 只读 flags(Read-only Flags)
以下 flag 由运行状态派生,ps:set无法管理,只能通过ps:report查看:
| Flag | 说明 |
|---|---|
--ps-can-scale | 当应用的 Procfile 或 builder 禁止水平扩缩容时为false |
--deployed | 首次成功部署后为true |
--running | 应用有任何容器在运行时为true |
--processes | 所有 proctype 的已扩缩容进程总数 |
--status-<proctype> | 每个 Procfile 进程类型对应的容器状态与 ID(如running (CID: abc123def45)) |
其中--status-<proctype>由 plugins/ps/report.go 的addStatusFlags动态生成:它扫描应用数据目录下CONTAINER.*文件、读取容器 ID 并调用docker inspect查询{{ .State.Status }},容器不存在时状态显示为missing。
9.4 计算值的解析顺序
ps:report中computed系列的取值遵循"应用值 → 全局值 → 内置默认"的链式回退,例如reportComputedRestartPolicy(plugins/ps/report.go):先取应用级restart-policy,为空再取全局,再为空则回退到DefaultProperties["restart-policy"](即on-failure:10)。procfile-path、stop-timeout-seconds、skip-deploy的计算逻辑完全同构。
十、服务器重启后的自动恢复(ps:restore)
10.1 恢复流程
服务器重启或 Docker 重启/升级后,Docker 可能不会自动启动旧的应用容器,某些情况下还会重新分配容器 IP。Dokku 通过 init 进程在检测到 Docker daemon 启动后触发dokku ps:restore。该命令对每个应用串行执行以下步骤:
- 启动所有链接的服务;
- 清除已生成的代理配置文件;
- 若应用未被手动停止,则启动应用:
- 容器仍存在:直接启动,并重建生成的代理配置文件;
- 任一容器缺失:重建整个应用。
从源码(plugins/ps/ps.go)看,Restore的调用链为:scheduler-pre-restore(供调度器做前置准备)→proxy-clear-config(清理可能失效的代理配置)→ 检查restore属性(为false则跳过)→ 调用Start。恢复前的全局准备restorePrep则先对所有应用执行proxy-clear-config --all。
10.2 恢复期间的注意事项
恢复期间,若 Docker 重新分配的 IP 与其它应用重合,请求可能短暂路由到错误的应用。Dokku 会尽力避免,但仍有几分钟内 URL 可能路由错乱的风险。应对方式:使用自定义 proxy 插件,或等待数分钟直至恢复完成。
10.3 用restore属性控制恢复行为
restore属性为false时,重启后ps:restore会跳过该应用:
dokku ps:set node-js-app restore false恢复默认值true:
dokku ps:set node-js-app restore联动机制:手动执行ps:stop时,post-stop触发器会把restore写为false(见 plugins/ps/triggers.go);而一次成功的部署(core-post-deploy)会把restore重置回true(见 plugins/ps/triggers.go)。也就是说,"手动停止 → 重启服务器 → 应用保持停止"与"部署后 → 重启服务器 → 应用自动拉起"这两种行为都由此属性驱动。
十一、进程管理的测试与验证
ps 插件的行为有完整的单元测试保障,可参见 plugins/ps/functions_test.go;Dokku 全量集成测试位于 tests/unit 目录下的 bats 测试中(如ps_*系列),覆盖了启停、重启、扩缩容与恢复等场景。实际运维时可遵循以下验证路径:
dokku ps:report <app>查看部署状态、运行状态、进程数与计算后的重启策略;dokku ps:scale <app> --format json检查 formation 是否符合预期;- 修改任何 ps 属性后通过
dokku ps:report <app>确认computed系列取值; - 修改重启策略后务必
dokku ps:rebuild <app>使其生效。
结语
ps 插件是 Dokku 进程生命周期的"总调度台":向上承接构建产物(receive-app、deploy、release-and-deploy触发器),向下驱动调度器与代理(scheduler-*、proxy-*触发器),同时以Procfile+ 属性系统为枢纽,把"进程类型抽象"这一 Heroku 生态核心概念完整落地到 Docker 运行时之上。理解ps:scale的合并/替换/清零语义、重启策略的解析优先级与restore属性的联动机制,是熟练运维多进程 Dokku 应用的三个关键抓手。结合本文引用的 plugins/ps 源码路径,你可以随时深入对应函数验证行为细节。
【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考