Check out the open-source initiative Docker4Drupal.org that will help you deploy docker-based local environment for Drupal

In this article, I will explain why you should use Docker for Drupal and demonstrate Drupal 8 deployment with the official images from Docker Hub.

What is Docker?

Docker allows you to package your application with all of its dependencies into a standardized unit called container.

Your application, for example, Drupal website, has dependencies, such as a web server (Nginx/Apache2) and a database (MySQL/MariaDB/PostgreSQL).

And usually, when you want to deploy a new copy of your website, you install these dependencies manually via OS packaging system, such as apt-get or yum, then you configure them, install extensions, etc, which is not really a great experience.

Of course, you could use orchestration tools, such as Puppet, Ansible, Salt, Chef which automate your installation and configuration process.

Or you can use completely different approach: container virtualization Docker. With Docker, you package your application into containers and then you can run these containers on almost any host. You can run it on your laptop, on a production server, inside your personal VPS or even inside of Vagrant.

Containers let you abstract from the details

If you want to learn Docker I recommend reading the official documentation “Understanding Docker”, it’s surprisingly well written.

6 reasons to use Docker for Drupal deployments

Hosting agnostic. In case you want to migrate to another hosting provider, it will much easier to do with Docker: your website is just a set of containers that can be run anywhere Cloning. If you want to spin up a new environment (e.g. development or testing instance) it’s easier to do with Docker, you just run another container of the same docker image Environment consistency. We all know this kind of problems when you find this mysterious bug on a dev instance and you can’t reproduce it, later you find out that it’s caused by some missed extension or a different version of some library. Such problems solved by design when you use containers Isolation. When you have few websites or few instances of one website on the same server it’s important to have isolation between them — you don’t want high loading on one of them to affect the others. Docker containers are isolated by design though the isolation is kind of tricky Optimal infrastructure. It’s no secret that the way you configure Nginx, PHP, MariaDB for your website affects its performance. If you’re not good at it, you can use container images on Docker Hub built by other people Scalability. Every container can be scaled both vertically (allocate more resources) and horizontally (clone the container and use a load balancer)

Let’s rock!

Since this article was posted originally we’ve launched docker4drupal initiative. It’s a recommended way to deploy docker-based environment for local development. Read docker4drupal getting started.

Ok, so we‘re going to deploy Drupal 8 with two docker containers: Apache2 + PHP and MariaDB (MySQL fork).

For this demonstration, I will spin up the smallest Droplet on DigitalOcean with Ubuntu 14.04 LTS.

Connecting to our VPS by SSH as a root and for the sake of simplicity we will disable default firewall ufw to avoid its configuration (we don’t recommend to do it):

$ ufw disable

Firewall stopped and disabled on system startup

Install Docker:

Check that everything is fine:

$ docker -D info

Containers: 0

Images: 0

Server Version: 1.9.1

Storage Driver: aufs

Root Dir: /var/lib/docker/aufs

Backing Filesystem: extfs

Dirs: 0

Dirperm1 Supported: false

Execution Driver: native-0.2

Logging Driver: json-file

Kernel Version: 3.13.0–68-generic

Operating System: Ubuntu 14.04.3 LTS

CPUs: 1

Total Memory: 490 MiB

Name: drupal8-docker

ID: GUMM:PUBZ:VJOF:52B7:ZIEN:UCJC:4QA2:BSP5:UGSW:FGPV:AZY6:ASZD

WARNING: No swap limit support

Here we can see that we have neither images nor containers, docker version, etc. By default, docker uses AUFS which allows docker to use versioning for docker images like in git, i.e. when you want to update the existing image, it won’t be downloaded entirely again, only new layers will be fetched.

Ok, now let’s download docker images. We’re going to use official images of MariaDB and Drupal. By default, if you don’t specify the absolute URL to the image it will be searched and downloaded from Docker Hub. Tag “latest” will be used by default since we don’t need any specific version.

$ docker pull mariadb

AUFS in action: layers of the image have been downloading

Now let’s download Drupal image. This time, we will specify the tag: 8.0.1.

$ docker pull drupal:8.0.1

Let’s take a quick look at the Dockerfile of this image. As you can see it’s inherited from the official PHP docker image with Apache2. Then Apache’s rewrite module is enabled, additional libraries and PHP extensions are installed, opcache settings are updated and finally Drupal itself is downloaded.

# from https://www.drupal.org/requirements/php#drupalversions

FROM php:5.6-apache



RUN a2enmod rewrite



# install the PHP extensions we need

RUN apt-get update && apt-get install -y libpng12-dev libjpeg-dev libpq-dev \

&& rm -rf /var/lib/apt/lists/* \

&& docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \

&& docker-php-ext-install gd mbstring opcache pdo pdo_mysql pdo_pgsql zip



# set recommended PHP.ini settings

# see https://secure.php.net/manual/en/opcache.installation.php

RUN { \

echo 'opcache.memory_consumption=128'; \

echo 'opcache.interned_strings_buffer=8'; \

echo 'opcache.max_accelerated_files=4000'; \

echo 'opcache.revalidate_freq=60'; \

echo 'opcache.fast_shutdown=1'; \

echo 'opcache.enable_cli=1'; \

} > /usr/local/etc/php/conf.d/opcache-recommended.ini



WORKDIR /var/www/html



# https://www.drupal.org/node/3060/release

ENV DRUPAL_VERSION 8.0.1

ENV DRUPAL_MD5 423cc4d28da066d099986ac0844f6abb



RUN curl -fSL "http://ftp.drupal.org/files/projects/drupal-${DRUPAL_VERSION}.tar.gz" -o drupal.tar.gz \

&& echo "${DRUPAL_MD5} *drupal.tar.gz" | md5sum -c - \

&& tar -xz --strip-components=1 -f drupal.tar.gz \

&& rm drupal.tar.gz \

&& chown -R www-data:www-data sites

Let’s see our images:

$ docker images

The command “docker image” shows downloaded images

The images are quite heavy because they are assembled in Debian Jessie with its APT packaging system, fetching a lot of weighty dependencies.

Now, let’s run a container with MariaDB. By using key v (volume) we tell Docker to create a new mount from the host where our data will be stored. By default, the data will be stored inside of the container and this means it will be lost after rebuilding the container (you might need it to apply MariaDB updates).

In the output, we see the hash (identifier) of the running container.

$ docker run -e MYSQL_ROOT_PASSWORD=admin -e MYSQL_DATABASE=drupal8 -e MYSQL_USER=drupal8 -e MYSQL_PASSWORD=drupal8 -v mariadb:/var/lib/mysql -d --name mariadb mariadb

Now we run Drupal container with a link to just created MariaDB and the binding to the 80-th port. The link is just a record in /etc/hosts specifying IP of the container with MariaDB in a virtual network created by Docker during its installation.

$ docker run --name drupal8 --link mariadb:mysql -p 80:80 -d drupal:8.0.1

Let’s take a look at our containers:

$ docker ps

Command docker ps shows running containers

Open our IP in a browser and see Drupal installation. The installation is usual, except one little thing – you need to specify database host: mysql instead of localhost. That’s the name of the binding we’ve created before.

Change DB host to the name of the link (mysql) between the containers

That’s it. Enjoy fresh-installed Drupal 8.

Enjoy Drupal 8!

There are more amazing articles coming! Subscribe to our blog if you don’t want to miss it!

And check out the platform we’ve built. It helps you automate Drupal deployments with Docker to any server. It’s completely free.