Home >Backend Development >PHP Tutorial >Prepare your Laravel app for the cloud
The recent announcements at LaraconUS have sparked a renewed interest in cloud-based deployments within the Laravel community. As the debate continues on how to deploy your apps, one thing is clear: the cloud is becoming a more viable option for Laravel users.
In this article, we'll explore how to prepare your Laravel app for deployment in a cloud environment using FrankenPHP, Caddy, Dockerfiles, and finally deploying it to Sevalla.
So where do we start? In the local environment of course! ?
For the sake of simplicity, we'll assume you have a fresh Laravel app installed on your local machine, which connects to a PostgreSQL database to read/write some data.
Before we move on, make sure you have a .env
file in your project root with the following content:
.env
:
<!-- Syntax highlighted by torchlight.dev -->... DB_CONNECTION=pgsql ...
Once that's verified, we can start building. ? ☕️
It's always a good idea to have a local development environment that closely resembles your production environment. This way, you can catch any issues early on and avoid surprises when you deploy your app in production.
To mimic the production setup we're going to use Docker and Docker Compose. If you don't have Docker installed on your machine, you can download it from the official website.
First off, create a new file called compose.yml
in the root of your Laravel project and add the following content:
compose.yml
:
<!-- Syntax highlighted by torchlight.dev -->services: php: image: dunglas/frankenphp:php8.3-bookworm environment: SERVER_NAME: ":8080" ports: - 8080:8080 volumes: - .:/app
This configuration file defines a service called php
that uses the dunglas/frankenphp:php8.3-bookworm
image, which is a FrankenPHP image that includes necessary extensions to run a Laravel app.
The SERVER_NAME
environment variable configures Caddy to listen on port 8080
.
We also expose port 8080
to access the app from the host machine.
To test your configuration, try running the following command in your terminal:
<!-- Syntax highlighted by torchlight.dev -->docker compose up [-d]
You should see a Laravel error page explaining the connection was not established to the database because of a missing driver when you navigate to http://localhost:8080
in your browser. This is expected as we haven't connected our Laravel app to a database yet.
Awesome, so far we've configured our Laravel app to be served by a FrankenPHP server.
Next, let's connect our local app with a PostgreSQL database!
To connect your Laravel app to a PostgreSQL database, we'll need to do a couple of things.
First, we need to set the following environment variables in your .env
file:
.env
:
<!-- Syntax highlighted by torchlight.dev -->... DB_CONNECTION=pgsql ...
Following that, you'll need to add new services to your compose.yml
file, and create a custom Dockerfile
for your dev environment. Create and update the files with the following content:
Dockerfile.dev
:
<!-- Syntax highlighted by torchlight.dev -->services: php: image: dunglas/frankenphp:php8.3-bookworm environment: SERVER_NAME: ":8080" ports: - 8080:8080 volumes: - .:/app
Dockerfile.dev
is only meant to be used by your local/development environment, and it extends the dunglas/frankenphp:php8.3-bookworm
image to include the pdo_pgsql
extension, which is required to connect to a PostgreSQL database.
compose.yml
:
<!-- Syntax highlighted by torchlight.dev -->docker compose up [-d]
There is a lot going on here, let's take a look at what has changed and why:
php
service to use a custom Dockerfile called Dockerfile.dev
to build a new image that includes the necessary extensions to connect to a PostgreSQL database.db
that uses the postgres:16.4-alpine
image to run a PostgreSQL database. We've also defined some environment variables to set up the database user, password, and database name.db_data
to persist the data in the database on your machine, and Docker could reuse it when you restart the services.init
was also added that reuses Dockerfile.dev
. This image is used to run the php artisan migrate
command to run your database migrations. The depends_on
key ensures that the db
service is up and running before the migrations are run.php
service now depends on the init
service to ensure that the database migrations are run before the Laravel app starts.db
service to ensure that the PostgreSQL database is up and running before the init
service runs the migrations.To test your configuration, run the following command in your terminal:
<!-- Syntax highlighted by torchlight.dev -->... DB_CONNECTION=pgsql DB_HOST=db DB_PORT=5432 # default PostgreSQL port DB_DATABASE=main DB_USERNAME=admin DB_PASSWORD=password
Your application should now be connecting to your PostgreSQL database, and your database migrations are always run. ?
Your local envnironment is now ready to mimic your production environment. You can now develop your app locally and test a really similar setup you'll use in production.
It's time to make the necessary changes for your production environment.
The first step is to tell Docker which directories it can safely ignore when building the production image. Create a new file called .dockerignore
in the root of your Laravel project and add the following content:
.dockerignore
:
<!-- Syntax highlighted by torchlight.dev -->FROM dunglas/frankenphp:php8.3-bookworm RUN install-php-extensions pdo_pgsql
This file tells Docker to ignore the vendor
, bootstrap/cache
, and tests
directories.
Then, create a Dockerfile
that will be used to build your production image:
Dockerfile
:
<!-- Syntax highlighted by torchlight.dev -->... DB_CONNECTION=pgsql ...
This Dockerfile
is similar to the Dockerfile.dev
we created earlier, but it includes a few additional steps:
SERVER_NAME
environment variable to :8080
to instruct Caddy to listen on port 8080
.@composer
PHP extension to install Composer in the image.composer install
command is run to install the dependencies of your Laravel app./app
and copied the contents of your Laravel app to the image.To test your changes in your local environment, you'll need to produce a production build of your app. Run the following command in your terminal:
<!-- Syntax highlighted by torchlight.dev -->services: php: image: dunglas/frankenphp:php8.3-bookworm environment: SERVER_NAME: ":8080" ports: - 8080:8080 volumes: - .:/app
This command builds a new Docker image called my-laravel-app
based on the Dockerfile
in the current directory.
To test your newly built production image, use the following command:
<!-- Syntax highlighted by torchlight.dev -->docker compose up [-d]
Replace <your-app-key>
with the value of the APP_KEY
environment variable in your .env
file or grab a key from here.
Visit localhost:8080 in your browser, and your app should start in production mode. It may error due to the lack of a database connection, but that's expected.
Now that you have a production-ready Docker image, you can deploy it to a cloud provider. ?
In this tutorial, we'll use Sevalla, a new cloud provider that offers a simple way to deploy Dockerfile
-based deployments.
As your app depends on a PostgreSQL database, you're better off provisioning a new PostgreSQL database on Sevalla first. Once you're logged in the Sevalla dashboard,
Once your database is ready, you can create your Laravel app on Sevalla.
APP_KEY
environment variable required by LaravelDockerfile
as build typeIf your app is ready, you can now connect it with your PostgreSQL database.
Then, set the following environment variables in the "Environment variables" tab with your database's connection details:
DB_CONNECTION
DB_HOST
DB_PORT
DB_DATABASE
DB_USERNAME
DB_PASSWORD
We recommned using the internal network address of your database as the DB_HOST
value. This way, your app can connect to the database over a private network.
The last step is to set up a Job process for your application to run the database mirgations before starting the app.
php artisan migrate --force
If this is also done, you can now initiate a manual deployment of your app in the Deployments tab. ?
If all went well, congrats! You've successfully prepared your Laravel app for the cloud. ?
In this article, we've explored:
docker compose
.By following these steps, you can take your Laravel app to new heights and enjoy the benefits of cloud-based deployments. ?
We received valuable feedback from the community through a discussion on X.
The first point highlighted that including the php artisan serve
command in the compose.yml
file was unnecessary, as it bypassed the FrankenPHP server. We've corrected this by updating the relevant sections of the compose.yml
file.
The second point, shared by Kévin Dunglas (creator of FrankenPHP), recommended using a Debian-based image (bookworm
) instead of Alpine (alpine
), as Debian offers better compatibility with PHP and better performance with FrankenPHP. As a result, we updated both the Dockerfile.dev
and Dockerfile
files.
We're grateful for the community's support and feedback. ? ❤️
The above is the detailed content of Prepare your Laravel app for the cloud. For more information, please follow other related articles on the PHP Chinese website!