如何在Docker环境下运行Laravel(Lumen)Scheduler定时任务
Docker 默认单容器只能运行一个前台主进程,原有配置仅启动了PHP内置开发服务,调度进程未正常启动,同时直接在CMD中拼接多个命令会出现进程孤儿、异常无感知等问题,以下是两种适配不同场景的解决方案:
方案1:单容器本地调试用Supervisor进程管理
适合本地快速验证功能,不推荐生产环境使用
步骤1:新增Supervisor配置文件
在项目根目录新建supervisord.conf,内容如下:
[supervisord] nodaemon=true user=root logfile=/var/log/supervisord.log pidfile=/var/run/supervisord.pid [program:laravel-web] command=php -S 0.0.0.0:8000 -t public directory=/src user=www-data autostart=true autorestart=true stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:laravel-scheduler] command=php artisan schedule:work directory=/src user=www-data autostart=true autorestart=true stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0
步骤2:修改Dockerfile
在原有apk --no-cache add的软件列表中新增supervisor,末尾新增配置复制和启动指令,修改后完整Dockerfile如下:
FROM php:7.4-fpm-alpine RUN docker-php-ext-install mysqli pdo pdo_mysql RUN apk --no-cache add \ supervisor \ php7 \ php7-mysqlnd \ php7-fpm \ php7-pdo \ php7-mbstring \ php7-xml \ php7-openssl \ php7-json \ php7-phar \ php7-zip \ php7-dom \ php7-session \ php7-zlib && \ php7 -r "copy('http://getcomposer.org/installer', 'composer-setup.php');" && \ php7 composer-setup.php --install-dir=/usr/bin --filename=composer && \ php7 -r "unlink('composer-setup.php');" && \ ln -sf /usr/bin/php7 /usr/bin/php && \ ln -s /etc/php7/php.ini /etc/php7/conf.d/php.ini RUN set -x \ addgroup -g 82 -S www-data \ adduser -u 82 -D -S -G www-data www-data COPY . /src ADD .env.example /src/.env # 复制supervisor配置 COPY supervisord.conf /etc/supervisord.conf WORKDIR /src RUN chmod -R 777 storage RUN composer install # 启动supervisor管理两个进程 CMD ["supervisord", "-c", "/etc/supervisord.conf"]
注意:原有配置中服务绑定localhost:8000会导致容器外部无法访问,已修改为0.0.0.0:8000
方案2:生产级多容器拆分(适配AWS部署)
符合容器单进程原则,是部署到AWS的推荐方案,无需修改原有镜像,仅调整启动命令即可:
- Web服务容器:使用原有镜像,启动命令保持
php -S 0.0.0.0:8000 -t public(生产环境请替换为Nginx+PHP-FPM组合,PHP内置服务仅适用于开发场景) - 调度任务容器:使用完全相同的镜像,仅将启动命令修改为
php artisan schedule:work
本地测试docker-compose示例
新建docker-compose.yml即可同时启动两个服务:
version: '3' services: web: build: . ports: - "8000:8000" volumes: - ./:/src scheduler: build: . command: php artisan schedule:work volumes: - ./:/src
AWS部署适配
- 若使用ECS:定义两个任务定义,共用同一个镜像,分别配置不同的启动命令即可,可单独对Web服务配置负载均衡和自动扩容
- 若使用EKS:定义两个Deployment分别运行Web和调度任务,敏感配置可通过AWS Secrets Manager/Parameter Store注入
- 若使用Elastic Beanstalk:在
Dockerrun.aws.json中配置多容器运行规则即可
注意事项
- 两个容器需使用相同版本的代码,避免调度任务和Web业务逻辑不一致
- 所有进程统一使用
www-data用户运行,避免存储目录权限冲突 - 生产环境不要使用
.env文件存储配置,可通过容器环境变量注入敏感信息
内容的提问来源于stack exchange,提问作者Idowu Olayinka
相关产品推荐
相关产品推荐

