PHP

Dockerize your toolchain!

Die eigene Toolchain im Docker-Container testen
Keine Kommentare

Mittlerweile nutzt fast jeder Entwickler Tools zur statischen Codeanalyse, zur Ausführung von Tests und zur fortwährenden Prüfung des Codestyles im Projekt. Aber wie kann uns Docker dabei helfen? Und welchen Vorteil habe ich dadurch gegebenenfalls in Legacy-Projekten?

Jeder Entwickler kennt sie: Tools wie PHPUnit, PHPStan oder PHP_CodeSniffer, um nur einige zu nennen, können im Programmieralltag helfen, qualitativen, einheitlich formatierten und testbaren Programmcode zu schreiben. Sie sind oft elementare Bestandteile des lokalen Entwicklungsprozesses, die routinemäßig in jedem Projekt eingesetzt werden.
Oft sind sie auch bereits fest in der Continuous-Integration-(CI-)Pipeline verankert. Direkt als Abhängigkeit des Projekts via Composer oder autark als PHAR-Datei via Phive installiert, kann das Projekt jederzeit analysiert und getestet werden.

Warum dockerized Tools?

Dieses Set-up bedingt jedoch, dass das Hostsystem entsprechend präpariert ist. Von der entsprechend benötigten PHP-Version über diverse PHP Extensions bis zum Vorhandensein bestimmter Libraries. Bearbeite ich verschiedene Projekte, die unterschiedlichste technische Entwicklungsstände aufweisen oder gar ältere PHP-Versionen voraussetzen, führt das dazu, dass das System entsprechend belastet wird.

Warum also nicht auch die eigene Toolchain in Docker-Container packen und in der bestmöglichen Laufzeitumgebung und mit allen benötigten Abhängigkeiten laufen lassen? Denn mittlerweile laufen am Ende auch viele PHP-Projekte produktiv bereits in einem Docker-Container, oft orchestriert von Kubernetes oder Docker-Swarm.

Wie funktioniert das?

Die Funktionsweise ist dabei recht simpel. Als Basis dient oft eine leichtgewichtige Linux-Distribution wie Alpine. In diese werden die erforderliche PHP-Version, die notwendigen PHP-Erweiterungen und das Tool selbst als PHAR-Datei oder global via Composer vorinstalliert. Auch benötigte PHP-ini-Einstellungen werden gesetzt und ein entsprechender Mountpoint wird festgelegt, auf den die Daten unserer Projekte später eingehängt werden können.

International PHP Conference

Entwickler – das verlorene Handbuch

by Stefan Priebsch (thePHP.cc)

My browser does what?

by Joel Lord (Red Hat OpenShift)

JavaScript Days 2019

Einführung in Node.js

mit Golo Roden (the native web)

Concepts of the modern Web

mit Sven Kölpin (OPEN KNOWLEDGE)

Und mittlerweile findet man im Docker Hub auch mindestens ein fertiges Image zu den gängigsten Tools des PHP-Ökosystems, das man direkt nutzen kann.

PHP-5-Legacy-Code analysieren

Während dieser Artikel entstand, war die PHP-Version 7.3 bereits verfügbar. Und dennoch läuft ein nicht geringer Teil der Webseiten und Applikationen weltweit auch heutzutage noch mit PHP 5. Wer selbst auch noch ältere Codebases betreut und dennoch statische Codeanalysetools wie z. B. PHPStan oder churn-php einsetzen möchte, die jedoch mindestens PHP 7 erfordern, kann das mit diesem Ansatz ebenfalls tun. Denn der zu analysierende Code wird dabei nicht im Container ausgeführt, sondern nur gemountet und analysiert, und das Ergebnis dieses Vorganges wird ausgegeben.

Schnelle Ausführung dank Shell-Aliase

Führt man mehrere Tools immer wieder via Docker aus, empfiehlt es sich, diese einfach als Aliase in der Shell zu hinterlegen. Für PHPStan muss dazu beispielsweise nur folgende Zeile in ~/.zshrc, ~/.bashrc oder ~/.profile. eingetragen werden:

alias phpstan='docker run -v $PWD:/app --rm phpstan/phpstan:latest'

Dieses Vorgehen empfiehlt sich auch, wenn man verschiedene Versionen eines Tools nutzt. Dazu wird einfach pro Docker-Tag ein Alias angelegt.

Eigene Skripte im Container ausführen

Hin und wieder finden sich auch spezielle Tools oder Skripte in Projekten, die beispielsweise Berechnungen, Dateikonvertierungen oder Validierungen vornehmen und inhaltlich eng ans Projekt gebunden sind. Auch für solche Skripte kann es sehr sinnvoll sein, in der jeweils bestmöglichen Laufzeitumgebung zu laufen. Um das zu verdeutlichen, nehmen wir als Beispiel an, dass in unserem Projekt regelmäßig Bilder verkleinert und mit einem Wasserzeichen gekennzeichnet werden sollen. Listing 1 zeigt dabei unser vereinfachtes Skript, das intern auf die Library intervention/image zurückgreift.

<?php
require __DIR__ . '/vendor/autoload.php';

use Intervention\Image\ImageManager;

(new ImageManager(['driver' => 'imagick']))
  ->make(__DIR__ . '/public/input.jpg')
  ->resize(640, 480)
  ->insert(__DIR__ .  '/public/watermark.png')
  ->save(__DIR__ . '/public/output.jpg');

echo 'Done.';

Das Problem hier: die Library nutzt die PHP-Erweiterungen gd, imagick und exif, um bestmögliche Ergebnisse zu liefern. Diese wiederum sind auf unserem Hostsystem standardmäßig nicht installiert und werden sonst auch im Projekt nicht weiter benötigt. An dieser Stelle können wir damit starten, diesen Teil der Applikation auszulagern, um eventuell den Performance-Boost von PHP 7 in einem alten Projekt zu nutzen oder einfach unser System nicht mit sonst nicht genutzten PHP Extensions und Libraries zu belasten. Dazu erstellen wir unser Dockerfile (Listing 2).

FROM alpine:3.8

RUN apk --update --progress --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/v3.8/community add \
  # Add PHP7 and only needed extensions
  php7 \
  php7-json \
  php7-phar \
  php7-openssl \
  php7-fileinfo \
  php7-gd \
  php7-imagick \
  php7-exif \
  # Cleanup
  && rm -rf /var/cache/apk/* /var/tmp/* /tmp/*

# Install library
COPY --from=composer:1.8.0 /usr/bin/composer /usr/local/bin/composer
RUN composer global require intervention/image

VOLUME ["/app"]
WORKDIR /app

ENTRYPOINT ["php"]
CMD ["-m"]

In diesem Dockerfile, basierend auf Alpine Linux, installieren wir PHP, die erforderlichen PHP-Erweiterungen sowie Composer und unsere eigentliche Library. Danach können wir unser Bildbearbeitungsskript mit folgendem Befehl ausführen:

docker run --rm -v $PWD:/app php-test /app/resizer.php

Das Ganze kann mit wenig Aufwand auch sehr schnell dynamisiert werden – beispielsweise, indem man die Variablen als Parameter mitgibt.

Fazit und Zusammenfassung

Docker hilft uns, neue Tools schnell zu testen, ohne sie direkt als Abhängigkeit des Projekts zu registrieren und unser Hostsystem unnötig zu belasten. Und mit einer dockerized Toolchain können auch alte Codebases mit neuesten Tools analysiert werden. Auch die Möglichkeit, projektinterne Skripte mit Docker in die perfekte Laufzeitumgebung zu bringen und damit die Performance zu erhöhen, sollte geprüft werden.

PHP Magazin

Entwickler MagazinDieser Artikel ist im PHP Magazin erschienen. Das PHP Magazin deckt ein breites Spektrum an Themen ab, die für die erfolgreiche Webentwicklung unerlässlich sind.

Natürlich können Sie das PHP Magazin über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Entwickler Magazin ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -