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

How to Simplify Setup of Complex Drupal Sites with Docker and Expresso PHP

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


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


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


The first line will look something like this:

FROM php:7.2-fpm


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



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.


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


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',


Edit settings.php and replace

$settings['hash_salt'] = '';


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


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


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.


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

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


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.


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


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.


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.