This solution describes how to deploy a custom WordPress installation using Dokku. Note that the WordPress application container is using Nginx with PHP FPM.
Creating an Application
Connect to the server and create your app(s):
ssh username@server-id.healthcareblocks.com dokku apps:create my-app-name
Preparing Your Application for Deployment
Do the following steps on your local development machine:
1. Add a file named Procfile to the root of your application and specify the startup command.
web: vendor/bin/heroku-php-nginx -C nginx_app.conf --verbose
2. Add a file named nginx_app.conf to the root of your application repo, with the following contents. Some of the settings are optional.
# Permalinks location / { index index.php index.html; try_files $uri $uri/ /index.php?$args; } # Adds trailing slash to */wp-admin requests rewrite /wp-admin$ $scheme://$host$uri/ permanent; # Deny access to any files with a .php extension in the uploads directory # Works in sub-directory installs and also in multisite network location ~* /(?:uploads|files)/.*.php$ { deny all; } # Max upload size client_max_body_size 100M; # Optimizations fastcgi_buffers 8 32k; fastcgi_buffer_size 64k; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; # Compression gzip on; gzip_min_length 1000; gzip_comp_level 2; gzip_buffers 4 32k; gzip_types text/plain application/javascript text/xml text/css image/svg+xml; gzip_vary on; # Set time to expire for headers on assets location ~* .(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; } # Sitemap url (if using the WordPress SEO plugin) #rewrite ^/sitemap_index.xml$ /index.php?sitemap=1 last; #rewrite ^/([^/]+?)-sitemap([0-9]+)?.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;
3. 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 the root of your source control repository and not within a subdirectory.
If your app does not have any library dependencies and your application is compatible with the latest stable version of PHP, add a composer.json file containing empty JSON curly braces - {}. This is necessary in order for the deployed application to be recognized as a PHP application.
To specify a different PHP version:
{ "require": { "php": "^5.6.0" } }
Supported PHP Versions
- 5.5
- 5.6
- 7.0
Don't forget to freeze the composer file and add the composer.json and composer.lock files to source control:
composer update
Included Extensions
The following built-in extensions are enabled automatically on Healthcare Blocks and do not need to be specified in composer.json. In addition, any extensions that PHP enables by default, such as DOM, JSON, PCRE or PDO, are also included in the environment.
- Bzip2
- cURL
- FPM
- mcrypt (5.5 and 5.6 only)
- MySQL (PDO) (uses mysqlnd)
- MySQLi (uses mysqlnd)
- OPcache
- OpenSSL
- PostgreSQL
- PostgreSQL (PDO)
- Readline
- Sockets
- Zip
- Zlib
Additional extensions are built as "shared" and need to be explicitly referenced in your composer.json. Since Heroku maintains the PHP buildpack used by Dokku, refer to their page for additional details on this topic.
Example composer.json
{ "require": { "php": "~5.6.0", "ext-mbstring" : "*", "ext-gd": "*", "ext-curl": "0.0.0.*", "ext-exif": "0.0.0.*" }, "scripts": { "post-install-cmd": [ "chmod -R 777 wp-content" ] } }
4. On the server, define any environment variables, especially addresses for external databases / services, API keys, and any other production-specific setting you don't want to store in your source code.
5. In your source code, copy wp-config.php.sample to wp-config.php, using the environment variables you set above. Example:
$_SERVER['SERVER_PORT'] = "80"; // ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define('DB_NAME', getenv('DB_NAME')); /** MySQL database username */ define('DB_USER', getenv('DB_USER')); /** MySQL database password */ define('DB_PASSWORD', getenv('DB_PASSWORD')); /** MySQL hostname */ define('DB_HOST', getenv('DB_HOST')); /** Database Charset to use in creating database tables. */ define('DB_CHARSET', 'utf8'); /** The Database Collate type. Don't change this if in doubt. */ define('DB_COLLATE', ''); /**#@+ * Authentication Unique Keys and Salts. * * Change these to different unique phrases! * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service} * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again. * * @since 2.6.0 */ define('AUTH_KEY', getenv('AUTH_KEY')); define('SECURE_AUTH_KEY', getenv('SECURE_AUTH_KEY')); define('LOGGED_IN_KEY', getenv('LOGGED_IN_KEY')); define('NONCE_KEY', getenv('NONCE_KEY')); define('AUTH_SALT', getenv('AUTH_SALT')); define('SECURE_AUTH_SALT', getenv('SECURE_AUTH_SALT')); define('LOGGED_IN_SALT', getenv('LOGGED_IN_SALT')); define('NONCE_SALT', getenv('NONCE_SALT'));
6. In most cases, your database will be running on a separate machine via our database-as-a-service plan. You should have received connection information and credentials during the on-boarding process.
- Connecting to a MySQL database
- For PostgreSQL or MongoDB databases, refer to the "Database Configuration" info in the Dokku Getting Started guide
Deploy your App
Frequently Asked Questions
How do I persist uploaded files, themes, plugins, etc.?
Dokku uses a Docker container to run your WordPress application. By default, containers use an ephemeral filesystem, which is not guaranteed to persist any files that are modified or added after your application is deployed and running. What you'll need to do on the server is define a storage mount. This should be done when deploying your application for the first time.
- First, create a directory where your files will be stored on the server. We recommend using any path under the encrypted data volume (/data):
ssh username@server-id.healthcareblocks.com mkdir -p /data/wp-content/plugins /data/wp-content/themes /data/wp-content/uploads chown -R 32767:32767 /data/wp-content
- Next, configure your app to leverage the above paths:.
dokku storage:mount my-app-name /data/wp-content/plugins:/app/wp-content/plugins dokku storage:mount my-app-name /data/wp-content/themes:/app/wp-content/themes dokku storage:mount my-app-name /data/wp-content/uploads:/app/wp-content/uploads
- Lastly, re-deploy your application and confirm that dynamic content is being saved to the proper location. If everything is working correctly, you should see newly uploaded files appear under /data/wp-content on the server.
Important note: if your project code repository tracks changes to wp-content/plugins or wp-content/themes, these directories will get overwritten by the storage mount settings above. So you'll need to either remove them from your code and upload them via the WordPress admin panel, or not create a storage mount for the directory that you'd like to keep under source control.
Additional Documentation
More help topics can be found in the Dokku Getting Started guide.