Eine Datenbank einrichten

Eine Datenbank einrichten

Auf der Website des Konferenzgästebuchs geht es darum, während der Konferenzen Feedback zu sammeln. Wir müssen die Kommentare von den Konferenzteilnehmer*innen in einem permanenten Speicher ablegen.

Ein Kommentar lässt sich am besten durch eine feste Datenstruktur beschreiben: Autor*in, E-Mail, der Text des Feedbacks und ein optionales Foto. Das ist die Art Daten, die am besten in einer traditionellen relationalen Datenbank gespeichert wird.

PostgreSQL ist das Datenbanksystem unserer Wahl.

PostgreSQL zu Docker Compose hinzufügen

Auf unserem lokalen Rechner haben wir uns entschieden, Docker zur Verwaltung von Diensten zu verwenden. Die generierte docker-compose.yml-Datei beinhaltet bereits PostgreSQL als Dienst:

docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
###> doctrine/doctrine-bundle ###
database:
    image: postgres:${POSTGRES_VERSION:-13}-alpine
    environment:
        POSTGRES_DB: ${POSTGRES_DB:-app}
        # You should definitely change the password in production
        POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ChangeMe}
        POSTGRES_USER: ${POSTGRES_USER:-symfony}
volumes:
    - db-data:/var/lib/postgresql/data:rw
    # You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
    # - ./docker/db/data:/var/lib/postgresql/data:rw
###< doctrine/doctrine-bundle ###

Dadurch wird ein PostgreSQL-Server installiert und einige Environment-Variablen konfiguriert, die den Datenbanknamen und die Credentials (Anmeldeinformationen) steuern. Die Werte spielen keine Rolle.

Wir stellen auch den PostgreSQL-Port (5432) des Containers dem lokalen Host zur Verfügung. Das wird uns helfen, von unserer Maschine aus auf die Datenbank zuzugreifen:

docker-compose.override.yml
1
2
3
4
5
###> doctrine/doctrine-bundle ###
database:
    ports:
    - "5432"
###< doctrine/doctrine-bundle ###

Note

Die pdo_pgsql-Erweiterung sollte installiert worden sein, als PHP in einem vorherigen Schritt eingerichtet wurde.

Docker Compose starten

Starte Docker Compose im Hintergrund (-d):

1
$ docker-compose up -d

Warte ein wenig, bis die Datenbank hochgefahren ist und überprüfe, ob alles in Ordnung ist:

1
2
3
4
5
$ docker-compose ps

        Name                      Command              State            Ports
---------------------------------------------------------------------------------------
guestbook_database_1   docker-entrypoint.sh postgres   Up      0.0.0.0:32780->5432/tcp

Überprüfe die Docker Compose logs wenn es keine aktiven Container gibt oder wenn die State-Spalte nicht Up anzeigt:

1
$ docker-compose logs

Zugriff auf die lokale Datenbank

Die Verwendung des psql-Befehls im Terminal kann sich von Zeit zu Zeit als nützlich erweisen. Aber Du musst dir die Anmeldeinformationen und den Datenbanknamen merken. Weniger offensichtlich ist, dass Du auch den lokalen Port kennen musst, mit dem die Datenbank auf dem Host läuft. Docker wählt einen zufälligen Port, so dass Du an mehr als einem Projekt gleichzeitig mit PostgreSQL arbeiten kannst (der lokale Port ist Teil der Ausgabe von docker-compose ps).

Wenn Du psql über die Symfony CLI aufrufst, musst Du dir nichts merken.

Die Symfony CLI erkennt automatisch die für das Projekt ausgeführten Docker-Dienste und stellt die Environment-Variablen bereit, die psql für die Verbindung zur Datenbank benötigt.

Dank dieser Konventionen ist der Zugriff auf die Datenbank via symfony run viel einfacher:

1
$ symfony run psql

Note

Wenn Du die psql Binärdatei nicht auf Deinem lokalen Host hast, kannst Du sie auch über docker-compose laufen lassen:

1
$ docker-compose exec database psql app symfony

Datenbank-Daten exportieren und importieren

Verwende pg_dump um did Datenbank-Daten zu exportieren:

1
$ symfony run pg_dump --data-only > dump.sql

Und importiere die Daten mit:

1
$ symfony run psql < dump.sql

PostgreSQL zu Platform.sh hinzufügen

Für die Produktiv-Infrastruktur auf Platform.sh sollte das Hinzufügen eines Dienstes wie PostgreSQL in der .symfony/services.yaml-Datei erfolgen, das wurde bereits durch das Recipe vom webapp-Paket gemacht:

.platform/services.yaml
1
2
3
database:
    type: postgresql:13
    disk: 1024

Der database-Dienst ist eine PostgreSQL-Datenbank (in der selben Version wie für Docker), die wir mit einer Kapazität von 1 GB bereitstellen wollen.

Wir müssen die Datenbank auch mit dem Anwendungscontainer "verknüpfen", was in .platform.app.yaml beschrieben ist:

.platform.app.yaml
1
2
relationships:
    database: "database:postgresql"

Der database-Dienst vom Typ postgresql wird auf dem Anwendungscontainer mit database referenziert.

Kontrolliere, daß die pdo_pgsql-Erweiterung bereits installiert ist für die PHP-Runtime.

.platform.app.yaml
1
2
3
4
5
runtime:
    extensions:
        # other extensions
        - pdo_pgsql
        # other extensions

Zugriff auf die Platform.sh-Datenbank

PostgreSQL läuft nun sowohl lokal über Docker, als auch in der Produktivumgebung auf Platform.sh.

Wie wir gerade gesehen haben, verbindet symfony run psql sich automatisch mit der von Docker gehosteten Datenbank – Dank der Environment-Variablen, die von symfony run bereitgestellt werden.

Wenn Du eine Verbindung zur PostgreSQL-Datenbank herstellen möchtest, die auf den Production-Containern gehostet wird, kannst Du einen SSH-Tunnel zwischen dem lokalen Computer und der Platform.sh-Infrastruktur öffnen:

1
2
$ symfony cloud:tunnel:open
$ symfony var:expose-from-tunnel

Standardmäßig werden Platform.sh-Dienste nicht als Environment-Variablen auf dem lokalen Rechner angezeigt. Dafür musst Du zusätzlich den var:expose-from-tunnel-Befehl ausführen. Warum? Die Verbindung zur Datenbank in der Produktivumgebung ist ein gefährlicher Vorgang. Du kannst mit echten Daten herumpfuschen.

Verbinde dich nun via symfony run psql wie bisher mit der remote PostgreSQL-Datenbank:

1
$ symfony run psql

Wenn du fertig bist, vergiss nicht, den Tunnel zu schließen:

1
$ symfony cloud:tunnel:close

Tip

Um einige SQL-Abfragen auf der Production-Datenbank auszuführen, kannst Du auch den symfony sql-Befehl anstelle einer Shell verwenden.

Environment-Variablen bereitstellen

Docker Compose und Platform.sh arbeiten dank Environment-Variablen nahtlos mit Symfony zusammen.

Überprüfe alle Environment-Variablen, die durch symfony bereitgestellt werden, indem Du symfony var:export ausführst:

1
2
3
4
5
6
7
8
$ symfony var:export

PGHOST=127.0.0.1
PGPORT=32781
PGDATABASE=main
PGUSER=main
PGPASSWORD=main
# ...

Die PG* Environment-Variablen werden vom psql Dienstprogramm gelesen. Was ist mit den anderen?

Wenn ein Tunnel zu Platform.sh mit var:expose-from-tunnel geöffnet ist, gibt der var:export-Befehl die Environment-Variablen in der Platform.sh zurück:

1
2
3
4
$ symfony cloud:tunnel:open
$ symfony var:expose-from-tunnel
$ symfony var:export
$ symfony cloud:tunnel:close

Deine Infrastruktur beschreiben

Du hast es vielleicht noch nicht gemerkt, aber es ist sehr hilfreich die Infrastruktur mit beim Code zu speichern. Docker und Platform.sh nutzen Konfigurationsdateien um die Infrastruktur des Projektes zu beschreiben. Wenn eine neue Funktionalität einen zusätzlichen Service braucht, sind die Änderungen des Code und die Änderungen für die Infrastruktur im selben Patch.

This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.