Dokku with Laravel cookbook
I know how frustrating it is to update the app name every time you copy a command.. That’s why I’ve created the input below π Enjoy!
My app name is: insert (appname is default)
TABLE OF CONTENTS
Why Dokku rather than Forge or Ploi?
My reasons:
- π Zero downtime deploys baked-in
- π Each app is isolated by Docker
- πΈ No additonal costs or security risks
- βΎοΈ Not limited to PHP (anything deploys)
In comparison, Forge supports zero downtime deploys by making you subscribe to Envoyer (10$/mo) or reaching out for other hacks. Even then, such setup would be limited to PHP-FPM, making it impossible to run Octane or other languages/runtimes.
SQLite as your database
Dokku stores persistent data in a “persistent” directory, so let’s create one:
dokku storage:ensure-directory appname-db
Then we can enter it to make a new production-ready WAL-mode database:
cd /var/lib/dokku/data/storage/appname-db
sqlite3 database.sqlite "
PRAGMA journal_mode = WAL;
PRAGMA auto_vacuum = INCREMENTAL;
PRAGMA page_size = 4096;
PRAGMA wal_autocheckpoint = 1000;
VACUUM;
"
Finally, let’s mount our directory to the app itself:
dokku storage:mount appname /var/lib/dokku/data/storage/appname-db:/app/database/sqlite
And set the required environment variable:
dokku config:set appname DB_DATABASE=/app/database/sqlite/database.sqlite
Octane for max performance (Dockerfile)
### Stage 1: Asset Build
FROM node:20 AS assets-builder
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
### Stage 2: Laravel Build
FROM composer:2 AS dependencies
WORKDIR /app
COPY . .
RUN composer install --no-dev --optimize-autoloader --no-interaction
### Stage 3: Final Image
FROM dunglas/frankenphp
COPY --from=composer /usr/bin/composer /usr/bin/composer
RUN install-php-extensions pcntl zip
WORKDIR /app
COPY . .
COPY --from=dependencies /app/vendor /app/vendor
COPY --from=assets-builder /app/public/build /app/public/build
EXPOSE 80
CMD ["php", "artisan", "octane:start", "--server=frankenphp", "--host=0.0.0.0", "--port=80", "--admin-port=2019"]
Queues
Procfile
lets you define multiple processes for your app. Here’s mine:
web: php artisan octane:start --server=frankenphp --host=0.0.0.0 --port=80 --admin-port=2019
release: php artisan migrate --force
queue: php artisan queue:work
But, any new process won’t be activated until we scale it up:
dokku ps:scale appname queue=1
Server and provisioning
I prefer to use Debian 12 as it does not come with any extra bloat such as Snap on Ubuntu and uses minimum resources. Besides, it’s proven to be super stable and run for years without reboots by others.
apt install unattended-upgrades -y