Run Laravel 9.x applications on Fly.io. The primary goals are to be a solid jumping off point as well as an attempt at sane defaults for your application images.
We heavily leverage Laravel Sail that facilitates local development containers but take them a step further to deploy for production workloads. Laravel Sail doesn't include Nginx, something the documentation highly encourages
We're also taking plenty of guidance from Greg Sanderson's Fly Hello Laravel example.
As a general rule to speed up deploying applications, it seems better to bake in any OS level apt
or composer
package, within reason.
The largest bottleneck tends to be the network it runs on. Digital Ocean has a local cache of package managers but I'm not sure if Fly.io does.
This seems to make sense when you think that the docker image has to be downloaded at a certain compressed size then further packages have to travel over the network.
I had known Fly.io had been looking for Laravel Specialists and once Chris Fidao announced he joined, that things could quickly move in another direction. Full Stack Laravel shows us how easy it is to now configure a new application. Compare that to the discussion here, the post that started me down this rabbit hole.
I've chosen to abandon this project largely because this solidified my desire to fully move away from PHP into Elixir. When I read the other posts in Laravel Bytes, I could no longer see myself as one of the authors. It's funny how once something goes from imagination to seeing a concrete example, our brain quickly says either "Yep!" or "Nope!" I may return to finish at some point but I want to be realistic and say that may never happen.
- This file is the most complete version.
- My plan was to start with 8.1 and work backwards.
- Remove the various Dockerfile.alpine versions.
- These were a holdover of my previous Docker project spanning versions 7.4 to 8.1.
- I kept these around in the event the various OS packages or configuration would be useful. It may make sense to try to configure something from the PHP source instead of Ubuntu as done with Sail.
- Heavily used by Gitlab CI jobs at my employer, The Rethinkgroup, Inc.
- Nginx is installed but nothing is configured.
- There's an existing command commented out to capture the default files as a backup. I always recommend this. It's more work to rebuild the image than to have files sitting around I may never use.
- My intention was to look at how Laravel Forge and the documentation suggests to run.
- Laravel Sail doesn't use Nginx so there's no guidance there to pull from.
- I hadn't tested any of this in production yet but the image builds.
- There may be minor adjustments needed to the
supervisor
commands and arguments but I don't believe so. They seem pretty stable given what I've used with Laravel Forge.
- There may be minor adjustments needed to the
I've yet to compare this to the steps outlined in Full Stack Laravel so these may be supported already.
- In queue workers.
- There's one large
docker/supervisor.conf
instead of one file per configuration. - The directive
directory=/var/www/html/
is not used.- The command becomes
php artisan
instead of always needing the path.
- The command becomes
- I've been bit by just running
php artisan
without understanding which version that is.- I prefer using
php8.1 artisan
to be explicit. - Docker images generally don't have their PHP versions updated by devops.
- I prefer using
- There's one large
- PHP v8.0 is used by default.
- This is honestly fine as what changes between PHP versions is usually negligible. That's not always the case though.
- Inspiration from Sails
- A command that changes all of the settings in the PHP section.
- A command to enable or change the
cron
andqueue
additions. - Our version
8.1/etc/supervisor/conf.d/laravel-schedule.conf
runs a specific schedule instead of usingdocker/cron
.- This may or may not be an improvement, it's more personal preference.
- The configuration for the Redis section of Full Stack Laravel would be great as a command.
- Something like
curl -s "https://laravel.build/example-app?with=mysql,redis" | bash
as suggested here. - It'd be nice to have a
fly configure redis
orphp
that handled this for you. - Editing the
fly.toml
should likely be an escape hatch if they hope to capture more Laravel Forge users. This is mostly how things are today but it could be taken a little bit further.
- Something like
- Sail images have one long
apt-get
command, we split them up into groupings.- Con: This is annoying as changes upstream will require further understanding.
- Con: One long command produces a much smaller Docker image.
- Pro: Breaking apart logical sections makes it easier to understand.
- Pro: Docker caches each RUN line as a layer, if we're only tweaking Nginx none of the other sections get rebuilt.
- An example
sail/app
is742.46 MB
versus817.8 MB
but it's important to remember Nginx isn't included.
- Supervisor files are split by need.
- Pro: We can disable or enable by moving the files in and out of the configuration directories.
- Pro: It's easy to find what to change vs a single larger file.
- Con: It may not be easier to determine what to change by file name alone.
- Leveraging Laravel Sail
- Sail uses Ubuntu as a base over Alpine Linux.
- Pro: Users may be more used to working with Ubuntu.
- Con: Images are larger but not by a huge amount.
- Sail's
start-container
is a solid Docker entry point. - Using Sail for personal and production development should make the transition far easier.
- Sail uses Ubuntu as a base over Alpine Linux.
Nginx, php, supervisor, and any applicable application configuration is broken into grouping patterns to reduce changing lines in a larger configuration file to replacing files entirely or just not copying them into the image.
This will likely be the biggest area of adjustment where not all files will be required and some will likely need to be adjusted further in the case of manually configuring queue workers over running something like Laravel Horizon.
- Required
docker.conf
- Sets supervisor defaults to run inside Docker containers.group.conf
- Determines which configurations to execute in the foreground. This will likely be the file that needs to be altered the most.nginx.conf
- Nginx proxies our HTTP requests to php-fpm.php-fpm.conf
- The main workhorse for our Laravel application, responsible for processing the web requests from Nginx.
- Optional
- If any of these optional files are to be utilized,
group.conf
needs to be adjusted to start the new process. laravel-horizon.conf
- Laravel Horizon requires Redis but manages all our queue workers under a single process. You would typically configure either Horizon or the queue workers manually.laravel-notifications.conf
- Laravel queue worker configured for thenotifications
queue instead of default.laravel-queue.conf
- Laravel queue worker configured for thedefault
queue.laravel-schedule.conf
- The Laravel scheduler.
- If any of these optional files are to be utilized,
To support a new version of PHP:
- Create a new top level directory, i.e.
8.1
. - Replicate the prior
Dockerfile
, essentiallycp 8.0/Dockerfile 8.1
. - Change the line
FROM php:8.0-fpm
toFROM php:8.1-fpm
.- This assumes the internal build tags don't change. Fortunately this tag is rather stable.
- Build your new image to test:
docker build ./8.1 -t w0rd-driven/docker-laravel-fly-io:8.1
. - Troubleshoot any breaking changes.
- Occasionally you may have to track a deviation further up the stack.
- Since we're running
php:8.1-fpm
you should inspect the list of supported tags to see what that image is built from.
- Since we're running
- In the case of 7.3,
libzip
is no longer included so it needs to be added explicitly.- 7.2 also removed extensions so this is the most common type of problem you'll run into.
- Remove any previously cached images via the rmi command:
docker rmi w0rd-driven/docker-laravel-fly-io:8.1
. - Remove any unused images
docker image prune --all
.
- Occasionally you may have to track a deviation further up the stack.
1. [Full Stack Laravel](https://fly.io/laravel-bytes/full-stack-laravel/)
2. [Fly Hello Laravel](https://github.com/gregmsanderson/fly-hello-laravel)
3. [Using Laravel on Fly.io](https://community.fly.io/t/using-laravel-on-fly-io/5037)
4. Laravel Sail
1. [Laravel Sail Repository](https://github.com/laravel/sail)
2. [Laravel Sail Docker Environments](https://github.com/laravel/sail/tree/1.x/runtimes)
5. [Docker in Development](https://serversforhackers.com/s/docker-in-development)
6. Docker
1. [Docker Hub for official PHP image](https://hub.docker.com/_/php).
2. [Github repository for official PHP image](https://github.com/docker-library/php).