Main Content
The back of a man looking at a white board with a big scribble black line between points A and B

Docker & Expresso PHP: Simplifying Drupal Development

The ever-increasing complexity and functionality of Drupal sites does not need to translate into increasingly steeper development costs.

In the past, Drupal sites were relatively homogeneous with the occasional multi-domain or multi-site implementation. Today, as sites become more complex, with features such as headless integration with non-Drupal software, the overhead of reproducing an environment locally can become very costly.

Docker was created to bridge the gap between a homogeneous Drupal implementation and a complex integration with non-Drupal software.  

Rather than running a full virtual machine locally, Docker emulates a given environment but still uses your operating system for better efficiency. This is done via "containers" for things like MySQL and PHP, enabling you to do things such as set a given PHP version for each site rather than system-wide.

As a result, the process of increasing a site’s complexity has less of an impact on onboarding time.

To build on the benefits of Docker, Expresso PHP was created. Expresso PHP is an open-source Docker setup geared toward PHP development, including Drupal.  An additional benefit: by only utilizing official Docker images, there is no need to maintain custom images.

To further illustrate the benefits of Docker and Expresso PHP, let’s walk through setting up a local Drupal environment in Drupal 8 using macOS Mojave.


Software Versions Used

  • macOS Mojave 10.14.4
  • Drupal 8.6.14
  • Docker 18.09.3
  • Docker Compose 1.24.0-rc1
  • Expresso PHP v1.1.0


Setting up Drupal using Expresso PHP

Here is a step-by-step guide to using Expresso PHP to set up Drupal.


1. Clone the Expresso PHP Git repo and begin setup.

The first step is cloning the Expresso PHP Git repo and doing some initial setup. This installation assumes you are installing Docker sites in a "Docker" directory within your local environment's home directly.

In the directions for this example, the site in question is called "my-site."

cd ~/docker
git clone my-site
cd my-site
git checkout nginx-php


2. Specify the desired PHP version.

After cloning the repo, specify the desired PHP version here:


The first line will look something like this:

FROM php:7.2-fpm


3. Clone the site's Git repo.

Next, clone the Drupal site's Git repo or otherwise add the site.  This example assumes the repo will be cloned within a directory called "my-site", so its location would be:



4. Use symlink.

Replace the existing "web" directory with a symlink to the document root:

rm -rf ~/docker/my-site/web
cd ~/docker/my-site
ln -s my-site/docroot web

This example assumes the document root is "docroot," but it could be "www" or something else.


5. Copy the settings.php.

Copy the settings.php file from default.settings.php

cd ~/docker/my-site/my-site/docroot
cp sites/default/default.settings.php sites/default/settings.php
cd sites/default

Want to learn more about Drupal? Sign up for training!


6. Replace array().

Edit settings.php and replace:

$databases = array();

with the following:

$databases['default']['default'] = [
  'database' => 'expresso-php',
  'username' => 'expresso-php',
  'password' => 'expresso-php',
  'host' => 'db',
  'port' => '3306',
  'driver' => 'mysql',
  'prefix' => '',
  'collation' => 'utf8mb4_general_ci',


7. Add espresso-php.

Edit settings.php and replace:

$settings['hash_salt'] = '';


$settings['hash_salt'] = 'expresso-php';


8. Update the hosts file.

A local domain can be used to update the hosts file. You will need to use sudo to edit /etc/hosts and add the following: my-site.test


9. (Optional) Make a directory for the site's database.

Optionally, create a directory for a copy of the site's database and place a *.sql of the database into this directory:

cd ~/docker/my-site
mkdir ref_db
cd ref_db

This is only needed if a Makefile or build script will be used, which is recommended; otherwise, DB import could be done via drush.

Note - The designated location for the reference database may be different for a given Makefile or build script.


10. Add Drupal files directory.

Add the Drupal files directory here and modify permissions if needed:

cd ~/docker/my-site/my-site/docroot/sites/default


11. Build Docker containers.

Build the Docker containers: 

cd ~/docker/my-site
docker-compose up -d

Note: This is only needed during initial set, on a daily basis, "docker-compose start" and "docker-compose stop" will be sufficient.


12. Import the Drupal database.

The next step is importing the Drupal database. Ideally this would be done via a Makefile or build script.

Alternatively, the DB import can be done via Drush:

cd ~/docker/my-site/docroot
docker-compose exec -T php_nginx drush sql-cli < ../ref_db/ecoDB.sql


13. Check port for access.

Once the DB is imported, check the port needed to access the site:

docker-compose ps

It will use the port associated with my-site_nginx_1; for example, 32768.


14. Confirm if it works.

Access the local website to confirm it works. For example, if the IP is 32768 then the site's URL would be:



Commonly Used Commands

To use Drush:

docker-compose exec php_nginx drush cr

To SSH in to the nginx container:

docker-compose exec php_nginx /bin/bash

To start services:

docker-compose start

To restart services:

docker-compose restart
docker-compose ps

"docker-compose ps" is included here since restarting services resets the port used to access the site.

To uninstall the site:

cd ~/docker/my-site/my-site/docroot
docker-compose down -v
cd ~/docker
rm -fr ~/docker/my-site

That's all there is to it. When a build script or Makefile is used, a new environment can be set up from the script in a matter of minutes. The main, limiting factor is time needed to copy in the Drupal files/ directory and import the database.

Expresso PHP and Docker are excellent tools that enable you to maintain a straightforward setup process, even as complexity increases -- serving as another clear indicator of the inherent agility of Drupal.

Looking for further insights on leveraging Drupal to achieve specific outcomes? Contact us today.