You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

错误原因

  1. 宿主机与容器环境不一致:容器外的PHP环境缺少Laravel运行所需的依赖扩展、环境变量或队列驱动连接权限(比如Redis仅绑定容器内部网络),导致命令看似启动但无法读取/处理队列任务。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:42:40