---
title: Docker L3D and Drupal Projects
tags:
- docker
---
# L3D and Drupal Projects

## Introduction and overview

We do provide a couple of project templates for Drupal projects out of the box:

- [Drupal 8](/composer/project/d8)
- [Drupal 9](/composer/project/d9)

If you prefer to use your own prroject template, you'll get the most out of
L3D if you add our ccomposer plugin [drupal-development-environment](/composer/plugin/drupal-dev-environment)
to your required dev components:

```bash
composer require --dev lakedrops/drupal-development-environment
```

This comes with all the dependencies, that help you in local Drupal development:

- [Ahoy](/composer/plugin/ahoy)
- [Behat](/composer/plugin/b4d)
- [Docker4Drupal](/composer/plugin/d4d)
- [Dorgflow](/composer/plugin/dorgflow)
- [Drupal Environment](/composer/plugin/drupal-environment)
- [Traefik](/composer/library/traefik)
- [Utilities](/composer/library/composer-json-utils)

You'll find the documentation for each of these tools in their own section.

In the current context, just an extra note on the drupal-environment plugin: this
has been moved out of drupal-development-environment and contains all the tasks
and templates to initially build the directory structure and setting files.

It is a great idea to utilize the same structure in your production environment
too. To get there, you can simply add this plugin to your regular requirements:

```bash
composer require lakedrops/drupal-environment
```

In both cases, development and production, your project settings for this
toolset goes into the file `.lakedrops.yml` in your project root and each
project describes in its own documentation, what values go into this file so
that you get similar (but not identical) setup on all stages. It should not
be identical, because you don't want all the development tools on your 
production site.

## Working with multiple projects in parallel

The composer plugin [Docker4Drupal](/composer/plugin/d4d) in combination with 
the composer library [Traefik](/composer/library/traefik) automatically
configures your host for zero-setup always working routing for any number of
projects in parallel.

Everything is based on a project ID which has to be unique on a single host.
Ideally the ID should be short and only contain characters and numbers. The
ID will be part of the domain-name under which this project will be opened in
the browser locally and maybe even within your LAN.

The ID will be stored in a variable called `COMPOSE_PROJECT_NAME` which is
stored in the `.env` file in the root of your project. For this documentation
we continue by using the sample ID `project1`.

Based on this ID, ...

- L3D builds the main container called `project1_l3d`
- Traefik creates a Docker network called `traefik_project1`
- Docker4Drupal creates a number of containers depending on the services you
  require, e.g.
  - `project1_apache_1`
  - `project1_mailhog_1`
  - `project1_mariadb_1`
  - `project1_php_1`
  - `project1_pma_1`
  - `project1_redis_1`
- Node and NPM will create a container `project1_l3d_node`

All those containers can communicate with each other as they all belong to the
same logical network provided by Traefik. If you have a second and more projects
with the same logic but a different ID, they will simply do the same for 
themselves and each project will be self-contained but isolated from all the
other projects on the host.

### Routing

The logical network for each project is also used for routing traffic, i.e.
HTTP requests, from you host - or even from you LAN - to the right container
for further processing. All of that routing is managed by Traefik which
defaults to port 8000 for http and port 8443 for https traffic. You can
change those ports to anything else by setting the following environment
variables in the `.env` file in your users home directory:

```bash
DOCKER4DRUPAL_TRAEFIK_PORT=80
DOCKER4DRUPAL_TRAEFIK_PORTS=443
```

If you change those values later on, don't forget to run `ahoy traefik rewrite`
to update existing services.

Routing also requires domain names. They help Traefik to decide which request
needed to be routed into which container. Depending on the services you use,
the following domain names will be used for the respective services:

- `project1.docker.localhost:8000`: The Drupal website.
- `pma-project1.docker.localhost:8000`: PhpMyAdmin of the project.
- `mailhog-project1.docker.localhost:8000`: The Mailhog service for the project.
- `bs-project1.docker.localhost:8000`: Browsersync instance when running Gulp.

In other words, the project ID plus some service identifier are used as the
subdomain to your Traefik domain, which defaults to `docker.localhost`. You
can overwrite that domain with the environment variable
`DOCKER4DRUPAL_TRAEFIK_DOMAIN`, e.g. to `username.company.dev` with `username`
being replaced by the name of the developer or their hostname.

In any event, make sure that your local DNS resolves all those domains
properly to the correct host in your LAN. There are different tools around
that let you do that, dnsmasq or Pi-hole are two possible tools that make it 
easy and are well documented.

This approach even allows your team to get access to active projects on their
teammates hosts, if everything is setup accordingly, e.g.

| Developer | Hostname | IP | Domains |
| --- | --- | --- | --- |
| Lisa | laptop12 | 192.168.1.45 | *.laptop12.company.dev |
| Max | desktopmax | 192.168.1.83 | *.desktopmax.company.dev |
| Sara | laptop33 | 192.168.1.84 | *.laptop33.company.dev |
| Manuel | laptop01 | 192.168.1.87 | *.laptop01.company.dev |

If e.g. Lisa and Manuel are both working on project1, there will be two domains
available in your LAN for that project:

- `project1.laptop12.company.dev`: the current version on Lisa's laptop
- `project1.laptop01.company.dev`: the current version on Manuel's laptop

Everyone in the LAN can access the current projects on all hosts of developers,
if configured this way. Even for remote teams, this very same setup can be 
achieved over a VPN.

### Working with SSL

#### Specify and configure your dev-domain

For this documentation we work with the domain `username.company.dev` and this will be used as wildcard, so that for each project you're working on a sub-domain suffix will be added, e.g. `shop.username.company.dev` or `customer14.username.company.dev`.

#### Issue a wildcard SSL certificate

For this you have to install a LetsEncrypt client. We recommend [Certbot](https://certbot.eff.org). Then you can issue a wildcard certificate with the following command:

```
certbot -d "*.username.company.dev" --server https://acme-v02.api.letsencrypt.org/directory --manual --preferred-challenges dns certonly
cp /etc/letsencrypt/live/username.company.dev/*.pem ~/.traefik/certs
sudo chmod +r ~/.traefik/certs/*.pem
```

You will be presented with a request to configure a TXT record on your DNS provider. Once you're done that, certbot will issue the SSL certificate for you and you're good to go. Note: you have to renew the certificate every 3 months by using the same commands again.

#### Configure Traefik to use your SSL certificate

Add the following line to your `.env` file in your user's home directory:

```bash
DOCKER4DRUPAL_TRAEFIK_DOMAIN=username.company.dev
DOCKER4DRUPAL_TRAEFIK_USESSL=1
DOCKER4DRUPAL_TRAEFIK_PORT=80
DOCKER4DRUPAL_TRAEFIK_PORTS=443
DOCKER4DRUPAL_TRAEFIK_CERT=fullchain.pem
DOCKER4DRUPAL_TRAEFIK_KEY=privkey.pem
```

To update your Traefik configuration and restart the service, go to one of your
projects in L3D and call `ahoy traefik rewrite` to get everything setup once and
forever.

## Using XDebug

Debugging PHP can be a game changer in Drupal development. In the context of L3D
in combination with the composer plugin [Docker4Drupal](/composer/plugin/d4d)
this is provided out of the box and configured very easily. We describe the
steps for PhpStorm, but other IDEs should be very similar.

As XDebug comes with a performance hit, it is turned off by default. When you
need it, simply call `ahoy debug on` in you L3D container of the project you
want to debug and the scripts will reconfigure the PHP container and refresh
it with a few seconds. When you've finished debugging, you may want to turn it
off again with `ahoy debug off`.

XDebug version 3 connects to port 9003 of your IDE and PhpStorm is preconfigured
by default to list on that port.

You can then just enable debugging in PhpStorm and wait for the first request
which will prompt you to configure the details. Or you configure actively the
debug configuration:

![Screenshot](/files/screenshots/Screenshot from 2021-01-25 18-59-52.png)

The name and the server name should both be called `Docker`. And the mapping
needs to be configured from your project root directory on your host to the
path `/var/www/html` in the container.

With this setup, you can debug both web requests coming from the browser and
CLI commands for PHP which is executed inside the PHP container like e.g.
drush - all with the same setup.