Deploying a Laravel app using Dokku
Tags: laravel, docker, tutorial, webdev
Published: 2021-11-19 18:24:55

## Introduction

Dokku is basically a self-hosted Heroku. It allows you to deploy your apps with a simple git push and it'll handle all the building and deploying automatically.

After having trouble finding an up-to-date and exhaustive how-to guide, I decided to write the steps down, It'll help me later and hopefully you as well ? Here are the steps I went through !



## Setup your server

- Create a DigitalOcean Dokku droplet or any other basic Ubuntu/Debian Server on which you [installed Dokku](https://dokku.com/docs/getting-started/installation/)

- (facultative) Point a domain or Sub-domain to your Dokku installation

- Visit your server's IP in your browser to finish the Dokku setup, make sure the SSH key is the correct one. Enter your Top Level Domain in the hostname field. I chose to use the virtualhost naming for my Dokku apps, I think it makes more sense for web apps!

- Install the MySQL plugin for Dokku on your server
```
dokku plugin:install https://github.com/dokku/dokku-mysql.git mysql
```

- (optional) Install the Let's Encrypt plugin if you want free SSL certificates
```
sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git
```



## Project Setup

- Add PHP extension requirements to `composer.json`. This tells Dokku to activate those extensions on your server. Here are the ones I needed as example !
```
"require": {
  "ext-bcmath": "*",
  "ext-ctype": "*",
  "ext-curl": "*",
  "ext-exif": "*",
  "ext-fileinfo": "*",
  "ext-gd": "*",
  "ext-json": "*",
  "ext-mbstring": "*",
  "ext-pdo": "*",
  "ext-openssl": "*",
  "ext-tokenizer": "*",
  "ext-xml": "*",
  "ext-zip": "*"
}
```

- After making the changes in `composer.json` you'll need to update it using `composer update`. You might encounter problems with the PHP extensions not being installable on your local env, in that case use `composer update --ignore-platform-reqs` to avoid installing them.

- Add a build script to package.json, it will be run automatically on deploy by Dokku
```
"scripts": {
    "production": "mix --production",
    "build": "npm run production"
  },
```

- Make sure your `config/database.php` has this line in the 'mysql' config :
`'url' => env('DATABASE_URL'),`

- Create a Procfile (a file named Procfile at the root of the project). The `release` part contains the command that'll be run right after a build. The `web` part specifies the web server to run, here we simply run the default PHP server from Heroku and point it to the `public` folder
```
release: php artisan migrate --force
web: vendor/bin/heroku-php-apache2 public/
```

- Specify the buildpacks you'll need in a .buildpacks file at the root of the project. You can see these as "build steps" before putting your application online. `heroku-buildpack-php` install your composer packages (amongst other things) and `heroku-buildpack-nodejs` install your npm dependencies and runs your build script.
```
https://github.com/heroku/heroku-buildpack-php
https://github.com/heroku/heroku-buildpack-nodejs
```



## Dokku Setup

- Create the app on the Dokku server with this command
`dokku apps:create {name_of_your_app}`

- Add the git remote on your local dev environment with :
`git remote add {remote_name} dokku@{server_url}:{app_name}`
`remote_name` can be whatever. I use "staging" and "production" for example. `app_name` is the name you gave your Dokku app at the previous step.

- Set up all your environment variables on the server using the `dokku config:set {your_app_name} VAR=VALUE VAR2=VALUE2 ...` command. Don't forget to mention an APP_KEY, APP_ENV, APP_URL, etc !

- Create a MySQL database and link it to your app (your-db-name can be anything)
```
dokku mysql:create {your-db-name}
dokku mysql:link {your-db-name} {your_app_name}
```

- Get the MySQL connection URL (mysql://user@example...) and set it as a variable for your app
```
dokku mysql:info {your-db-name} --dsn
dokku config:set {your_app_name} DATABASE_URL={connection_string_from_previous_command}
```



## Deployment

- Push your app to your Dokku server using :
`git push {remote_name}`



## (optional) Add a Let's encrypt certificate to your app !
 
- Setup your contact email for Let's encrypt and generate your certificate
```
dokku config:set --no-restart {your_app_name} DOKKU_LETSENCRYPT_EMAIL={your_email_address}
dokku letsencrypt:enable {your_app_name}
```

## All done 💃
Enjoy your app !