Neue Welt - Strapi - Part 1

In Neue Welt - Strapi - Part 1 werde ich strapi als Docker Container betreiben. Als image nehme ich das Standard Docker Image von Strapi.

Neue Welt - Strapi - Part 1

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 setzten.

Was kann Strapi?

Ghost als Beispiel ist ein System was ich mittlerweile sehr gern habe, Ghost kann ausserdem 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

Custom Content Types

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

Die möglichen Feldtypen

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 Nachschlagenfeld (Lookup) 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

Strapi relation field settings

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 (relationnelles) 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 :)

graphql tools extension

Der Technologische Stack

Strapi ist in nodejs 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.

the possibilities

Was aber wiederrum 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öglichkeiten 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 setzten, 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 kucken, 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 Ontolgien 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 mein nginx-proxy (nachzulesen hier) Netzwerk bereitgestellt.

Da ich aktuell viele Instanzen bereitstelle - ich teste -, steuere ich den docker compose stack über eine enviorenment Datei an. Die sieht bei mir wie folgt aus.

TAG=alpine
DATABASE_CLIENT=mongo
DATABASE_HOST=<mongohost>                 // Beispiel mongo.meinedomain.de
DATABASE_PORT=<port>                      // Beispiel 27017
DATABASE_NAME=<db_name>                   // Beispiel strapi_prod
DATABASE_USERNAME=<user>                  // Beispiel root
DATABASE_PASSWORD=<pass>                  // Passwort zum user
DATABASE_AUTHENTICATION_DATABASE=<aut_db> // Beispiel admin
VIRTUAL_HOST=<url>                        // letsencrypt bsp. strapi.akube.de
LETSENCRYPT_HOST=<url>                    // letsencrypt bsp. strapi.akube.de
LETSENCRYPT_EMAIL=<mailaddr>              // letsencrypt issuer mail
.env file example

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
docker-compose.yml file

Diese yaml Struktur sollte bereits bekannt sein. Es wird ein Container mit dem Namen strapi erstellt - diesen Teil könnte man auch in die .env packen. Basierend auf dem Tag wird das image gezogen, die benötigten Parameter für die Datenbank sowie für die automatische letsencrypt Zertifikatsanfforderung werden aus der .env Datei ausgelesen. Strapi verwendet Standardmäßig 1337 - das hätte ich auch unter der Überschrift gefällt mir nicht so gut unterbringen können - als Port, ich habe das mal so gelassen.

Es wird ein Volume angelegt und verlinkt, genauso wird auch das Stadard-Netzwerk angegeben - somit kann jwilders comanion 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.