Deploy a Laravel Application
Getting an application running on Fly is essentially working out how to package it as a deployable image. Once packaged it can be deployed to the Fly infrastructure to run on the global application platform.
In this guide we'll learn how to deploy a Laravel application on Fly.
Prepare a Laravel App
Bring your own Laravel app, or create a new one!
If you want to start fresh, here's how to set up a new application. You'll need PHP 8+ and composer installed locally. You can check your PHP version using php --version
.
composer create-project laravel/laravel fly-laravel
cd fly-laravel
php artisan serve
You should be able to visit http://localhost:8000
and see the home page.
Deploy to Fly.io
Install Fly
First, install flyctl, your Fly app command center, and sign up to Fly if you haven't already.
Launch
Next, we'll run fly launch
to automagically configure your app for Fly.
The launch
command adds a few files to your code base. Don't worry, it will ask before overwriting anything.
Here is what gets added:
Dockerfile
- Used to build a container image that is run in fly.dockerignore
- Used to ensure certain files don't make its way into your repositoryfly.toml
- Configuration specific to hosting on Flydocker
- A directory containing configuration files for running Nginx/PHP in a container
Running fly launch
(and later fly deploy
) uses the Dockerfile
to build a container image, copying your application files into the resulting image.
Fly doesn't care about the state of your git repository - it copies whatever files are present (except for files ignored by .dockerignore
).
If you haven't already, go ahead and run fly launch
!
- You'll be asked to provide secret
APP_KEY
. You can generate one usingphp artisan key:generate --show
. - When asked if you want to deploy now, say No.
If you have other environment variables to set, you can edit the fly.toml
file and add them.
[env]
# Set any env vars you want here
# Caution: Don't add secrets here
APP_URL = "https://fly-hello-laravel.fly.dev"
Replace this with the URL your app will be served on (by default, "https://<your-app-name>.fly.dev"
).
For sensitive data, you can set secrets with the fly secrets set
command:
fly secrets set SOME_SECRET_KEY=<the-value-from-your-env-file>
Deploy
Finally, run fly deploy
to build and deploy your application!
You should be able to visit https://your-app-name.fly.dev
and see the Laravel demo home page.
That's it! Run fly open
to see your deployed app in action.
Try a few other commands:
fly logs
- Tail your application logsfly status
- App deployment detailsfly deploy
- Deploy the application after making changes
CRON and Queues
You may need to run Laravel's scheduler or queue workers.
The included docker/supervisor.conf
comes with presets for both!
Scheduler (CRON)
File docker/crontab
defines a CRON task that runs the schedule:run
command.
You can edit that file to add/remove cron tasks as needed.
To get CRON tasks running in your app, edit file docker/supervisor.conf
and uncomment section [program:laravel-schedule]
:
[program:laravel-schedule]
numprocs=1
autostart=true
autorestart=true
redirect_stderr=true
process_name=%(program_name)s_%(process_num)02d
command=/usr/sbin/crond -f -l 8
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
This will run crond
the next time you deploy via fly deploy
.
Queue Workers
The docker/supervisor.conf
file also has a preset for running queue workers.
To enable those, uncomment the [program:laravel-queue]
program:
[program:laravel-queue]
user=app
numprocs=1 ;numprocs=5
autostart=true
autorestart=true
redirect_stderr=true
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work sqs --sleep=3 --tries=3 --backoff=3 --max-time=3600
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
You'll want to edit the above to use the driver of your choice, or configure multiple worker processes.
Extra Credit
Your app is a special snowflake. Here are a few things you may want to customize further!
PHP Version
The Dockerfile
installs PHP 8.0 by default. If you want PHP 8.1 or (bless your heart) PHP 7, you can find/replace instances of php8
to your version of choice.
For example, to update to PHP 8.1, you'll need to edit:
Dockerfile
- Change package names from php8 to php81 (e.g.php8-cli
tophp81-cli
)docker/app.conf
(if present) - Changelisten
to usephp81-fpm.sock
docker/php-fpm.conf
(if present) - Changeinclude
to use file path/etc/php81
server.conf
- Changefastcgi_pass
to pass tophp81-fpm.sock
supervisord.conf
- Change[program:php8-fpm]
(if present) to run commandphp-fpm81
If you need PHP 7, you can find other PHP versions (and matching Alpine container versions) here. Note that you may not be able to use alpine:edge
as the base container.
Node Version
The Dockerfile
uses fancy multi-stage builds to install your Node dependencies and build static assets.
You can change the Node version used in the Dockerfile
by changing FROM node:14
to a version of your choice.
# Change this:
FROM node:14 as node_modules_go_brrr
# To whatever version you need:
FROM node:16 as node_modules_go_brrr
One last note: The node_modules
directory ends up being excluded from your code base. If you need it, you'll have to adjust the Dockerfile
:
# Keep this line
COPY --from=node_modules_go_brrr /app/public /var/www/html/public
# Add this line:
COPY --from=node_modules_go_brrr /app/node_modules /var/www/html/node_modules
Logging Stack Traces
By default, we set the Logging output to use a JsonFormatter
. This makes the log output a bit cleaner, but has the trade-off of not showing you a full stack trace.
If you need to get the full stack trace, update your config/logging.php
file and adjust the stderr
channel to include a formatter_with
configuration:
'stderr' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => StreamHandler::class,
'formatter' => env('LOG_STDERR_FORMATTER'), // JsonFormatter
'formatter_with' => [
'includeStacktraces' => true,
],
'with' => [
'stream' => 'php://stderr',
],
],