Drupal 8 CI/CD with Docker via Jenkins. Part 1: Integration

Chingis
Wodby blog
Published in
4 min readOct 13, 2016

--

THIS ARTICLE IS OUTDATED: please see new article “New deployment method — CI/CD via third-party CI”

In this article I will demonstrate how to organize CI workflow for your Drupal 8 website with Docker. We will use Jenkins as our CI/CD tool and docker4drupal containers for test environment.

This article will consist of two parts. In the first part we will install Jenkins and set up our build. During the build we will spin up testing environment with docker4drupal containers and run a few test suites (both unit and functional) from Drupal core.

In the second part, we will prepare the deployment tarball (archive with the code) and upload it to AWS S3. Then we deploy a new docker-based environment for Drupal and deliver there our tarball.

Installation and configuration

First let’s install Jenkins. I will install it on a AWS EC2 node with Debian 8.

  1. Install Jenkins
wget -q -O — https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c ‘echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list’
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install sudo curl git jenkins

2. Generate SSH key for Jenkins user

sudo -H -u jenkins ssh-keygen -t rsa -b 4096
sudo -H -u jenkins cat ~/.ssh/id_rsa.pub

3. Allow sudo for jenkins

echo ‘jenkins ALL= NOPASSWD: ALL’ > /etc/sudoers.d/jenkins

4. Install Docker engine

apt-key adv — keyserver hkp://p80.pool.sks-keyservers.net:80 — recv-keys 58118E89F3A912897C070ADBF76221572C52609D
echo “deb https://apt.dockerproject.org/repo debian-jessie main” > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install docker-engine

5. Allow jenkins deal with Docker.

adduser jenkins docker

6. Install Docker Compose.

curl -sS https://bootstrap.pypa.io/get-pip.py | python
pip install docker-compose

7. Install AWS Cli (we will use AWS S3 for delivery)

pip install awscli

8. Restart Jenkins service

service jenkins restart

9. Get your jenkins admin password here

cat /var/lib/jenkins/secrets/initialAdminPassword

10. Open your Jenkins installation (localhost:8080). Install suggested plugins:

11. Install additional plugins “Environment Injector Plugin” and “AnsiColor”

Continuous Integration

  1. We need to grant Jenkins access to our git repository. We generated an SSH key before, so we just select the appropriate option

2. Now add this SSH key to your Git repository. You can find it here.

cat /var/lib/jenkins/.ssh/id_rsa.pub

3. Create a new Freestyle Project (job) in Jenkins and add your git repository

4. Add the following docker-compose.yml file to your repository, it’s a simplified version of docker4drupal:

version: "2"

services:
mariadb:
image: wodby/drupal-mariadb
environment:
MYSQL_RANDOM_ROOT_PASSWORD: 1
MYSQL_DATABASE: drupal
MYSQL_USER: drupal
MYSQL_PASSWORD: drupal

nginx:
image: wodby/drupal-nginx
environment:
NGINX_UPSTREAM_NAME: php
DRUPAL_VERSION: 8
volumes_from:
- php

php:
image: wodby/drupal-php:7.0
depends_on:
- mariadb
environment:
SIMPLETEST_BASE_URL: http://nginx
SIMPLETEST_DB: mysql://drupal:drupal@mariadb/drupal
volumes:
- ./:/var/www/html

docker-compose.yml file defines a set of services/containers for our test environment. Besides PHP we need MariaDB and Nginx containers because we will run functional tests and they require a database and a web server. For the same reason we add two variables for Simpletest in PHP container.

As you can see we don’t expose any public ports and have no volume for the database. We don’t need it because our environment will be used only for tests during the build.

Build Setup

Add the following files to our repository which will be used for our build.

build.sh:

#!/bin/bash

set -eo pipefail

# Install merge plugin.
docker run --rm \
-v "$HOME/.composer":/composer \
-v "$PWD":/app \
composer/composer:alpine update -n

# Install all requirements.
docker run --rm \
-v "$HOME/.composer":/composer \
-v "$PWD":/app \
composer/composer:alpine update -n

This script will run a docker containers with composer to fetch Drupal’s dependencies.

tests.sh

#!/bin/bash

sudo chown -R 82:82 .

docker-compose up -d mariadb
docker-compose up -d nginx

docker-compose run --user 82 php vendor/bin/phpunit -c core core/tests/Drupal/Tests/Core/Password/PasswordHashingTest.php
docker-compose run --user 82 php vendor/bin/phpunit -c core core/tests/Drupal/KernelTests/Component/Utility/SafeMarkupKernelTest.php
docker-compose run --user 82 php vendor/bin/phpunit -c core core/tests/Drupal/FunctionalTests/Breadcrumb/Breadcrumb404Test.php

sudo chown -R jenkins:jenkins .

docker-compose down --remove-orphans

First, we change ownership to user 82, it’s a www-data user id inside of the php/nginx containers. Then we spin up mariadb and nginx services defined in our docker-compose.yml file. And finally we launch 4 test suites (unit and functional) from Drupal’s core.

Now we just need to add build steps that will execute these scripts.

Running the Build

We now have everything we need. Let’s run the build. We’ll see the following output:

As you can all tests are passed. This means we can now go the second part where we deliver our build.

Part 2: Continuous Delivery

--

--