Vom Container zur signierten Anwendung — warum wir TYPO3 als OCI-Artefakt von der Runtime trennen
Viele TYPO3-Projekte werden heute als vollständige Container-Images gebaut, bei denen jede Anwendung ihre eigene Laufzeitumgebung, PHP-Konfiguration und Abhängigkeiten erneut mitbringt. Wir gehen einen anderen Weg und trennen Runtime und Anwendung konsequent: Die Runtime liefern wir als gehärtetes Golden Image, die eigentliche TYPO3-Anwendung als signiertes OCI-Artefakt. Das Ergebnis sind kleinere Deployments, reproduzierbare Releases, schnellere Rollbacks und eine deutlich klarere Supply-Chain. Dieser Beitrag beschreibt den Ansatz, warum er gerade zu TYPO3 passt — und wo seine Grenzen liegen.
TL;DR
Das verbreitete Muster baut pro TYPO3-Projekt ein eigenes Container-Image, das die komplette Laufzeitumgebung mit verpackt. Bei mehreren Installationen ist der größte Teil dieser Images identisch (PHP, FrankenPHP, Extensions, OS-Pakete, TYPO3-Core); unterschiedlich ist nur die Anwendung selbst, also Sitepackage, Konfiguration, Extensions, Assets. Wir trennen beides: eine gehärtete, zentral gepflegte Runtime als Golden Image und die Anwendung als eigenständiges, vollständig vorgebautes und signiertes OCI-Artefakt. Beim Deployment treffen beide aufeinander, das Artefakt wird geprüft und bereitgestellt, FrankenPHP startet. Beschreibbar bleiben nur fileadmin/, var/ und der Upload-Storage; der Anwendungscode bleibt unveränderlich. Das ist kein Dogma gegen Container (sie bleiben eine gute Transporthülle), sondern eine Verschiebung der Deployment-Einheit von „individuelles Image“ auf „signierte Anwendung“.
Die Container-Frage
In vielen Projekten sieht ein TYPO3-Build heute ungefähr so aus:
FROM php:8.5
RUN composer install
COPY . .
# TYPO3 Setup
# -> individuelles Image pro Anwendung
Das funktioniert, und es ist über Jahre der Standardweg geworden. Der Preis dafür fällt erst auf, wenn man mehr als eine Installation betreibt: Jede Anwendung bringt ihre komplette Laufzeitumgebung erneut mit, obwohl diese Umgebung über die Projekte hinweg fast deckungsgleich ist.
Das eigentliche Problem
Betrachten wir zwei TYPO3-Installationen, Kunde A und Kunde B. Beide verwenden PHP 8.5, FrankenPHP, dieselben PHP-Extensions, dieselben Betriebssystem-Pakete und denselben TYPO3-Core. Trotzdem werden zwei vollständige Images gebaut, und der größte Teil dieser Images ist identisch. Unterschiedlich ist nur ein kleiner Teil: das Sitepackage, die Konfiguration, die Assets und die projektspezifischen Extensions.
Anders gesagt: Wir bauen, signieren, verteilen und patchen denselben Unterbau wieder und wieder, nur damit er einen kleinen, projektspezifischen Aufsatz trägt. Jede Sicherheitslücke in der Laufzeit zwingt zum Neubau jedes einzelnen Projekt-Images. Die Einheit, die wir bewegen, ist viel größer als die Einheit, die sich tatsächlich ändert.
Runtime und Anwendung sind unterschiedliche Dinge
Der Kern unseres Ansatzes ist, diese beiden Ebenen bewusst zu trennen.
Golden Image = Runtime
Das Golden Image enthält alles, was die Anwendung zum Laufen braucht, aber nichts Projektspezifisches: FrankenPHP, PHP samt nativen Extensions, Caddy, Zertifikate und die Security-Defaults. Es wird einmal zentral gebaut, gehärtet, gescannt und signiert — und von allen Projekten geteilt. Eine Lücke im Unterbau wird an genau einer Stelle gepatcht, nicht in jedem Projekt einzeln.
Application Artifact = TYPO3-Anwendung
Das Artefakt enthält die eigentliche Anwendung: TYPO3-Core, Composer-Dependencies inklusive vendor/, die Extensions, das Sitepackage und die Assets. Es ist das, was sich von Projekt zu Projekt und von Release zu Release unterscheidet — und genau diese kleine, sich ändernde Einheit ist das, was wir versionieren, signieren und bewegen.
Warum kein Composer im Produktivsystem?
Ein häufiger Ansatz baut die Anwendung erst beim Start zusammen, etwa per composer install in einem Init-Container. Wir halten das für problematisch. Eine produktive Anwendung sollte nicht im Moment des Deployments entstehen, sondern bereits vollständig gebaut, getestet und signiert vorliegen.
composer install zur Startzeit bedeutet einen Netzwerkzugriff auf Paket-Quellen im kritischen Pfad jedes Pod-Starts, ein nicht deterministisches Ergebnis (was heute auflöst, kann morgen anders auflösen) und eine Angriffsfläche genau dort, wo sie am wenigsten hingehört — in der Produktion. Die Lieferketten-Vorfälle der letzten Wochen im npm- und PHP-Ökosystem unterstreichen das: Wer Abhängigkeiten erst zur Laufzeit zieht, verlagert das Lieferketten-Risiko in den Produktivbetrieb. Build-Zeit ist der richtige Ort, um Abhängigkeiten aufzulösen, zu prüfen und festzuschreiben.
Die Anwendung als OCI-Artefakt und das Deployment
Deshalb behandeln wir die Anwendung als eigenständiges OCI-Artefakt in der Registry:
registry.example.com
└─ customer-a
└─ app:v1.4.2
├─ vendor/
├─ public/
├─ config/
└─ extensions/
Das Artefakt enthält bereits alle Composer-Abhängigkeiten und ist damit vollständig reproduzierbar. Es wird einmal gebaut, einmal signiert und anschließend unverändert ausgeliefert. OCI ist hier bewusst gewählt: Dasselbe Registry-, Signatur- und Distributions-Ökosystem, das wir für Images ohnehin betreiben (Tags, Digests, Signaturen mit cosign, Attestation), trägt auch die Anwendung — ohne dass sie ein lauffähiges Image sein muss.
Beim Deployment treffen zwei Bausteine aufeinander: das Golden Image (Runtime) und das Application Artifact (Anwendung). Der Startprozess ist bewusst schlicht:
1. Artefakt laden (app:v1.4.2 aus der Registry)
2. Signatur pruefen (Vertrauen vor Ausfuehrung)
3. Dateien bereitstellen (read-only in die Runtime mounten)
4. FrankenPHP starten
Beschreibbar bleiben nur die Bereiche, die TYPO3 zur Laufzeit wirklich braucht: fileadmin/, der Upload-Storage und var/. Der eigentliche Anwendungscode bleibt unveränderlich — er kommt aus einem signierten Artefakt und wird zur Laufzeit nicht mehr verändert.
Vorteile
Kleinere Deployments. Statt mehrere Gigabyte große Images zu verteilen, wird nur das eigentliche Anwendungsartefakt aktualisiert. Die geteilte Runtime liegt ohnehin schon auf den Knoten.
Schnellere Rollbacks. Ein Rollback ist ein Versionswechsel des Artefakts (von app:v1.4.2 zurück auf app:v1.4.1), ohne Neubau eines Containers. Die Runtime bleibt dieselbe.
Bessere Supply-Chain. Runtime und Anwendung werden unabhängig voneinander signiert und attestiert. Eine Lücke im Unterbau wird einmal zentral gepatcht; ein fehlerhaftes Release der Anwendung wird unabhängig davon zurückgerollt. Die Verantwortlichkeiten sind sauber getrennt und einzeln nachweisbar.
Höhere Reproduzierbarkeit. Die Anwendung wird einmal gebaut und danach unverändert ausgeliefert. Was im Staging lief, läuft in Produktion — Bit für Bit dasselbe Artefakt, nicht ein erneut zusammengebauter Annäherungswert.
Passt das zu TYPO3?
Ja, und überraschend gut. TYPO3 braucht zur Laufzeit nur wenige beschreibbare Bereiche, im Wesentlichen fileadmin/ und var/ (plus den Upload-Storage). Der gesamte Anwendungscode kann unveränderlich bleiben. Damit erfüllt TYPO3 genau die Voraussetzung, die ein immutable ausgeliefertes Artefakt verlangt: eine klare Trennlinie zwischen unveränderlichem Code und veränderlichem Zustand. Wer persistente Assets ohnehin über FAL in Object Storage legt (siehe unseren Schwester-Post zum RWX-Volume), hat diese Trennung bereits gezogen — der OCI-Artefakt-Ansatz ist die konsequente Fortsetzung auf der Code-Ebene.
Warum wir diesen Weg erforschen — und seine Grenzen
Wir glauben, dass Anwendungen langfristig nicht mehr als individuell gebaute Container betrachtet werden sollten. Container sind eine gute Transporthülle, aber die eigentliche Einheit eines Deployments ist die Anwendung selbst. Deshalb experimentieren wir mit einer Architektur, die TYPO3-Anwendungen als signierte OCI-Artefakte behandelt und von ihrer Laufzeitumgebung trennt. Das ist ausdrücklich nicht der einzig denkbare Weg, und wir verkaufen ihn nicht als fertige Wahrheit — aber er führt in eine Richtung, die wir für richtig halten: reproduzierbare, sichere und souveräne Plattformen, bei denen jeder Baustein einzeln nachweisbar, einzeln patchbar und einzeln zurückrollbar ist.
Der Ansatz hat Voraussetzungen, die wir offen benennen. Er verlangt Disziplin im Build: Die Anwendung muss vollständig und deterministisch vorgebaut werden, was eine saubere CI-Strecke und gepinnte Abhängigkeiten voraussetzt. Die Runtime-Versionierung wird zur eigenen Aufgabe, denn Golden Image und Artefakt müssen kompatibel bleiben, also braucht es eine klare Kontrakt-Definition (PHP-Version, Extension-Set) zwischen beiden. Und für sehr kleine Setups mit einer einzigen Installation ist der Mehrwert geringer; seine Stärke spielt der Ansatz bei mehreren Plattformen mit geteiltem Unterbau aus. Wer das berücksichtigt, bekommt eine Architektur, die mit der Zahl der betreuten Installationen besser statt schlechter skaliert.
Häufige Fragen
Ist ein OCI-Artefakt dasselbe wie ein Docker-Image?+
Nein. Ein OCI-Artefakt nutzt dasselbe Registry- und Signatur-Ökosystem wie Images (Tags, Digests, cosign), muss aber kein lauffähiges Image sein. Wir transportieren damit die fertige Anwendung — vendor/, public/, config/, Extensions — getrennt von der Runtime.
Warum nicht einfach composer install im Init-Container?+
Weil das einen Netzwerkzugriff und ein nicht deterministisches Ergebnis in den kritischen Pfad jedes Pod-Starts legt — und das Lieferketten-Risiko in die Produktion verlagert. Abhängigkeiten gehören zur Build-Zeit aufgelöst, geprüft und festgeschrieben, nicht zur Startzeit.
Welche Verzeichnisse muss TYPO3 zur Laufzeit beschreiben können?+
Im Wesentlichen fileadmin/, der Upload-Storage und var/. Der Anwendungscode bleibt unveränderlich und kommt aus dem signierten Artefakt. Persistente Assets gehören über FAL in Object Storage, nicht auf ein RWX-Volume.
Wie funktioniert ein Rollback bei diesem Ansatz?+
Als Versionswechsel des Artefakts, etwa von app:v1.4.2 zurück auf app:v1.4.1, ohne Neubau eines Containers. Die geteilte Runtime bleibt unverändert.
Lohnt sich der Aufwand auch für eine einzelne TYPO3-Installation?+
Der Reproduzierbarkeits- und Signatur-Vorteil gilt immer; der Effizienzgewinn durch die geteilte Runtime entfaltet sich aber vor allem bei mehreren Plattformen mit gleichem Unterbau. Für ein einzelnes Setup ist der Mehrwert geringer.
Fazit
Der Reflex, jedes TYPO3-Projekt als eigenes Container-Image zu bauen, stammt aus einer Zeit, in der Image gleich Anwendung war. Trennt man Runtime und Anwendung (gehärtetes Golden Image hier, signiertes OCI-Artefakt dort), werden Deployments kleiner, Rollbacks schneller, die Supply-Chain klarer und Releases reproduzierbar. TYPO3 eignet sich dafür besonders, weil sein veränderlicher Zustand klein und klar abgegrenzt ist. Die Frage ist nicht „Wie baue ich ein gutes Image?“, sondern „Was ist eigentlich die Einheit, die ich ausliefere — und kann ich sie signieren, prüfen und zurückrollen, ohne den Unterbau anzufassen?“.
Wir bauen TYPO3-Plattformen, bei denen Runtime und Anwendung getrennt, signiert und einzeln zurückrollbar sind.
Architektur-Review und Aufbau Ihrer TYPO3-Deployment-Strecke: gehärtetes Golden Image als geteilte Runtime, die Anwendung als signiertes OCI-Artefakt, reproduzierbare Releases, schnelle Rollbacks und eine nachweisbare Supply-Chain.
Plattformbetrieb statt Beratung-on-paper — von der CI-Strecke über die Signatur bis zum Deployment.

