资讯动态

Dokku 定时任务(Scheduled Cron Tasks)完全指南:从 app.json 声明到 cron:run 实战

发布时间:2026/9/10 13:53:18 来源:尧图企业网站定制
Dokku 定时任务Scheduled Cron Tasks完全指南从 app.json 声明到 cron:run 实战【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku本篇技术指南围绕 Dokku 内置的定时任务Scheduled Cron Tasks能力展开详细讲解如何通过app.json中的cron键为应用声明周期性执行的命令如何用cron:set、cron:list、cron:suspend、cron:resume、cron:run、cron:report等命令管理任务生命周期以及如何通过 vector 集成持久化任务输出。读完本文你将能够为任何 Dokku 应用配置可靠的定时任务理解其执行环境、超时回收机制与调度器差异并掌握自管理 cron 的高级用法。功能概述与命令速览Dokku 从 0.23.0 版本开始提供内置的定时任务支持cron插件位于 plugins/cron。它把应用app.json中的cron声明转换为调度器可执行的定时任务对使用宿主 crontab 的调度器如docker-local写入dokku用户 crontab对自带 cron 后端的调度器如k3s则原生调度。所有命令如下cron:list app [--format json|stdout] # 列出应用的定时任务 cron:report [app] [flag] # 显示应用 cron 报告 cron:resume app cron_id # 恢复一个 cron 任务 cron:run app cron_id [--detach] [--ttl-seconds SECONDS] # 即时运行一个 cron 任务 cron:set [--global|app] key value # 设置或清除应用的 cron 属性 cron:suspend app cron_id # 挂起一个 cron 任务Dokku 托管 Cron通过 app.json 声明任务Dokku 自动调度dokku run命令其入口是应用app.json文件中的cron键。从源码看app.json由 plugins/app-json/appjson.go 解析其中AppJSON.Cron是CronTask的列表每个任务包含command、maintenance、schedule、concurrency_policy四个字段。声明任务以下app.json示例等效于每天执行一次dokku run $APP npm run send-email{ cron: [ { command: npm run send-email, schedule: daily } ] }app.json的默认搜索路径与部署方式相关如需从 monorepo 等场景指定其他位置可通过app-json:set app appjson-path path设置值为相对于基础搜索目录的路径详见 deployment-tasks.md。任务属性说明每个 cron 任务支持以下属性属性说明command在构建出的应用镜像内执行的命令也可以直接引用Procfile条目schedulecron 兼容的调度定义决定命令何时运行。秒通常不支持maintenance布尔值决定该任务是否处于维护不可执行状态concurrency_policy字符串默认allow控制任务与自身是否可并发执行。合法值allow允许并发、forbid已有任务运行则新任务直接退出、replace终止已有任务并启动新任务每个应用可以声明零个或多个 cron 任务。任务的验证发生在构建产物生成之后、应用部署之前cron 调度表则在部署后阶段post-deploy更新。也就是说一份非法的时间表或命令会在部署时直接报错而不是等到调度触发时才暴露。从 plugins/cron/cron.go 的实现可以看到schedule使用robfig/cron/v3解析器校验其标志位组合为Minute | Hour | Dom | Month | Dow | Descriptor——因此不支持秒字段但支持daily、hourly等描述符。concurrency_policy非allow/forbid/replace时会返回Invalid cron concurrency policy错误command与schedule为空时也会在部署阶段报错WarnToFailure模式。任务执行时长上限与回收cron 任务最长可运行 24 小时超过后会被系统回收docker-local调度器通过每 5 分钟运行一次的dokku ps:retire扫描回收超时任务因此任务实际可能超时最多约 5 分钟k3s调度器则直接通过 Job 的activeDeadlineSeconds强制执行期限。源码中DefaultTTLSeconds常量定义为86400plugins/cron/cron.godocker-local 会将其作为com.dokku.active-deadline-seconds标签盖印到容器上k3s 则渲染为 CronJob 的activeDeadlineSeconds。任务执行环境须知运行定时任务时有以下几点需要注意定时任务在应用运行时的环境中执行如果应用镜像不存在命令可能执行失败调度基于宿主服务器时区通常为 UTC目前 cron 模板中只指定了PATH与SHELL两个环境变量MAILTO可通过cron:set设置MAILFROM可通过cron:set设置每个定时任务都在一个一次性run容器内执行因此会继承为run容器配置的所有 docker-options任务之间绝不共享资源定时任务按调度器分别支持使用宿主 crontab 的调度器如docker-local会把app.json中的 cron 任务写入dokku用户 crontab自己管理 cron 后端的调度器如k3s则原生调度宿主 crontab 调度器如docker-local管理的所有应用的任务都写入同一个、归属于dokku用户的 crontab 文件该 crontab 应视为 Dokku 专用不要手动写入其他条目command会被分词tokenize后直接在容器内 exec不会解释;、、|、等 shell 特性。包含裸 shell 操作符的命令在部署时验证app.json会被拒绝因此格式错误的 cron 命令会导致部署失败而非静默运行失败。如果需要 shell 语义请显式包裹命令例如sh -c do-thing /var/log/x.log任务输出写入容器的 stdout 和 stderr可通过 Dokku 的 vector 集成持久化见下文cron 任务不能在app.json中声明日志文件路径。写入dokku用户 crontab 的只有dokku cron:run app cron_id行任何来自部署仓库的路径都不会被插值进去。关于命令分词plugins/cron/cron.go 的ValidateCronCommand使用mvdan.cc/sh/v3/shell的shell.Fields解析命令cron:run在派发时使用同一解析器因此部署时能通过校验的命令一定可以执行。对应的单元测试见 plugins/cron/cron_test.gosh -c echo CRON_OK; echo hi /tmp/x.txt这类显式包裹的命令会被接受而echo CRON_OK; echo hi /tmp/x.txt、cmd1 cmd2、cmd | other、cmd file、cmd $(other)都会被拒绝。持久化 Cron 任务输出如果不做额外配置任务输出只会投递到 cron 配置的MAILTO地址。要保留输出可以通过 Dokku 的 vector 集成配置一个 sink详见 logs.md 的 vector 日志投递章节。为应用配置的任何 sink 都会与应用的其余日志一起收到 cron 任务输出dokku logs:set node-js-app vector-sink console://?encoding[codec]json若要单独保留 cron 输出改用vector-cron-sinkcron 输出就会被路由到这里而不是应用主 sinkdokku logs:set node-js-app vector-cron-sink console://?encoding[codec]text要写入宿主机上的文件可指向/var/log/dokku/apps目录该目录已挂载进 vector 容器。dokku_cron_id字段可用于模板化让每个任务拥有自己的日志文件dokku logs:set node-js-app vector-cron-sink file://?path/var/log/dokku/apps/node-js-app/cron-{{ dokku_cron_id }}.logencoding[codec]text需要注意的路由规则logs.md设置 cron sink 是移动而非复制 cron 输出——vector 把每行日志恰好路由到两个 sink 之一仅设置vector-cron-sink时 cron 输出去 cron sink、其余输出无处可去两者都设置时 cron 输出去 cron sink、其余去vector-sink。cron 分支的事件额外带dokku_app与dokku_cron_id两个字段只有它们保证存在模板中引用其他字段可能导致日志被静默丢弃对非常短命的任务还存在相关注意事项。管理 cron 设置cron:setcron插件提供若干可按应用管理的设置项。下表列出了本文其他章节未覆盖的属性名称描述级别全局默认值mailfrom在 cron 文件中设置MAILFROM变量用于 cron 报告仅全局空字符串maintenance是否让应用运行 cron应用与全局falsemailto在 cron 文件中设置MAILTO变量用于 cron 报告仅全局空字符串所有设置都通过cron:set命令完成。以maintenance为例dokku cron:set node-js-app maintenance true传入空值即可恢复默认值dokku cron:set node-js-app maintenance如果属性可以全局设置如mailto使用--global标志应用未设置时若全局值存在则生效dokku cron:set --global maintenance true同样传空值可恢复全局默认值dokku cron:set --global maintenance从实现看plugins/cron/subcommands.gocron:set在写入属性后还会触发scheduler-cron-write触发器对--global只传调度器参数让调度器重新生成 crontab同时它也是cron:suspend/cron:resume的底层实现。属性定义见 plugins/cron/cron.go默认属性包含mailfrom、mailto、maintenance其中mailfrom与mailto为全局属性。列出 Cron 任务cron:list使用cron:list命令列出应用的 cron 任务命令接收app参数dokku cron:list node-js-appID Schedule Command cGhwPT09cGhwIHRlc3QucGhwPT09QGRhaWx5 daily node index.js cGhwPT09dHJ1ZT09PSogKiAqICogKg * * * * * true输出也支持 JSON 格式dokku cron:list node-js-app --format json[{id:cGhwPT09cGhwIHRlc3QucGhwPT09QGRhaWx5,app:node-js-app,command:node index.js,schedule:daily}]获取全局任务使用--global标志dokku cron:list --globalID Schedule Command 5cruaotm4yzzpnjlsdunblj8qyjp daily /bin/true从源码看plugins/cron/subcommands.gostdout 格式的表格会额外展示Concurrency与Maintenance列Maintenance列对任务级挂起显示true (task)对应用级维护显示true (app)。--format仅支持stdout与json两种值。任务 ID 由GenerateCommandID生成对appName Command Schedule做 base36 编码plugins/cron/cron.go这也是为什么示例中同样的命令与时间表在不同应用会得到不同 ID。挂起与恢复指定 Cron 任务cron 任务可以临时挂起暂停按计划执行之后恢复适用于维护或调试场景。挂起指定任务使用cron:suspend并带上应用名与 cron IDdokku cron:suspend node-js-app cGhwPT09cGhwIHRlc3QucGhwPT09QGRhaWx5被挂起的任务将不再按计划执行。可通过cron:list输出的Maintenance列确认任务已挂起——挂起的任务会显示true (task)。恢复挂起的任务使用cron:resumedokku cron:resume node-js-app cGhwPT09cGhwIHRlc3QucGhwPT09QGRhaWx5恢复后任务将重新按计划执行。cron ID 可从cron:list输出获取。实现细节cron:suspend等价于cron:set app maintenance.cron_id truecron:resume等价于cron:set app maintenance.cron_id清除该属性plugins/cron/subcommands.go 与 plugins/cron/subcommands.go。属性前缀maintenance.定义于 plugins/cron/cron.go。任务级维护属性不能全局设置cron:set --global maintenance.id会报错且仅当属性值为true时才会覆盖app.json中声明的maintenance见FetchCronTasks中的合并逻辑plugins/cron/cron.go。即时执行 Cron 任务cron:runcron:run命令可以即时调用 cron 任务接收app参数和 cron ID可从cron:list输出获取dokku cron:run node-js-app cGhwPT09cGhwIHRlc3QucGhwPT09QGRhaWx5默认情况下任务在附加attached容器中运行视调度器支持而定。要在后台分离容器中运行指定--detach标志dokku cron:run node-js-app cGhwPT09cGhwIHRlc3QucGhwPT09QGRhaWx5 --detach即时调用默认也有 24 小时86400 秒的运行上限与计划调度的任务相同。可用--ttl-seconds指定不同期限dokku cron:run node-js-app cGhwPT09cGhwIHRlc3QucGhwPT09QGRhaWx5 --detach --ttl-seconds 600该值只作用于本次调用——由调度计划启动的任务仍保持 24 小时默认值。所有一次性 cron 执行的容器在调用结束后都会被终止。实现细节plugins/cron/subcommands.gocron:run会先校验--ttl-seconds必须为正整数validateTTLSecondsplugins/cron/cron.go对应测试见 plugins/cron/cron_test.go校验任务 ID 存在然后用shell.Fields对命令分词设置DOKKU_DETACH_CONTAINER、DOKKU_DISABLE_TTY分离模式、DOKKU_CONCURRENCY_POLICY、DOKKU_CRON_ID、DOKKU_RM_CONTAINER1、DOKKU_RUN_TTL_SECONDS等环境变量最终通过scheduler-run触发器派发给应用的调度器执行。查看 Cron 报告cron:report使用cron:report命令查看应用的 cron 配置报告dokku cron:report node-js-app cron information Cron task count: 2 python-sample cron information Cron task count: 0 ruby-sample cron information Cron task count: 10也可以只查看指定应用dokku cron:report node-js-app node-js-app cron information Cron task count: 2还可以传标志只输出你关心的特定信息dokku cron:report node-js-app --cron-task-count可设置的属性及其对应的 report 标志、JSON 键名详见下文属性参考一节完整实现见 plugins/cron/report.go。属性参考以下属性可通过cron:set设置并通过cron:report查看[!NOTE]Report flags列是cron:report接受的 CLI 参数名。cron:report --format json输出的 JSON 键为去掉--cron-前缀后的同名如global-mailto、computed-mailto、maintenance。带cron-前缀的旧键如cron-global-mailto在 0.38.x 弃用窗口期仍会输出并将在未来大版本中移除。属性作用域默认值Report flags描述mailfrom仅全局无--cron-global-mailfrom、--cron-computed-mailfromcron 失败邮件使用的From:地址mailto仅全局无--cron-global-mailto、--cron-computed-mailtocron 失败邮件的收件地址为空则禁用邮件maintenance应用 全局false--cron-maintenance、--cron-global-maintenance、--cron-computed-maintenance为true时挂起应用或全局的所有 cron 任务maintenance.cron-id仅应用false--cron-maintenance-cron-id按任务动态生成按计算出的 ID 挂起单个 cron 任务每个任务一行由cron:suspend/cron:resume写入底层原理crontab 生成与调度器协作理解谁能把任务写进 crontab有助于排障。核心逻辑位于 plugins/cron/crontab.gousesHostCron通过scheduler-uses-host-cron触发器询问某调度器是否使用宿主 crontab空调度器或未实现该触发器的视为falsecrontab.gogenerateCronTasks会收集所有使用宿主 crontab 的应用的app.json任务再加上通过cron-entries触发器注入的任务格式为$SCHEDULE;$COMMAND[;$LOGFILE]并过滤掉处于维护状态的任务crontab.gowriteCronTab每次都是全量重新生成dokku用户 crontab先crontab -r -u dokku再写入因此多个调度器共用宿主 crontab 时不会互相覆盖任务列表为空时直接删除 crontabcrontab.go。最终渲染使用的模板为 plugins/cron/templates/cron.tmpl内容大致为MAILFROM{{ .Mailfrom }} MAILTO{{ .Mailto }} PATH/usr/local/bin:/usr/bin:/bin SHELL/bin/bash {{ $task.Schedule }} {{ $task.DokkuRunCommand }}DokkuRunCommand对应用任务恒输出dokku cron:run app cron_idplugins/cron/cron.go绝不把用户命令直接写进 crontab——测试 plugins/cron/cron_test.go 专门断言 crontab 行不包含;、、|、、、$等 shell 元字符且不会把用户命令泄漏到 crontab 行中。自管理 Cron高级用法[!WARNING] 自管理 cron 属于高级用法。虽然下文提供操作说明但强烈建议优先使用内置定时任务支持除非确有必要。某些安装场景可能需要更细粒度的 cron 控制以下是配置 cron 的高级指引。使用 run 执行 cron 任务可以随时使用一次性容器运行应用任务dokku run node-js-app some-command对于不应被打断的任务run是处理 cron 任务的首选方式因为即使发生部署或扩缩容事件容器也会继续运行。代价是多个并发任务同时运行时内存占用会增加。使用 enter 执行 cron 任务在Procfile中加入以下条目cron: sleep infinity将cron进程扩到1dokku ps:scale node-js-app cron1然后即可在该容器中运行所有命令dokku enter node-js-app cron some-command注意也可以同时运行多个命令以减少内存占用但这可能会污染容器环境。对于需要正确恢复的任务应当使用上述方式——因为部署和扩缩容事件会中断正在运行的任务且后续命令始终运行在最新容器中。注意如果把 cron 容器缩容可能会中断任务正常运行。通用 cron 建议定期任务在 Dokku 上需要一些额外注意以下通用建议有助于保证任务成功运行在 cron 任务中使用dokku用户否则dokku二进制会尝试用sudo执行cron 运行会失败并报sudo: no tty present and no askpass program specified添加MAILTO环境变量把 cron 邮件发给自己添加PATH环境变量或指定宿主机上二进制文件的完整路径添加SHELL环境变量运行命令时指定 Bash让 cron 任务按时间排序存放保持服务器时间为 UTC读取 cronfile 时无需换算夏令时尽量在流量最低的时段运行任务用 cron 来触发任务而不是运行任务本体——用 rabbitmq 之类的真实队列系统处理实际任务尽量让任务保持安静只在出错时发邮件不要屏蔽标准错误或标准输出屏蔽前者会错过失败信息屏蔽后者意味着你其实应该通过修改应用来调整日志级别使用 Dead Mans Snitch 之类的服务验证 cron 任务是否成功完成在 cronfile 中写大量注释说明每个任务在做什么免得日后花时间解读文件将 cronfile 放在如/etc/cron.d/APP的模式路径下不要在 cronfile 文件名中使用非 ASCII 字符cron 对此很挑剔记得 cronfile 末尾要有换行符cron 同样很挑剔。以下是一份可直接参考的应用 cronfile 示例# server cron jobs MAILTOmaildokku.me PATH/usr/local/bin:/usr/bin:/bin SHELL/bin/bash # m h dom mon dow username command # * * * * * dokku command to be executed # - - - - - # | | | | | # | | | | ----- day of week (0 - 6) (Sunday0) # | | | ------- month (1 - 12) # | | --------- day of month (1 - 31) # | ----------- hour (0 - 23) # ----------- min (0 - 59) ### HIGH TRAFFIC TIME IS B/W 00:00 - 04:00 AND 14:00 - 23:59 ### RUN YOUR TASKS FROM 04:00 - 14:00 ### KEEP SORTED IN TIME ORDER ### PLACE ALL CRON TASKS BELOW # removes unresponsive users from the subscriber list to decrease bounce rates 0 0 * * * dokku dokku run node-js-app some-command # sends out our email alerts to users 0 1 * * * dokku dokku ps:scale node-js-app cron1 dokku enter node-js-app cron some-other-command dokku ps:scale node-js-app cron0 ### PLACE ALL CRON TASKS ABOVE, DO NOT REMOVE THE WHITESPACE AFTER THIS LINE小结Dokku 的定时任务体系由声明app.json的cron键— 验证部署期校验时间表与命令分词— 调度宿主 crontab 或调度器原生后端— 执行一次性 run 容器— 回收24 小时 TTL五段组成。日常使用推荐完全走内置方案用app.json声明、用cron:list/cron:report观察、用cron:suspend/cron:resume维护、用cron:run应急触发并配合vector-cron-sink持久化输出只有在需要细粒度控制或特殊约束时才考虑自管理 cron。相关可进一步阅读的仓库资料包括 cron 插件源码、cron 单元测试、app.json 格式定义 与 vector 日志集成文档。【免费下载链接】dokkuA docker-powered PaaS that helps you build and manage the lifecycle of applications项目地址: https://gitcode.com/GitHub_Trending/do/dokku创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价