Hyperf在Docker中运行定时任务本质是启用CrontabDispatcherProcess进程,由协程调度器驱动、非系统crond;需在processes.php注册该进程,配置crontab.php启用并设时区,任务类启用$singleton=true和Redis分布式锁防重复,Docker启动命令须显式指定--workers等参数确保多进程正常加载。

Hyperf 在 Docker 中运行定时任务,本质是让 Crontab 组件在多进程 Swoole Server 环境下安全、不重复地执行。它不是靠系统 crond,而是由框架内建的协程调度器驱动。关键在于:**避免多 Worker 进程同时触发同一任务,同时确保 Crontab 进程随主服务一起启动并稳定运行**。
必须启用 Crontab 调度进程
Docker 容器默认只跑一个主 Server 进程(如 HTTP 服务),而 Hyperf 的定时任务需要单独的 CrontabDispatcherProcess 来轮询和触发。若不显式注册,即使配置了 @Crontab 注解,任务也不会执行。
- 在
config/autoload/processes.php中添加:
return [
Hyperf\Crontab\Process\CrontabDispatcherProcess::class,
];- 该进程会自动监听所有
@Crontab标记的任务,并按规则分发到可用 Worker 中执行(非抢占式) - 无需额外启动命令,
php bin/hyperf.php start启动时即加载
开启定时任务并设置时区
确保 config/autoload/crontab.php 已存在且启用:
MiniMax 图片理解 + 网络搜索 MCP 工具。适配 Docker 环境(极空间等),支持图片 OCR 识别、图像内容理解、网络搜索。API Key 安全存储在本地 credentials 文件,不暴露在代码中。
return [
'enable' => true,
'timezone' => 'Asia/Shanghai',
'scan' => [
'paths' => [
'app/Crontab',
],
],
];-
enable必须为true,否则整个 Crontab 模块被跳过 -
timezone强烈建议显式设置,否则依赖容器默认时区(Alpine 默认 UTC),会导致 cron 表达式解析偏差(比如0 2 * * *实际在 UTC 时间凌晨 2 点执行) -
scan.paths明确指定任务类所在目录,避免因 Docker 构建或挂载导致路径扫描失败
防重复:单例 + 分布式锁双保险
Hyperf 默认以多 Worker 模式运行(如 --workers=4),若无防护,4 个进程可能在同一秒内同时执行同一个定时任务。
- 在任务类中启用单例模式(进程级互斥):
public array $singleton = true;
- 进一步增强可靠性,搭配 Redis 分布式锁(需已配置 Redis):
public array $mutex = [
'type' => 'redis',
'timeout' => 10, // 锁超时秒数
];- 二者叠加可覆盖单机多进程 + 多容器部署场景
- 注意:Redis 连接需在
config/autoload/redis.php中正确定义,默认连接名'default'
Docker 启动命令要带完整服务模式
很多 Dockerfile 误用 php bin/hyperf.php start 但未传参,导致 Swoole 启动为单进程,或未加载 Process 配置。
- 推荐 CMD 写法(兼容开发与生产):
CMD ["php", "bin/hyperf.php", "start", "--workers=4", "--task-workers=2"]
-
--workers显式声明 Worker 数量,确保 CrontabDispatcherProcess 能识别可用资源 - 避免使用
--watch或--dev进入生产镜像,它们会干扰进程稳定性 - 若用 docker-compose,确保环境变量(如
APP_ENV=prod)不会关闭 Crontab 组件

















