Search by

lakedrops / docker4drupal

jurgenhaas

Composer Plugin to prepare local Drupal development environment for Docker.

Package info

gitlab.lakedrops.com/composer/plugin/docker4drupal

Issues

Documentation

Type:composer-plugin

pkg:composer/lakedrops/docker4drupal

Statistics

Installs: 51 628

Dependents: 3

Suggesters: 0

v3.10.100 2026-11-09 17:41 UTC

This package is auto-updated.

Last update: 2026-11-09 17:42:07 UTC


README

Composer plugin that renders Docker Compose services for Drupal projects.

Public and private service domains

DOCKER4DRUPAL_TRAEFIK_PRIVATE_DOMAIN affects CI builds only, including Build Prod Site NG (LAKEDROPS_BUILD_NG=yes). When set, auxiliary services use <service>-<project>.<private domain>. The Drupal web server retains its configured project domain. Local development and L3D sandboxes ignore the private domain variable.

Invoice Ninja always stays public in Build Prod Site NG, including staging stacks built by that job. Its router and APP_URL both use invoice-<public project domain>, preserving the URL from before v3.10.98. For example, invoice-main-example.example.com does not change when a runner adds a private domain. Other auxiliary services remain private. The public project domain comes from the existing project configuration; this change does not construct a different public hostname or add a second router.

Non-production pipeline previews still use the private domain for Invoice Ninja, including their container host mappings. They are test environments, not the customer-facing production application.

This is an explicit, non-configurable exception: servicedomain holds the shared auxiliary domain, while the computed invoicedomain holds Invoice Ninja's domain. A configurable per-service exposure switch would let a project accidentally violate the requirement that customer-facing Invoice Ninja stays public.

OpenTelemetry endpoint address

DOCKER4DRUPAL_OPENTELEMETRY_ADDRESS is the IPv4 address that the php container uses for the host of OPENTELEMETRY_ENDPOINT, the OTLP endpoint that lakedrops/drupal-environment configures for the drupal/opentelemetry module. It is meant for a log server that admits NetBird peers only while its name still resolves to a public address, for example DOCKER4DRUPAL_OPENTELEMETRY_ADDRESS=100.64.104.21 with OPENTELEMETRY_ENDPOINT=https://logs.lakedrops.com/api/default. php then gets the entry logs.lakedrops.com:100.64.104.21 in its extra_hosts, in the same list as the names of LOCAL_IP and the private domain.

The mapping applies to pipeline builds, Build Prod Site NG, and local development, where L3D exports the variables of ~/.env and the project's .env. L3D sandboxes ignore it. Without the variable, or without a host in OPENTELEMETRY_ENDPOINT, nothing changes. An address that is not IPv4 is ignored with a warning.

The log server's own host. There, a request from a container to one of the host's addresses arrives at Traefik from the gateway of traefik-public, which Traefik refuses for NetBird-only names. A pipeline build recognizes this host when the variable equals the runner's DOCKER4DRUPAL_TRAEFIK_NETBIRD_ADDRESS: php joins traefik-public and maps the endpoint's host to Traefik's address there, never to the gateway. As with the private domain, gw_priority: 1 on the project's default network of php and the web server keeps service names such as php resolving to the own project once a php of another project joins traefik-public. This needs Docker 28 and Compose 2.33 or later. The web servers of stacks rendered without it on the same host, by older releases of this plugin or without these variables, have no such priority.

Build Prod Site NG always uses the address as given. DeployNG writes the gateway of traefik-public, not Traefik's address, for TRAEFIK-IP-PLACEHOLDER, so live and staging stacks on the log server's own host cannot reach a NetBird-only endpoint there. Such stacks are not supported.

Tests

Install dependencies without activating Composer plugins in this plugin's own checkout, then run the integration test:

composer install --no-interaction --no-scripts --no-plugins
composer --no-plugins test
composer --no-plugins validate --no-check-publish
for file in src/*.php tests/*.php; do php -l "$file" || exit; done

On an L3D host, run these commands through l3d .. The test uses the real configuration class and Twig template, parses the generated YAML, and checks production with and without a private domain, production staging, pipeline previews, local development, and sandboxes. It checks the Invoice Ninja router and APP_URL together, other auxiliary routes, and pipeline host mappings. For DOCKER4DRUPAL_OPENTELEMETRY_ADDRESS, it checks the entry and the networks of php in each of these contexts, on the log server's own host and on another one, and that the file stays the same without the variable, without a host in the endpoint, or with an address that is not IPv4. The Service domain regression job runs these checks, Drupal/DrupalPractice coding standards, and PHPStan (using phpstan.neon) in MR, develop, and feature/* pipelines. Its lint tools are installed separately so they do not alter the plugin's dependencies. The tool installation sets COMPOSER_BIN_DIR explicitly to .qa/vendor/bin: shared Composer artifacts export a different bin directory, which must not redirect these isolated tools into vendor/bin.

The shared validate stage runs in branch pipelines for develop and feature/*, but not in merge request pipelines. Use a feature/<issue>-<description> branch and require both its full validate stage and Service domain regression job before merging. The branch regression job consumes the same shared artifacts and Composer variables as develop; the lightweight MR job alone does not validate those conditions.

Release flow

Feature and fix merge requests target develop. The shared CI configuration runs Publish Release on develop unless SKIP_PUBLISH_RELEASE=1; that job clones develop and invokes the shared merge command for the release merge. The resulting Merging develop into main merge request is separate from the feature/fix MR.

The main pipeline's Tag Release job recognizes a commit beginning Merge branch 'develop' into 'main' (also release into main, or a commit containing [tag release]). It runs gen-semver and creates the generated tag on main. [MAJOR_VERSION], [MINOR_VERSION], [PATCH_VERSION], and [REVISION_VERSION] select an explicit increment; skip-tag suppresses tagging. The tag pipeline's Build Package Tag job publishes the tag to GitLab's Composer registry. Do not merge the fix or the release MR, or trigger tagging, until the change has been reviewed.

After a reviewed release, rebuild the production Compose file and deploy it to restore the public Invoice Ninja route. Production jobs install the newest release; pipeline builds follow each project's lock file. Reverting the change would restore the private production route and break the public Invoice Ninja URL when the private domain is set.