Drupal contributed modules via Docker

Kevin Wenger
6 min readDec 7, 2020

Let’s dive into a simple solution to ease your contribution process to Drupal modules & themes.

For a fair amount of time I’m contributing to Drupal in the form of Contributed Modules, patches to Core and Documentation.

During my journey as a contributor I have been stuck trying to solve some simple problems:

  • How to contribute to many modules without having to Bootstrap a Drupal project for each of them ?
  • How to tests those modules in a different version of Drupal to ensure compatibility and stability ?
  • How could I accelerate my development by isolating my modules from each other ?
  • When one of my contributed modules required 3rd-party integration (Solr, Elasticsearch, Redis), How can I isolate the installation of it ?

The beauty of contributing to open source is that you can clone your favorite project, get it running locally, and test out experiments and changes in real time! Way to feel like a wizard.

This article outlines my experience learning to contribute to Drupal and why I created Drupal Docker Container for Contributions.
A Docker image for Drupal contributors giving a solution to quickly setup a Docker for both contributed modules or contributed themes.

Dockerize your contrib modules to move faster

I see way too many developers creating awesome modules and struggling to test them by having to bootstrap a complete clean Drupal environment and symlinks the custom modules/themes inside it.
With this Docker image, I want to highly simplify this process by having a containerized Drupal used for manual or automated testing of modules/themes Contributions projects.

The Bad Fish Paradigm

A big fish in a small pond 🐟

My journey started 4 years ago. During my first year of contribution I had a single “Drupal Sandbox” project and decided to symlinked all contributed modules I developed for in the modules\contrib directory.

Some would say I put all my eggs in one basket …
But guess what ? Yes I did, and it worked ….

Well it worked, until I developed for 20+ contributed modules symlinked on the same “Drupal Sandbox”.
Imagine dealing with each modules being in a pretty unstable release (dev branch FTW 🎉), sometimes requiring different version of the same dependency or just not being compatible with the same Drupal version.

I got stuck and everything explode spectacularly 💣 💥 .

The Spaghetti Catalyst

maintenance is easy with everything in one place — isn’it ? 🙈

Well obviously having one single “Drupal Sandbox” project was not a pretty good idea.

diaírei kài basíleue, in ancient Greek: «divide and rule»
- Philip II of Macedon

So I decided to split my “Drupal Sandbox” into multiple “Drupal Sandboxes” each by Drupal version I wanted to support (“Drupal Sandbox 8.6”, “Drupal Sandbox 8.8”, …).

This solution solved my incompatible dependencies problem and my cascade of unstable modules as I isolated every module into its own Sandbox when it was necessary.

At this time, I was an active maintainer of Travis CI, a Travis solution to test Drupal modules with PHPUnit. I added it on each of my projects and used the used it for automated testing on CI — allowing me to tests multiple versions of Drupal on CI.

Once again, it worked …. I had to deal with many “Drupal Sandboxes” (growing each days), but it works.

Well it worked, until I had to deal with bigger contributed modules requiring different PHP versions and requiring 3rd-party such as Redis, Solr Elasticsearch (obviously each of them in many disparate versions for backward compatibilities 🙏).

Once more, imagine me trying to make sense of all those Spaghetti “Drupal Sandboxes”, having different symlinked projects, connected to 3rd-party software (each one in a different random port 😵) …

I got overwhelmed by all those “Drupal Sandboxes” and Services 🙀 .

The Space Whale Resurgence

Just keep swimming 🐳

Well … Obviously working locally was driving me crazy. I had to figure out how to works with those modules in a complete new way.
I decided to get the problem upside down.

It might help to spin up a Docker container with the software application you need to test.

Docker seems promising, it solves the isolations problems, the server architecture versions and it will accelerate my development by containerising all the necessary services … Bonus point, it will make my modules way more easy for others to contribute to 💪 .

So I dive into this exciting new idea.

I started looking for Drupal Docker images and found a bunch of them on Docker Hub.
Unfortunately, my dreams fade quickly 😿 … all of those images serve the same purpose, integrate Docker into a complete Drupal project, none of them was made for standalone modules/themes contributions.

Well … nothing seems to exist as I need it … Then I decided to create my own, extending the official Drupal images for standardization and stability .

How to use this image

  1. Create a Dockerfile file at the root level of your contributed modules/themes
ARG BASE_IMAGE_TAG=8.9.0
FROM wengerk/drupal-for-contrib:${BASE_IMAGE_TAG}

You may want to update the default BASE_IMAGE_TAG to be used following your module current supporting version.

2. Then create a docker-compose.yml file in the same location and update the mounted volume name to match your custom module name

version: '3.6'services:drupal:
build: .
depends_on:
- db
ports:
- 8888:80
volumes:
# Mount the module in the proper contrib module dir.
- .:/var/www/html/modules/contrib/my_module
restart: always
db:
image: mariadb:10.3.7
environment:
MYSQL_USER: drupal
MYSQL_PASSWORD: drupal
MYSQL_DATABASE: drupal
MYSQL_ROOT_PASSWORD: root
restart: always

3. Spin up the Docker integration

$ docker-compose build --pull
$ docker-compose up -d drupal
# wait on Docker to be ready, especially MariaDB that takes many seconds to be up before install.
$ docker-compose exec -u www-data drupal drush site-install standard --db-url="mysql://drupal:drupal@db/drupal" --site-name=Example -y

4. (Optionally) You may want to setup a different Drupal Docker versions for testing, then use the build argument BASE_IMAGE_TAG

$ docker-compose build --pull --build-arg BASE_IMAGE_TAG=9.0 drupal
$ docker-compose up -d drupal
# wait on Docker to be ready, especially MariaDB that takes many seconds to be up before install.
$ docker-compose exec -u www-data drupal drush site-install standard --db-url="mysql://drupal:drupal@db/drupal" --site-name=Example -y

Travis Integration example

Now having a Docker working environment, let’s use it to run our tests inside our containers.

  1. Create a .travis.yml file at the root level of your repository
language: phpservices:
- docker
env:
global:
# The module name to be mounted and tested in the Docker.
- MODULE_NAME="my_module"
jobs:
include:
- name: D8.8
env: BASE_IMAGE_TAG="8.8"
- name: D8.9
env: BASE_IMAGE_TAG="8.9"
- name: D9.0
env: BASE_IMAGE_TAG="9.0"
before_install:
- docker-compose build --pull --build-arg BASE_IMAGE_TAG=${BASE_IMAGE_TAG} drupal
- docker-compose up -d drupal
# wait on Docker to be ready, especially MariaDB that takes many seconds to be up.
- docker-compose exec drupal wait-for-it drupal:80 -t 60
- docker-compose exec drupal wait-for-it db:3306 -t 60
before_script:
- docker-compose exec -u www-data drupal drush site-install standard --db-url="mysql://drupal:drupal@db/drupal" --site-name=Example -y
script:
- docker-compose exec -u www-data drupal phpunit --no-coverage --group=${MODULE_NAME} --configuration=/var/www/html/phpunit.xml

Feedback

At any point during the contributing process I would love to help!
For help with a specific problem you can open an issue on Github.

Usage examples

Sources

For the most curious of you, here are some sources of additional information that inspired the creation of this article.

Github (21 August, 2020). Drupal Docker Container for Contributions
Seen on https://github.com/wengerk/docker-drupal-for-contrib

Tess Flynn (07 August, 2020). Drupal Development with Docker
Seen on https://drupalize.me/series/drupal-development-docker

Drupal Documentation (21 August, 2020). Docker based development environment
Seen on https://www.drupal.org/node/2736447

Pierre Abreu (14 April, 2019). Improve Drupal 8 performance on Docker and OSX
Seen on https://medium.com/faun/improve-drupal-8-perf...

Gerardo Fernández (19 December, 2019). How to integrate Docker into a Symfony-based project
Seen on https://medium.com/@ger86/how-to-integrate-...

--

--

Kevin Wenger

Swiss Web Developer & Open Source Advocate @antistatique | @Webmardi organizer | Speaker | Author | Drupal 8 Core contributor