Preparing the App

Create a file named Procfile in your project's root directory to define the command used to start your app (in a production environment, in most cases).

If you'd like to use Apache as the backend app server:

web: vendor/bin/heroku-php-apache2

If you'd like to use Nginx as the backend app server:

web: vendor/bin/heroku-php-nginx

For the above statements, if you need to set a document root, add it to the end. For example, if your document root is named public:

web: vendor/bin/heroku-php-apache2 public/

This declares a single process type, web, and the command needed to run it. The name web is important here - this process type will be able to receive web traffic when deployed.

Procfiles can contain additional process types. For example, you might declare one for a background worker process that processes items off of a queue.

Use PHP Composer to define PHP extensions that are dependencies for your application. Be sure you have Composer installed, and add a composer.json to your project's root directory. If you do not specify a PHP engine version, Dokku will use the latest stable version as shown on PHP Supported Versions.

To specify a PHP version:

{
  "require": {
    "php": "^8.1.0"
  }
}

You must use a version that is under "Active Support" or "Security fixes" on the above PHP page in order to satisfy HIPAA/security requirements.

If your app does not have any library dependencies and your application is compatible with the latest stable version of PHP, create a composer.json file containing empty JSON curly braces: {}

Available Built-in Extensions and Third-Party Extensions

Please refer to this table for a list of extensions that are available in the PHP Dokku runtime environment. Items with a checkmark are included by default whereas the ones with an asterisk (*) need to be added to composer.json.

Additional third-party extensions need to be explicitly referenced in your composer.json.

Add any required extensions to composer.json:

"require": {
  "ext-bcmath": "*",
  "ext-mcrypt": "*"
}

Then, run the following command:

composer update

Create the Dokku App on the Server

Connect to the Healthcare Blocks virtual machine:

ssh username@server-id.healthcareblocks.com

Tip: alternately, use the Dokku Client directly from your local machine instead of connecting to the server.

Create a new Dokku app:

dokku apps:create my-app

Configure Environment Variables

Define app-specific environment variables that your framework can use to control environment-specific behavior:

dokku config:set my-app APP_DEBUG=true FOO=another_value

In PHP, these settings can be retrieved via $_ENV:

<?php
echo 'Debugging enabled? ' .$_ENV["APP_DEBUG"];
?>

And PHP frameworks like Laravel have their own conventions:

'debug' => env('APP_DEBUG', false)

Healthcare Blocks recommends storing sensitive values, including database credentials, in an .env file or equivalent on the server. See this topic for details.

Be sure your application is configured to communicate with any non-local databases using SSL/TLS. Details here.

Configure a Buildpack

Dokku uses an auto-detect function to identify which buildpack is best suited for your application type, however, Healthcare Blocks recommends explicitly configuring the buildpack to avoid any issues.

If you'd like to always use the latest version of the PHP buildpack, use the following format:

dokku buildpacks:add my-app \
  https://github.com/heroku/heroku-buildpack-php.git

If you'd like to lock in a specific buildpack release, append the GitHub tag name to the end of the URL:

dokku buildpacks:add my-app \
  https://github.com/heroku/heroku-buildpack-php.git#v216

Release tags can be found here, and the corresponding change log is here.

Reference

Deploy your App

On your local machine, ensure you've initialized your local git repository and committed all files that will be deployed to the server. Development logs and assets and temporary files should be excluded in your .gitignore file.

Define a local git remote that references the Healthcare Blocks server and the app you created above:

git remote add hcb \
 dokku@server-id.healthcareblocks.com:my-app

Notice the "dokku" username. Even though you have a dedicated Linux user on the server, your SSH key is also associated with a dokku user that is used for handling deployments and remote commands.

To deploy the app:

git push hcb main

Main (or master in older git repositories) is the name of the branch you are pushing to on the server and should not be changed. To deploy a different local branch, for example, "integration":

git push hcb integration:main

Alternative Deployment Methods

Dokku is flexible and supports additional options besides buildpacks / git push:

Using Dockerfiles instead of Buildpacks

See Dockerfile Deployment.

Using External Docker Images

If you are already building a Docker image externally and want to use it as the basis for your Dokku app, see Initializing an app repository from a Docker image.

Other External Sources

Instead of using git push from a local machine, you can initialize/update a Dokku app using an archive file or external repository (including private ones).

Frequently Asked Questions

Should I pick Apache over Nginx when defining my Procfile run command?
Apache is more popular and required if your PHP framework requires .htaccess file support. Nginx, on the other hand, runs leaner and faster in virtual machine environments.

How do I run the equivalent of php -i with Dokku?

dokku --rm run my-app php -i

How do I write to the error log?
The PHP error log is automatically sent to stderr, and any message logged using the error_log function will thus be available in dokku logs:

error_log("my debug message");

The alternative approach is to write errors to the php://stderr stream directly:

file_put_contents("php://stderr", "my debug message \n");

App frameworks like Laravel typically have their own logging configuration. Relevant channels should use the errorlog or monolog driver:

<?php
return [
    'default' => env('LOG_CHANNEL', 'stack'),
    'channels' => [
        'single' => [
            'driver' => 'errorlog',
            'level' => 'debug',
        ],
…

If not using a PHP framework, one solution is to add a file named .user.ini to your project's root directory and include the following settings:

log_errors = On
error_log = /dev/stderr
error_reporting = E_ALL

How do I override the default PHP settings?
To override php.ini settings, inside the .user.ini file, you can include custom settings. For example:

upload_max_filesize = 5M

You can also include .user.ini files on a per directory basis.

Important: if you adjust the max filesize in PHP, you'll also need to update the configuration of the reverse proxy on the server by creating a file, /home/dokku/my-app/nginx.conf.d/overrides.conf, with the following contents:

client_max_body_size 5m;

What else do I need to do for Laravel apps?
Set a Laravel encryption key that is used for sessions. On your local machine, generate a key:

php artisan key:generate --show

Then add the random key to your .env file on the server.

How do I automatically run database migrations during a release?
Add a release statement to your Procfile with the proper command. See this page for details.

Reference Application

The following PHP app is compatible with Dokku:

https://github.com/heroku/php-getting-started