Neue Welt - Strapi - Part 1

calendar_month 1. September 2020 19 Wörter

Die „Neue Welt”-Serie findet hier ihren technischen Anfang. In diesem Artikel werde ich Strapi als Docker Container/Stack betreiben.

Was war nochmal Strapi?

Strapi ist ein Headless-CMS, d.h. Strapi stellt alle Anforderungen, die an ein Backend anfallen, bereit. Datenhaltung, WebService und Administration sind ein Paar dieser Anforderungen.

Um die Darstellung der Inhalte etc. muss von dem Betreiber/Entwickler separat bereitgestellt werden. Ich werde als Beispiel auf GatsbyJS setzen.

Was kann Strapi?

Ghost als Beispiel ist ein System, was ich mittlerweile sehr gern habe. Ghost kann außerdem auch als Headless-CMS betrieben werden. Wenn Ghost die Erstellung von eigenen „Inhaltstypen” anbieten würde, würde ich diesen Post nicht schreiben.

ContentTypes / Fields

Mit Strapi kann ich eigene Inhaltstypen anlegen. Zusätzlich werden verschiedene Feldtypen angeboten, mit denen der Inhaltstyp modelliert werden kann.

Das Beziehungs-/Relations-Feld ist hier noch eine eigene Erwähnung wert. Für jemanden, der seit über 10 Jahren ContentTypes modelliert hat – ich kann SharePoint und das sogar ziemlich gut – war das Lookup-Feld immer so ein halbfertiges Ding. Mit MOSS 2007 war das cool, mit den Jahren nicht mehr so. Das Lookup-Feld kann heute noch 1→1 oder 1→n Relationen… Strapi kann mehr: Hier sind weiterhin 1→1, 1→n, aber auch n→n möglich… und dann noch das ganze inverse :)

GraphQL

Strapi kann GraphQL und das ziemlich gut! Strapi kann meiner Meinung nach auch für schnelle Showcases oder kleine bis mittelgroße PoC verwendet werden.

Ich modelliere mein (relationelles) Datenmodell an der Oberfläche, die benötigten Berechtigungen für die API vergebe ich über eine Oberfläche und kann anschließend dagegen abfragen/entwickeln. Das ist einfach, einfach :)

Der technologische Stack

Strapi ist in Node.js geschrieben. Für mich ist dieser Teil eigentlich sehr uninteressant, da ich Sprachen und/oder Frameworks als Werkzeuge ansehe, die ich verwenden können sollte.

Was aber wiederum interessant ist, ist die Tatsache, dass ich hier an verschiedenen Stellen programmatisch reagieren und z.B. den Service, Controller oder das Model für einen ContentType anpassen kann. Letzteres – Models – bieten sogar die Möglichkeit, auf verschiedene Ereignisse bei der Verwaltung von Entitäten zu reagieren. In etwas so wie bei SharePoint ListEventReceivern – ich liebe es :)

Das sind mal so ein Paar Punkte, die Strapi für mich interessant gemacht haben.

Was kann Strapi nicht?

Strapi kann vieles nicht OOTB, das meiste kann programmatisch implementiert/integriert werden. Die Frage sollte vielmehr heißen: Was macht Strapi schlecht oder was gefällt mir nicht so?

Verwaltungsoberfläche bääh

Was mir nicht so gut gefällt, ist z.B. die Adminoberfläche – die ist zwar besser als die von manch anderen Headless-CMS-Systemen, aber immer noch potthässlich. Einem Redakteur oder einem Kunden würde ich für reine Content-Pflege diese Ansicht nicht antun wollen. Versucht mal ein Datum in einem Datumsfeld zu setzen, welches vor 2012 liegt…

Ich habe mich zwar nicht entschieden, würde aber gerne eine Editor-Oberfläche – am liebsten ähnlich wie die von Ghost – für die redaktionelle Tätigkeiten bauen. Mal gucken, evtl. mache ich das.

Keine ContentType-Hierarchie

Weiter oben habe ich aufgezählt, was Strapi meiner Meinung nach besser macht als SharePoint. Es gibt auch Funktionen, die ich z.B. von SharePoint gewohnt bin und tatsächlich in Strapi vermisse. Hierarchische ContentType-Struktur!

Würde Strapi sowas anbieten, wäre das für mich die ideale Plattform, um kleine Ontologien aufzubauen und mit bisschen Logik eine semantische Web-Umgebung aufzubauen. Das wird schwierig, wenn man keine ContentType-Vererbung hat.

Mehr habe ich aktuell nicht – mit dem produktiven Einsatz werden sicherlich weitere Punkte folgen. Damit dieser Artikel nicht zu lang wird, cutte ich hier und komme zum eigentlichen Thema: die Inbetriebnahme einer Strapi-Umgebung mit einer externen MongoDB-Instanz.

Die Inbetriebnahme einer Strapi-Umgebung mit einer externen MongoDB-Instanz

Dieses Vorhaben ist eigentlich sehr simpel, da die Macher von Strapi zum einen ein Docker-Image und zum anderen eine halbwegs gute Dokumentation bereitstellen.

Zu der Dokumentation geht es hier lang… Ich habe das MongoDB-Beispiel genommen, ein bisschen modifiziert und erfolgreich über meinen nginx-proxy Netzwerk bereitgestellt.

Da ich aktuell viele Instanzen bereitstelle – ich teste –, steuere ich den Docker-Compose-Stack über eine environment-Datei an. Die sieht bei mir wie folgt aus:

TAG=alpine
DATABASE_CLIENT=mongo
DATABASE_HOST=<mongohost>
DATABASE_PORT=<port>
DATABASE_NAME=<db_name>
DATABASE_USERNAME=<user>
DATABASE_PASSWORD=<pass>
DATABASE_AUTHENTICATION_DATABASE=<aut_db>
VIRTUAL_HOST=<url>
LETSENCRYPT_HOST=<url>
LETSENCRYPT_EMAIL=<mailaddr>

Das dazugehörige docker-compose.yml sieht dann so aus:

version: '3'

services:
  strapi:
    container_name: strapi
    image: strapi/strapi:${TAG}
    environment:
      - DATABASE_CLIENT=${DATABASE_CLIENT}
      - DATABASE_HOST=${DATABASE_HOST}
      - DATABASE_PORT=${DATABASE_PORT}
      - DATABASE_NAME=${DATABASE_NAME}
      - DATABASE_USERNAME=${DATABASE_USERNAME}
      - DATABASE_PASSWORD=${DATABASE_PASSWORD}
      - DATABASE_AUTHENTICATION_DATABASE=${DATABASE_AUTHENTICATION_DATABASE}
      - VIRTUAL_HOST=${VIRTUAL_HOST}
      - LETSENCRYPT_HOST=${LETSENCRYPT_HOST}
      - LETSENCRYPT_EMAIL=${LETSENCRYPT_EMAIL}
    ports:
      - 1337:1337
    volumes:
      - strapi_data:/srv/app

volumes:
  strapi_data:

networks:
  default:
    external:
      name: nginx-proxy

Diese YAML-Struktur sollte bereits bekannt sein. Es wird ein Container mit dem Namen strapi erstellt. Basierend auf dem Tag wird das Image gezogen, die benötigten Parameter für die Datenbank sowie für die automatische Let’s-Encrypt-Zertifikatsanforderung werden aus der .env-Datei ausgelesen. Strapi verwendet Standardmäßig 1337 als Port.

Es wird ein Volume angelegt und verlinkt, genauso wird auch das Standard-Netzwerk angegeben – somit kann jwilder’s companion wirken und wir bekommen ein SSL-Zertifikat.

Das ist es eigentlich auch schon – die .env und die docker-compose.yml sollten in einem Ordner auf dem Dateisystem abgelegt werden, dann kann Strapi mit

docker-compose up

gestartet werden. Anschließend kann mit dem Modellieren begonnen werden.

Zum Weitermachen empfiehlt sich die Tutorial-Serie von Strapi, die kann hier aufgerufen werden.

Wie geht es weiter?

Das ist eine gute Frage – ich bin mir ehrlich gesagt nicht sicher, ob ich in die Datenmodellierung eingehen sollte oder nicht. Was auf jeden Fall irgendwann mal folgen wird, ist eine Anleitung – Beschreibung einer Vorgehensweise – wie man per Paketmanager Strapi als Entwicklungsumgebung lokal einrichtet, Anpassungen vornimmt und ein Docker-Image daraus baut… Oh und wie man (relativ) einfach die Artikel aus Ghost importiert. Also haben wir zu Strapi mindestens noch 2 Artikel.