Skip to main content

RoadRunner

What is RoadRunner?

RoadRunner is a high-performance PHP application server written in Go, an alternative to PHP-FPM for keeping long-running PHP worker processes alive between requests instead of bootstrapping your app from scratch every time. It's a supported driver for Laravel Octane. The Laradock image pulls the official rr binary and layers it on a PHP-CLI Alpine image with the sockets and opcache extensions installed, then serves your mounted app via its .rr.yaml config (CMD ["rr", "serve"]).

Start RoadRunner

./laradock start roadrunner

RoadRunner is self-contained: it doesn't declare a dependency on php-fpm or a web server, it serves your app directly via the rr binary.

Stop RoadRunner

./laradock stop roadrunner

Configuration

All settings live in roadrunner/defaults.env and can be overridden by adding the same line to your own .env:

VariableDefaultWhat it does
ROADRUNNER_VERSION2025.1.15Version of the official RoadRunner image the rr binary is pulled from (build arg).
ROADRUNNER_HTTP_PORT8090Host-side port mapped to container port 8080.

The container also builds against LARADOCK_PHP_VERSION (Laradock's shared PHP_VERSION) and CHANGE_SOURCE, and adds an extra_hosts entry for dockerhost pointing at DOCKER_HOST_IP.

Set up Octane with RoadRunner

  1. In your Laravel app, install Octane with the RoadRunner driver:
    composer require laravel/octane spiral/roadrunner-cli
    php artisan octane:install --server=roadrunner
    This generates a .rr.yaml file. Set its HTTP address to 0.0.0.0:8080 so it's reachable from outside the container.
  2. Start the container:
./laradock start roadrunner
  1. Your app is served on the host at ROADRUNNER_HTTP_PORT (8090 by default), mapped to container port 8080.

Change the exposed port

Set the new host-side port in your .env:

ROADRUNNER_HTTP_PORT=8095

Then recreate the container so the new port mapping takes effect:

./laradock start roadrunner

Reload workers after a code change

RoadRunner boots your app once per worker and keeps it in memory between requests (that's the entire point of Octane workers), so unlike PHP-FPM it does not pick up code changes on the next request automatically. Reset the worker pool from inside the container instead of restarting it:

./laradock enter roadrunner
rr reset

This restarts the worker pool in place (no dropped connections, no container restart), so freshly deployed code is picked up on the next request. It needs an rpc: listen: block in your .rr.yaml (added automatically by php artisan octane:install --server=roadrunner); without it rr reset has nothing to connect to.

Common issues

  • Container starts but nothing responds. .rr.yaml needs its HTTP address set to 0.0.0.0:8080, not 127.0.0.1:8080, otherwise it only listens inside its own network namespace.
  • .rr.yaml not found. It's generated by php artisan octane:install --server=roadrunner inside your Laravel app; run that first, and confirm your app code is mounted correctly via APP_CODE_PATH_HOST.
  • Code changes don't show up. Workers keep your app booted in memory; reset the worker pool after deploying, don't expect a plain page refresh to pick up new code.
  • Extension-related errors. The image only installs sockets and opcache by default; additional extensions need to be added to roadrunner/Dockerfile and the image rebuilt with ./laradock rebuild roadrunner.
  • Port already in use on your host. Another service is already bound to 8090. Change ROADRUNNER_HTTP_PORT and restart with ./laradock start roadrunner.

Want another Octane-compatible runtime? See FrankenPHP. Looking for the classic Nginx + PHP-FPM setup instead? See Nginx. New to Laradock? Start with Getting Started.