如何让Supervisor在Docker容器外管理Laravel queue:worker
Laravel队列任务在Docker+Supervisor下的问题排查与解决
问题现象
- 在Docker容器外执行
php /var/www/someproject/src/artisan queue:work --queue=mail-queue,终端显示正在处理队列,但实际无任务执行 - 进入容器内执行
php artisan queue:work --queue=mail-queue,队列任务可正常运行 - 配置Supervisor后进程显示运行中,但无任务执行且日志为空
- 修改Supervisor命令为
php artisan queue:work --queue=mail-queue,提示找不到artisan文件 - 使用
docker exec -it come_container /bin/bash php artisan queue:work --queue=mail-queu,提示the input device is not a TTY
错误原因
- 宿主机与容器环境不一致:容器外的PHP环境缺少Laravel运行所需的依赖扩展、环境变量或队列驱动连接权限(比如Redis仅绑定容器内部网络),导致命令看似启动但无法读取/处理队列任务。
- Supervisor命令配置错误:
- 直接用
php artisan时,Supervisor的工作目录并非容器内的项目根目录,因此找不到artisan文件 - 使用
docker exec -it时,-it参数要求交互式终端,但Supervisor是后台进程,没有TTY设备,触发报错
- 直接用
解决方案
方案1:容器内集成Supervisor(推荐)
将Supervisor安装在Laravel应用容器中,直接在容器内管理队列进程,确保环境一致。
Dockerfile示例
FROM php:8.2-fpm # 安装依赖与Supervisor RUN apt-get update && apt-get install -y \ supervisor \ && docker-php-ext-install pdo_mysql \ && pecl install redis && docker-php-ext-enable redis # 创建Supervisor配置目录 RUN mkdir -p /etc/supervisor/conf.d # 复制Supervisor队列配置 COPY supervisor/laravel-queue.conf /etc/supervisor/conf.d/ # 设置项目工作目录 WORKDIR /var/www/html # 复制项目代码 COPY src/ . # 安装Composer依赖 RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer RUN composer install --no-dev --optimize-autoloader # 启动Supervisor CMD ["/usr/bin/supervisord", "-n"]
Supervisor配置文件(supervisor/laravel-queue.conf)
[program:laravel-mail-queue] process_name=%(program_name)s_%(process_num)02d command=php /var/www/html/artisan queue:work --queue=mail-queue --sleep=3 --tries=3 autostart=true autorestart=true user=www-data numprocs=1 redirect_stderr=true stdout_logfile=/var/www/html/storage/logs/queue-mail.log
docker-compose.yml示例
version: '3.8' services: app: build: . volumes: - ./src:/var/www/html environment: - APP_ENV=production - QUEUE_CONNECTION=redis # 根据实际队列驱动调整 depends_on: - redis redis: image: redis:alpine
方案2:宿主机Supervisor调用容器命令(适配已有宿主机Supervisor场景)
去掉docker exec的交互式参数-it,指定容器内artisan的绝对路径:
Supervisor配置示例
[program:laravel-mail-queue] process_name=%(program_name)s_%(process_num)02d command=docker exec come_container php /var/www/html/artisan queue:work --queue=mail-queue --sleep=3 --tries=3 autostart=true autorestart=true user=root # 替换为有权限执行docker命令的用户 numprocs=1 redirect_stderr=true stdout_logfile=/var/log/supervisor/queue-mail.log
核心原理说明
Docker容器是独立的隔离环境,宿主机的PHP环境与容器内的Laravel运行环境(包括PHP版本、扩展、环境变量、网络配置)完全分离。进入容器后,你处于Laravel项目的正确运行环境中,因此命令能正常连接队列驱动并处理任务;而宿主机执行时,要么缺少依赖,要么无法访问容器内部的队列服务,导致看似启动但无实际任务处理。
内容的提问来源于stack exchange,提问作者polycode
相关产品推荐
相关产品推荐

