Cron and Queues
You may need to run Laravel’s scheduler (via cron) or queue workers.
The best way is to use the processes configuration.
This allows you to segment your application into “groups”. Each “group” can run an instance of your code base with a specific use case (web server, cron tasks, queue worker).
If you used
fly launch
to create your Laravel application, all of this should work without further modification to the Docker setup.
Scheduler (cron)
We can start the cron
daemon, which is pre-configured to run php artisan schedule:run
.
To enable this, edit your fly.toml
file and add a [processes]
section:
[processes]
app = ""
cron = "cron -f"
The line app = ""
is needed (with an empty string!) to keep a process group for your application serving web requests.
We created an additional process group cron = "cron -f"
. This tells the VM to run the cron daemon rather than start the web server.
Edit your Dockerfile
to add additional cron definitions to /etc/cron.d
if you need. The cron -f
command will load any cron definitions found in any files in that location.
Queue Worker
We can start an instance of our queue worker by adding another process. In this example, we’ll add a worker
process group in addition to app
and cron
processes.
[processes]
app = ""
cron = "cron -f"
worker = "php artisan queue:listen"
Note that you may want to expand on the queue:listen
command. For example, you could run php artisan queue:listen sqs --sleep=3 --tries=3 --max-time=3600
to use the sqs
driver and determine other behaviors.
Extra Credit
There’s a few bits to explain about the above.
Command vs Entrypoint
Internally, the things defined in the [processes]
section are commands to run when the application instance is run.
In Docker terminology, these are the Commands (CMD
) being sent to the Entrypoint (ENTRYPOINT
) as defined in the Dockerfile
.
That’s why the app
process group has a command of an empty string! We want the Entrypoint script to run without passing it any additional commands. The Entrypoint script will then perform it’s default behavior of starting Nginx/PHP-FPM to serve web requests.
The commands we defined are run relative to the Laravel project root, which is /var/www/html
by default. This is configured in the Dockerfile
used to setup the application.
Lastly, don’t forget that Fly.io builds a Docker image, and then converts that to a micro-VM run on Fly’s hardware.
Services
The [http_service]
(or [[services]]
) section of the fly.toml
should already contain the line processes = ["app"]
, telling Fly to apply the service config to the application VM serving web requests. That will expose public ports and set health checks as you would want for the public-facing application.
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
processes = ["app"]
The queue and cron application instances don’t need to expose public ports and don’t support tcp-based health checks. Thus, we do not define any services
for them.
Scaling
You can scale the process groups out separately. For example, this will create 2 app
instances (load balanced automatically) and 4 queue worker instances.
fly scale count app=2 worker=4
Check the docs on processes for more examples on scaling separately (e.g. scaling server size and regions per process group).