LAMP env for Drupal 9 with Docker

28/01/2021
LAMP env para Drupal 9 con Docker - Docker logo

Why using Docker?

Docker allows us to create containers with very easy to maintain and manipulate microservices.

But not only this, docker also allows that a developer team be able to work in the same environment with the same versions of the services they are executing, no matter the operating system host they are using. In this way, errors are reduced when more people are working in the same project and in different areas of the same.

The environment

In order to make a Drupal environment in a virtualization system like docker, it will be needed to have a web service and a database. Both services can be located in a single container or in more than one container. Nowadays, everything is moving in the direction of microservices, that is why in this project two separated containers will be achieved, one for the web environment and other for the database.

The project tree looks like this:

Lamp env para Drupal 9 con Docker - Árbol de directorios
Project tree

Let's build the system

docker-compose.yml

In this YAML file, the following parameters are defined. This file is found in the project root. So below, two services are configured with docker-compose.

version: "3.7" // Docker-compose version.
services: // The services to create. 
        web: // Microservice 1. 
                build: apache // Container to build (dockerfile Apache).
                links: // Link to the database. 
                        - db // Name of the service to link.
                ports: // Mapping ports[Host]:[Container].
                        - "80:80" // HTTP port. 
                        - "HTTPS port (Need ssl). 
                volumes: // Volume to create. 
                        - ./www:/var/www/html // [Directory]:[Directory in container] 
        db: // Microservice 2. 
                build: mysql // Container to build (dockerfile Mysql). 
                ports: // Mapping port [Host]:[Container]. 
                        - "3306:3306" // Default database port.

apache/Dockerfile

FROM php:7.3-apache-stretch          // PHP and Apache version 

RUN useradd -u 1000 -m user      // Adding user uid 1000 
RUN apt-get update                      // Updating packages 
RUN apt-get install -y \                  // Install needed packages

#Container utilities
git \ 
wget \ 
vim \ 
#Connection 
mysql-client \ 
#Libraries 
libpng-dev \ 
libmcrypt-dev \ 
libicu-dev \ 
pecl install mcrypt-1.0.2 && \ 
apt-get install -y libmagickwand-dev --no-install-recommends && \ 

#PHP Extensions, needed for the CMS
docker-php-ext-install mbstring && \ 
docker-php-ext-install pdo_mysql && \ 
docker-php-ext-install mysqli && \ 
docker-php-ext-enable mcrypt && \ 
docker-php-ext-install opcache && \ 
docker-php-ext-install pcntl && \
docker-php-ext-install intl && \ 
docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && \ docker-php-ext-install gd && \ 
pecl install imagick && \ 
docker-php-ext-enable imagick && \ 
rm -r /var/lib/apt/lists/* && \ 

#Composer to manage dependencies 
curl -sS https://getcomposer.org/installer | php && \ 
mv composer.phar /usr/bin/composer && \ 

#Enable PHP modules
a2enmod rewrite && \ 
a2enmod ssl && \ 
a2ensite default-ssl && \ 
curl -sL https://deb.nodesource.com/setup_12.x | bash - 

#Enable SSL for HTTPS connection
RUN apt-get install nodejs -y && \ 
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/ssl-cert-user.key -out /etc/ssl/certs/ssl-cert-user.pem -subj '/' 

#Add custom templates to different config paths in the container
ADD templates/apache2.conf /etc/apache2/ 
ADD templates/php.ini /usr/local/etc/php/ 
ADD templates/xdebug.ini /usr/local/etc/php/conf.d/

apache/templates/apache2.conf

In the following link, apache configurations for the debian system can be found: https://sources.debian.org/src/apache2/2.4.10-10/debian/config-dir/apac…

apache/templates/php.ini

[php] 
register_globals = off 
display_errors = On 
error_reporting = E_ALL | E_STRICT 
log_errors = On 
error_log = /var/log/php_errors.log 
date.timezone="Europe/London" 
upload_max_filesize=64M 
post_max_size=64M 
memory_limit=1024M

mysql/Dockerfile

FROM mysql:5.7 
ENV MYSQL_ROOT_PASSWORD Qwerty_1234
ADD templates/custom_config.cnf /etc/mysql/conf.d/

mysql/templates/custom_config.cnf

[mysqld]

// mysql daemon
max_allowed_packet=128M 
default-storage-engine=InnoDB 
collation-server = utf8mb4_unicode_ci 
init-connect='SET NAMES utf8mb4' 
character-set-server = utf8mb4 
skip-character-set-client-handshake 

[client] 
default-character-set = utf8mb4 

[mysql] 
default-character-set = utf8mb4

scripts/drupal9.sh

#!/bin/bash 
# Directories
parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) 
cd "$parent_path" 

# Apache 
docker-compose exec web sh -c "sed -i -e 's/www\/html/www\/html\/web/g' /etc/apache2/sites-enabled/000-default.conf" 
docker-compose exec web sh -c "sed -i -e 's/www\/html/www\/html\/web/g' /etc/apache2/sites-enabled/default-ssl.conf" 
rm -rf ../www; 

# Drupal 9 with Composer 
cd .. && COMPOSER_MEMORY_LIMIT=-1 composer create-project 
drupal-composer/drupal-project:9.x-dev www 
./stop.sh 
./start.sh 

#Drush and database
docker-compose exec --user=1000:1000 web sh -c 'vendor/bin/drush si standard --db-url=mysql://root:Qwerty_1234@db/drupal9 -y' 
docker-compose exec web sh -c "ln -s /var/www/html/vendor/bin/drush /usr/local/bin/drush"

Let's get started!

To mount the containers, we will execute the script docker-compose up created in the document root. We created these scripts because they are going to be used a lot.

$ docker-compose up -d

The output of this command will be quite long, but it should end up as follows:

Lamp env para Drupal 9 con Docker - docker-compose up output
Building containers

Now we can see which containers are active (two in our case, one for the web server and one for the database):

$ docker ps
Lamp env para Drupal 9 con Docker - docker ps output
Docker ps

Once we have the two containers active, it's time to run the Drupal 9 installation script with composer and drush.

$ ./scripts/drupal9.sh

Containers

- web
        - usuario: docker-compose exec --user=1000:1000 web bash
        - root: docker exec -it [container_web] bash

- mysql 
        - root: docker exec -it [container_db] bash