Deploy Laravel with Postgres

This guide deploys a Laravel app to Naijacloud with a managed Postgres database. At the end you’ll have Laravel serving its welcome page over HTTPS at your own naijacloud.app address, with sessions, cache and the job queue stored in Postgres and migrations run every time the app starts. The stack is Laravel 13 on PHP 8.4 and FrankenPHP, with Postgres 18, built from a Dockerfile in your GitHub repository.

20 minBeginnerLast verified 2026-10-11laravelpostgres
What you'll have at the end

Laravel’s welcome page on your own naijacloud.app address. Every visit writes a session row to Postgres, and /up answers 200 when the app is healthy.

Before you start

  • A Laravel app in a GitHub repository, with composer.lock committed. Starting fresh? Run composer create-project laravel/laravel shop and push it.
  • PHP and Composer on your machine, to generate an app key.
  • A Naijacloud account. The free tier covers this guide: one web service and one database.

Why this guide uses a Dockerfile

Naijacloud can build PHP apps without a Dockerfile, but for Laravel today you want one. Two reasons, both found on the run this guide is based on:

  • A new Laravel app ships a package.json with Vite in it, so the detector reads the repo as a Vite static site rather than a PHP server.
  • The automatic PHP build uses PHP 8.3, and a current Laravel lock file needs PHP 8.4.

With a Dockerfile at the root of the repo, Naijacloud builds and runs that instead, and the build log says Building from your Dockerfile.

Add the Dockerfile

This one uses the FrankenPHP image, a production PHP server, adds the Postgres driver and Composer, installs your dependencies, checks the app's health on Laravel's /up route, and on start runs migrations before serving on the port Naijacloud gives it:

Dockerfile
FROM dunglas/frankenphp:1-php8.4
RUN install-php-extensions pdo_pgsql intl zip opcache
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app
COPY . .
RUN composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
HEALTHCHECK CMD curl -fsS http://localhost:${PORT:-8000}/up || exit 1
CMD php artisan migrate --force && php artisan config:cache && exec frankenphp php-server --root public/ --listen ":${PORT:-8000}"

Keep your local dependencies and secrets out of the image:

.dockerignore
vendor
node_modules
.env
storage/logs/*
.git

Trust the proxy

Naijacloud terminates HTTPS in front of the app. Tell Laravel to trust the forwarded headers so it generates https:// URLs. In bootstrap/app.php:

bootstrap/app.php
->withMiddleware(function (Middleware $middleware): void {
// Naijacloud terminates HTTPS in front of the app.
$middleware->trustProxies(at: '*');
})
Terminal
$ git add .
$ git commit -m "Dockerfile for Naijacloud"
$ git push

Create the database

In the dashboard, open your project and choose New service → Database. Name it shop-db, pick Postgres, choose the Free size and click Create database. On the shop-db is ready. screen, click Reveal secrets and copy the Internal URL. The password is shown once on this page.

Create the web service

Choose New service → Web service, name it shop and pick your repository and branch on the GitHub tab. Then:

  • Under Run it as, choose Server. The detector suggests Static site because of Vite.
  • Open Advanced and set Port to 8000, the port the Dockerfile listens on when Naijacloud sets PORT.

The build and start commands in the form don’t run for this service: the Dockerfile’s RUN and CMD do.

Set the variables

Generate an app key on your machine:

Terminal
$ php artisan key:generate --show
base64:4bN3Xq…

Under Environment variables, click Paste .env and paste these, with your own values, then Add variables:

APP_KEYThe key you just generated, including base64:
APP_ENVproduction
APP_DEBUGfalse
APP_URLhttps://shop.naijacloud.app
DB_CONNECTIONpgsql
DB_URLThe Internal URL you copied from the database
LOG_CHANNELstderr, so Laravel’s logs appear under Logs

Deploy and open it

Leave the size on Free and click Create web service. Free apps may sleep when nobody visits for a while and wake on the next request; paid apps never sleep. When the deploy goes live, the runtime log shows the migrations:

Runtime log · shop
INFO Preparing database.
Creating migration table ....................... DONE
INFO Running migrations.
0001_01_01_000000_create_users_table ........... DONE
0001_01_01_000001_create_cache_table ........... DONE
0001_01_01_000002_create_jobs_table ............ DONE

Open https://shop.naijacloud.app. Laravel’s welcome page loads, and the visit has written your first row to the sessions table in Postgres. https://shop.naijacloud.app/up is Laravel’s health route; set it as the Health check path under Advanced if you want each deploy to wait for it.

Whatever you build it with, it ships here.

Deploy your app for free

Free tier forever · No card