Skip to main content

Laravel Horizon

What is Laravel Horizon?​

Laravel Horizon is Laravel's official dashboard and configuration layer for Redis-backed queues, it doesn't replace the queue worker process, it supervises and reports on it. This container isn't a standalone daemon in the usual sense: it's a dedicated PHP/Alpine image (built via supervisord, extending Laradock's usual PHP extension-install pattern) whose job is to run php artisan horizon against your mounted Laravel application, under depends_on: workspace.

First-run setup (required)​

The container ships with only an example supervisord program file, laravel-horizon/supervisord.d/laravel-horizon.conf.example. Supervisord only loads files matching *.conf, so on a fresh checkout it loads nothing and the container starts but never actually runs php artisan horizon. Copy the example once before your first start:

cp laravel-horizon/supervisord.d/laravel-horizon.conf.example laravel-horizon/supervisord.d/laravel-horizon.conf

*.conf is gitignored on purpose (laravel-horizon/supervisord.d/.gitignore) so your local copy is never committed. Do this before starting the container, or restart it afterward if you already started it without the file.

Start Laravel Horizon​

Your app must already have Horizon installed (composer require laravel/horizon) and configured to use the redis queue connection. Then:

./laradock start laravel-horizon

The container depends_on workspace in compose.yml, so Compose starts it first automatically. It also needs redis running and reachable, since that's what php artisan horizon actually connects to.

Stop Laravel Horizon​

Stopping just pauses the container; horizon simply stops processing until you start it again:

./laradock stop laravel-horizon

This stops the container, which stops the supervised horizon process along with it. To remove the container:

./laradock remove laravel-horizon

Configuration​

Laravel Horizon's own dashboard and queue settings live in your Laravel app (config/horizon.php), not in this container. What this container's laravel-horizon/defaults.env controls is which optional PHP extensions get compiled into its image at build time, all false by default:

VariableDefaultWhat it does
LARAVEL_HORIZON_INSTALL_BZ2falseInstall the bz2 extension.
LARAVEL_HORIZON_INSTALL_GDfalseInstall the gd extension.
LARAVEL_HORIZON_INSTALL_GMPfalseInstall the gmp extension.
LARAVEL_HORIZON_INSTALL_GNUPGfalseInstall the gnupg extension.
LARAVEL_HORIZON_INSTALL_LDAPfalseInstall the ldap extension.
LARAVEL_HORIZON_INSTALL_IMAGEMAGICKfalseInstall imagick, version controlled by LARAVEL_HORIZON_IMAGEMAGICK_VERSION.
LARAVEL_HORIZON_INSTALL_INTLfalseInstall the intl extension.
LARAVEL_HORIZON_IMAGEMAGICK_VERSIONlatestGit ref of the imagick PECL/source build, used only when ImageMagick is installed.
LARAVEL_HORIZON_INSTALL_SOCKETSfalseInstall the sockets extension.
LARAVEL_HORIZON_INSTALL_YAMLfalseInstall the yaml extension.
LARAVEL_HORIZON_INSTALL_ZIP_ARCHIVEfalseInstall the zip extension.
LARAVEL_HORIZON_INSTALL_PHPREDISfalseInstall the redis PECL extension (in addition to predis, if your app uses it).
LARAVEL_HORIZON_INSTALL_MONGOfalseInstall the mongodb extension.
LARAVEL_HORIZON_INSTALL_CASSANDRAfalseInstall the Cassandra PHP driver.
LARAVEL_HORIZON_INSTALL_FFMPEGfalseInstall the ffmpeg binary for jobs that process media.
LARAVEL_HORIZON_INSTALL_AUDIOWAVEFORMfalseInstall the BBC audiowaveform binary.
LARAVEL_HORIZON_INSTALL_POPPLER_UTILSfalseInstall poppler-utils and antiword for PDF/document jobs.
LARAVEL_HORIZON_PUID1000UID for the container's laradock user.
LARAVEL_HORIZON_PGID1000GID for the container's laradock user.

This container also inherits PHP_FPM_INSTALL_PGSQL, PHP_FPM_INSTALL_BCMATH, and PHP_FPM_INSTALL_MEMCACHED from the shared PHP-FPM build args, so those extensions follow whatever you've already set for php-fpm.

Supervise queue workers​

The actual worker process(es) Horizon supervises are configured on the Laravel side, in config/horizon.php (queues, balance strategy, max processes, and so on), same as any Horizon setup. This container just needs Redis and your app code reachable to run php artisan horizon:

./laradock start redis workspace laravel-horizon

Supervisord config for the container itself lives in laravel-horizon/supervisord.d (see First-run setup if you haven't created laravel-horizon.conf yet), mounted straight into /etc/supervisord.d, edit it if you need to change how the horizon process is launched or restarted inside the container. It's a volume mount, not baked into the image, so a restart picks up your edit, no rebuild needed:

./laradock restart laravel-horizon

Manage Horizon from the CLI​

Open a terminal inside the container, the same way as any other Laradock service:

./laradock enter laravel-horizon

Then use Horizon's own Artisan commands, the same ones you'd use outside Docker:

CommandWhat it does
php artisan horizon:statusPrint whether Horizon is currently running or paused.
php artisan horizon:pausePause processing without stopping the container.
php artisan horizon:continueResume after a pause.
php artisan horizon:terminateGracefully stop after current jobs finish; supervisord (autorestart=true) restarts the process immediately, this is the standard way to pick up freshly deployed code without dropping in-flight jobs.
php artisan horizon:clearRemove all pending jobs from the queues Horizon is watching.

Common issues​

  • Horizon container is running but nothing shows in the dashboard. You most likely skipped First-run setup: without laravel-horizon.conf, supervisord has no program to run, so php artisan horizon never starts even though the container itself is healthy.
  • Horizon container starts but no jobs process. Confirm your Laravel app's QUEUE_CONNECTION=redis and that redis is running and reachable; Horizon only supervises Redis-backed queues.
  • Missing PHP extension errors from your app's jobs. The extension flags above are all false by default; if a job needs gd, imagick, mongodb, and so on, set the matching LARAVEL_HORIZON_INSTALL_* variable and rebuild: ./laradock rebuild laravel-horizon.
  • Extension build args changed but the container still lacks them. These are Dockerfile build args, not runtime env vars; a plain restart won't apply them, rebuild the image after changing .env.
  • Horizon dashboard (/horizon) shows no metrics. That dashboard is served by your app itself (through php-fpm/nginx), not by this container; this container only needs to be running so the underlying queue actually gets worked.
  • Edited supervisord.d/laravel-horizon.conf but nothing changed. Supervisord only reads that file at process start; restart the container (./laradock restart laravel-horizon), don't just wait.

Need the queue backend itself? See Redis. New to Laradock? Start at Getting Started.