For an introduction to dokku: https://gyaaniguy.top/blog/dokku/
In Brief: dokku is an application to manage hosting websites easily on your own server. It does so by using docker. Automating the tasks of installing servers/databases, configuring various services, running, building, handling ssl etc.
General steps:
First install dokku on your server. Then create a dokku project on the server. Setup ssl, some options, environment variables for laravel.
Next we configure our laravel project
- PHP's composer.json file. Dokku uses it to install PHP extensions
- add dokku configurations files in our laravel project.
Then we configure sqlite. Which is default database in laravel v11
Finally we have a workaround to deal with vite's quirk.
Create dokku application
Run on your server.
!! Set the 2 variables below !!
APP_NAME="p2" ; DOMAIN="p2.gyaaniguy.top" ;
# Create the app
dokku apps:create "$APP_NAME"
# Set the domain
dokku domains:set "$APP_NAME" "$DOMAIN"
# Enable Let's Encrypt for SSL
dokku letsencrypt:enable "$APP_NAME"
# Setup Environment Variables
dokku config:set "$APP_NAME" APP_NAME="$APP_NAME" APP_ENV="production" APP_DEBUG="false"
Note: environment variables, to configure laravel are passed via dokku config:set KEY_NAME=value . These are typically stored in .env file
Setup composer.json
We'll need to explicitly tell dokku to install php extensions, like ext-pdo_sqlite.
Add the extensions to the require section in composer.json. Adjust the PHP version to match your server. Note the pdo_sqlite line for sqlite. MariaDB / postgres will require different extensions.
"require": {
"ext-ctype": "*",
"ext-curl": "*",
"ext-exif": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pdo": "*",
"ext-openssl": "*",
"ext-tokenizer": "*",
"ext-xml": "*",
"ext-zip": "*",
"ext-pdo_sqlite": "*"
},
Now Run composer update on local
Local dokku settings
We will add a few more files to your laravel app.
.buildpacks file in the root of your laravel project:
https://github.com/heroku/heroku-buildpack-php
https://github.com/heroku/heroku-buildpack-nodejs
!!! Order is important !!
These instruct dokku to run commands like composer install. The nodejs buildpack runs the frontend vite / laravel_mix build. It's optional, but laravel uses @vite by default. If you are not using vite, you can drop the nodejs buildpack.
Create a Procfile file in the root of your laravel project, to run migrations:
release: php artisan migrate --force
web: vendor/bin/heroku-php-apache2 public/
Now push your project to the server. See the Intro article for instructions
Set APP_Key
This is an encryption used by laravel. There should be a better way of generating it. But I can't quite figure it out !
dokku run "$APP_NAME" php artisan key:generate --show
Copy the output - base64:Ng9mTA83j+Y7FZJSj22oSa6zw6r260Y9VRot01xG80U=
Then paste here
dokku config:set "$APP_NAME" APP_KEY="PASTE_HERE"
# dokku config:set "$APP_NAME" APP_KEY="base64:Ng9mTA83j+Y7FZJSj22oSa6zw6r260Y9VRot01xG80U="
Setup Database (sqlite)
Dokku runs in containers, which get destroyed every time the website is deployed. So it's important to keep database files outside the container. We do this by creating a directory on the server, then mounting it in the container. Dokku makes this easy.
# Create a directory for storage
dokku storage:ensure-directory "$APP_NAME"
# Mount it on the app container
dokku storage:mount "$APP_NAME" "/var/lib/dokku/data/storage/$APP_NAME:/app/databasedir"
# Set environment variable for laravel
dokku config:set "$APP_NAME" DB_DATABASE=/app/databasedir/database.sqlite DB_CONNECTION=sqlite
PS: Don't forget the sqlite extension (
ext-pdo_sqlite) incomposer.json, as shown earlier.
Fix https error with vite
If you are using Vite, you may get https issues with css/js files. Why? Because your dokku app is behind a reverse proxy.
Mixed Content: The page at 'domain.com' was loaded over HTTPS, but requested an insecure ...
Normal: User -> Apache -> site Dokku: User -> Nginx -> [forwards to] -> Docker container (apache or nginx) -> site
Some headers sent by the user get lost along the way. Nginx then re-sends some of them to apache, but apache doesn't know who is sending them, since the user could be spoofing them. The fix: tell apache to trust the proxy headers, since they come from a known proxy.
use Symfony\Component\HttpFoundation\Request;
->withMiddleware(function (Middleware $middleware) {
$middleware->trustProxies(headers:
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB
);
$middleware->trustProxies(at: '*');
})
Ideally laravel should handle this automatically....
Troubleshooting
dokku logs "$APP_NAME"- Run
composer updateafter modifying composer.json - Enable and set logs. They will log important errors !
# Set the environment variables to enable log.
# set LOG_LEVEL=info to see more entries. Check laravel docs for more.
dokku config:set "$APP_NAME" APP_DEBUG=true
# enter the docker container
docker exec -it $(docker ps | grep "$APP_NAME" | awk 'NR==1 {print $1}') bash
# watch logs
tail -f /app/storage/log/logging.txt
- Check if vite is being used.
@vite() - .buildpacks and Procfile file names are case-sensitive.
- Order of .buildpacks file
- Is sqlite being installed properly ? Check the
git pushlog. It contains a lot of useful info
If log is empty. Then add some logging Log::debug('manual debug message');
References:
https://dev.to/vdsmartin/deploying-a-laravel-app-using-dokku-5bi3 https://laracasts.com/discuss/channels/vite/laravel-vite-assets-blockedmixed-content-issues-in-production-environment