Wie du deine PHP Anwendung mit der Gitlab Pipeline deployst

Dieses Tutorial wird dir zeigen, wie du in wenigen Schritten deine PHP Anwendung per SFTP auf deinen Server automatisch deployen kannst. Das wird dir helfen deine Entwicklung zu beschleunigen ohne die Kontrolle über das Deployment abzugeben.

Für dieses Tutorial wird ein Gitlab Account benötigt. Solltest du noch keinen Gitlab Account besitzen kannst du diesen Link benutzen, um dir einen kostenlosen Account zu erstellen.

TL;DR

Das Script besitzt 2 Stages. Die deploy Stage nutzen wir zum manuellen Deployment und die Stage deploy-tag zum Deployen nach Pushen eines Tags.

stages:          
  - deploy
  - deploy-tag

deploy-job:
  stage: deploy
  when: manual  
  image: mwienk/docker-lftp:latest
  script:
    - lftp -e "set ftp:ssl-allow false; mirror --exclude .git/ --exclude .gitlab-ci.yml -eRnv . /; exit;" -u $CI_USERNAME,$CI_PASSWORD $CI_HOST

deploy-tag-job:
  stage: deploy-tag
  only:
    - tags  
  image: mwienk/docker-lftp:latest
  script:
    - lftp -e "set ftp:ssl-allow false; mirror --exclude .git/ --exclude .gitlab-ci.yml -eRnv . /; exit;" -u $CI_USERNAME,$CI_PASSWORD $CI_HOST

Vorbereitungen

Zu Testzwecken habe ich ein kleines Bootstrap 5 Projekt mit 3 PHP-Dateien angelegt. Diese PHP Dateien sollen am Ende automatisch auf deinen Hoster hochgeladen und die Dateien aktualisiert werden.

  • index.php
  • header.php
  • footer.php

header.php

<!doctype html>
<html lang="de" class="h-100">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Gitlab CI/CD example content">
    <meta name="author" content="Dominik Ratzow">
    <title>Gitlab CI/CD example content</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha256-YvdLHPgkqJ8DVUxjjnGVlMMJtNimJ6dYkowFFvp4kKs=" crossorigin="anonymous">

    <meta name="theme-color" content="#7952b3">
    <style>
        footer {
            position: fixed;
            bottom: 0;
            width: 100%;
        }
    </style>
</head>

<body>
    <header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom container">
        <a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none">
            <svg class="bi me-2" width="40" height="32">
                <use xlink:href="#bootstrap"></use>
            </svg>
            <span class="fs-4">Simple header</span>
        </a>

        <ul class="nav nav-pills">
            <li class="nav-item"><a href="#" class="nav-link active" aria-current="page">Home</a></li>
            <li class="nav-item"><a href="#" class="nav-link">Features</a></li>
            <li class="nav-item"><a href="#" class="nav-link">Pricing</a></li>
        </ul>
    </header>

index.php

<?php require_once 'header.php'; ?>
<main>
    <section class="py-5 text-center container flex-shrink-0">
        <div class="row py-lg-5">
            <div class="col-lg-6 col-md-8 mx-auto">
                <h1 class="fw-light">Beispiel Überschrift</h1>
                <p class="lead text-muted">Das ist nur ein Beispieltext!</p>
                <p>
                    <a href="#" class="btn btn-primary my-2">Klick mich!</a>
                </p>
            </div>
        </div>
    </section>
</main>

<?php require_once 'footer.php'; ?>

footer.php

<footer class="py-2 mt-auto bg-light">
    <div class="container">
        <p class="mb-1">
            <a href="https://www.ratzownal.de">© Dominik Ratzow 2022</a>
        </p>
    </div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha256-cMPWkL3FzjuaFSfEYESYmjF25hCIL6mfRSPnW8OVvM4=" crossorigin="anonymous"></script>
</body>

</html>

Gitlab Pipeline

Erstellen der .gitlab-ci.yml

Mit deinem kostenlosen Gitlab Account kannst du aktuell 400 CI/CD Minuten im Monat nutzen (Quelle). Diese CI/CD Minuten können dazu genutzt werden um automatische Scripte für deine Gitlab Projekte auszuführen. Es gibt weit aus mehr Möglichkeiten der Automatisierung in Gitlab als nur das Deployment. Diese sind aber nicht Gegenstand dieses Tutorials.

Um eine Gitlab Pipeline zu erstellen musst du lediglich eine Datei in deinem Gitlab Projekt erstellen und einchecken. Diese Datei muss den Namen .gitlab-ci.yml haben. Andere Dateinamen werden von Gitlab nicht als Pipeline-Datei erkannt. Erstelle bitte eine .gitlab-ci-yml Datei in deinem Projekt mit folgendem Inhalt.

stages:          
  - deploy

deploy-job:
  stage: deploy  
  image: mwienk/docker-lftp:latest
  script:
    - lftp -e "set ftp:ssl-allow false; mirror --exclude .git/ --exclude .gitlab-ci.yml -eRnv . /; exit;" -u XusernameX,XpasswordX XhostX

Dieses Script sorgt dafür, dass jeder Mal nach dem Pushen in das Gitlab Projekt das Script startet und deinen Inhalt auf den angegebenen Hoster transferiert. Im nächsten Schritt schauen wir uns den Aufbau und die Befehle dieser Datei genauer an.

Euer Projekt sollte nun wie folgt aussehen.

Projektdateien für das Beispiel Gitlab-CI-CD-Deployment
Aktuelle Projektdateien

Erklärung der Pipeline Datei

Zunächst werden die Stages, die durchlaufen werden sollen definiert. Diese Definition ist optional. Lassen wir diese Zeilen weg wird Gitlab automatisch nach dem Standard vorgehen. Die Standardstages sind .pre, build, test, deploy und .post. Dieses Tutorial konzentriert sich lediglich auf die Deploy-Stage und daher definieren wir diese unterhalb von Stages.

Im übrigen kannst du die Stages benamen wie du möchtest. Achte lediglich darauf, dass die Stages immer gleich benamt werden. In meinem Beispiel muss Zeile 2 und Zeile 5 den gleichen Namen haben. Ich empfehle aber einen aussagekräftigen Namen zu wählen und habe daher die Deployment-Stage „deploy“ genannt.

Als nächstes Implementieren wir die definierten Stages. Zeile 4 ist ebenfalls lediglich eine freiwählbare Bezeichnung und dient nur zur visuellen Zwecken.

Mit dem image-Attribut setzen wir das Docker Image, welches das Script benutzen soll. In diesem Fall ist es ein Image welches bereits lftp vorinstalliert hat. Das erleichtert das von uns zu programmierende Script deutlich. Es wäre natürlich möglich ein Alpine Image nehmen, jedoch müsste dann noch lftp oder Vergleichbares jedes Mal per Script im Docker Container installiert werden.

Solltest du überhaupt noch keine Kenntnisse von Docker haben reicht es Zeile 6 einfach zu akzeptieren, denn letztlich stellt das Image uns nur eine Möglichkeit dar, ein lftp Kommando abzusetzen.

Zeile 7 gibt an, dass nun das Script folgt, welches der Docker Container absetzen soll, wenn dieser gestartet ist.

Das lftp Script sieht sehr kompliziert aus. Ich gehe nicht auf alle Einzelheiten dieses Kommandos ein. Diese können unter diesem Link eingesehen werden.

Generell gesagt spiegelt der Befehl mirror das Quellverzeichnis mit dem Zielverzeichnis. Die Flags des Mirror Kommandos:

  • -e : löscht Dateien im Zielverzeichnis, die nicht im Quellverzeichnis sind
  • -R: Spiegelt nicht nur das aktuelle Verzeichnis sondern auch Unterverzeichnisse (Rekursion)
  • -n: Überträgt nur Daten, die neuer sind. Dies spart nicht veränderte Dateien zu übertragen
  • -v: Zeigt Details in der Konsolenausgabe an
  • –exclude: Exkludiert Ordner oder Dateien vom Spiegeln. Diese Ordner und Dateien werden nicht übertragen!

Das -u Flag des lftp Kommandos gibt die Nachfolge von Benutzernamen und Passwort, getrennt durch ein Komma, an. Als letztes wird der Host des Servers mitgegeben. In diesem Beispiel werden Benutzername, Passwort und Host im Klartext übertragen und im Projekt gespeichert. Ich zeige in nachfolgenden Sektionen, wie diese Informationen direkt in Gitlab gespeichert werden können, so dass im Projekt keine vertraulichen Informationen gespeichert werden müssen.

Hinter der Angabe von -eRnv kommen die Pfadangaben. Da die Dateien in meinem Fall auf Ebene der .gitlab-ci.yml liegen reicht ein „.“ aus. Der Punkt gibt das aktuelle Verzeichnis an. Nach dem Leerzeichen folgt das Zielverzeichnis auf dem Server. Ich möchte die Dateien direkt in das Verzeichnis kopieren, welches bei Verbindungsaufbau zum Server geöffnet wurde. Daher gebe ich den Pfad mit einem „/“ an. Andere Beispiele findet ihr weiter unten im Artikel und eine Reference für die YAML Datei auf der Gitlab Webseite.

Ausführen der Gitlab Pipeline

Nachdem die .gitlab-ci.yml Datei in das Git Repositoy von Gitlab gepusht wurde läuft automatisch das deploy Script los. Navigiert im Browser zu eurem Gitlab Projekt und öffnet in der Seitenleiste unter CI/CD den Link Jobs.

Jobs in der Navigation
Jobs in der Navigation

Seid ihr schnell genug gewesen, könnt ihr noch den Pipeline Status running sehen.

Laufende Gitlab Pipeline
Laufende Gitlab Pipeline

Die Pipeline sollte nur ziemlich kurz laufen (abhängig von der Anzahl und Größe der Dateien).

Fertige Gitlab Pipeline - Laufzeit 25 Sekunden
Fertige Gitlab Pipeline – Laufzeit 25 Sekunden

Den detaillierten Status der Jobs könnt ihr mit einem Klick auf den Status (running/passed) einsehen. Nachdem der Job erfolgreich gelaufen ist sieht der Status in etwa wie folgt aus.

Detaillierter Gitlab Job mit Status „passed“

Sollte in eurer Pipeline ein Fehler auftreten könnt ihr diesen ebenfalls im Log sehen.

Erweiterung des Scriptes

Deployment per Knopfdruck anstatt automatisch

Mit dem vorgestellten Script läuft das Deployment nach Pushen des Codes automatisch los. Es gibt aber Fälle in denen das nicht gewollt ist. Oft wechsele ich zwischen Laptop und Desktop PC hin und her. Damit ich auf beiden Geräten den gleichen Stand habe, pushe ich meine Änderungen regelmäßig in das Git Repository. Viele dieser Codestände sind dann nicht final und sollen überhaupt nicht auf den Server transferiert werden. Eine einfache Erweiterung unseres Scriptes sorgt dafür, dass wir aktiv die Pipeline starten müssen und diese nicht automatisch aktiviert wird.

stages:          
  - deploy

deploy-job:
  stage: deploy
  when: manual  
  image: mwienk/docker-lftp:latest
  script:
    - lftp -e "set ftp:ssl-allow false; mirror --exclude .git/ --exclude .gitlab-ci.yml -eRnv . /; exit;" -u XusernameX,XpasswordX XhostX

Zum manuellen Starten fügen wir in Zeile „when: manual“ hinzu. Dies verhindert das automatische Loslaufen der Pipeline beim Pushen.

Navigiert erneut im Browser zu eurem Gitlab Projekt und öffnet in der Seitenleiste unter CI/CD den Link Jobs. Der Jobstatus steht nun auf skipped.

Manuelles Starten der Gitlab Pipeline
Manuelles Starten der Gitlab Pipeline

Im rechten Bereich könnt ihr einen Play-Button sehen. Nach einem Klick auf diesen öffnet sich ein Dropdown mit einem einzigen Eintrag. Wählt diesen Eintrag aus um die Pipeline zu starten. Den detaillierten Status des Jobs könnt ihr nun wie gewohnt über den Klick auf den Status einsehen.

Deployment per Knopfdruck und automatisch bei Bedarf

Für die meisten Entwicklungen nutze ich eine Kombination aus automatischen Deployment und manuellen Deployment. Das ermöglicht mir eine Automatik zu behalten, jedoch nicht bei jedem Push ein Datentransfer auf den Server zu starten. Wir erstellen in der .gitlab-ci.yml eine zweite Stage für den automatischen Transfer. Diesen konfigurieren wir so, dass die Stage nur bei neuen Tags ausgeführt wird.

Die Strategie dahinter ist ein automatisches Deployment, wenn wir einen neuen Tag pushen. Das erreichen wir mit dem only Attribut. Das Attribut wird auf „– tags“ gesetzt. Außerdem wird das when Attribut aus der automatischen deploy Stage entfernt.

stages:          
  - deploy
  - deploy-tag

deploy-job:
  stage: deploy
  when: manual  
  image: mwienk/docker-lftp:latest
  script:
    - lftp -e "set ftp:ssl-allow false; mirror --exclude .git/ --exclude .gitlab-ci.yml -eRnv . /; exit;" -u XusernameX,XpasswordX XhostX

deploy-tag-job:
  stage: deploy-tag
  only:
    - tags  
  image: mwienk/docker-lftp:latest
  script:
    - lftp -e "set ftp:ssl-allow false; mirror --exclude .git/ --exclude .gitlab-ci.yml -eRnv . /; exit;" -u XusernameX,XpasswordX XhostX

Pusht ihr nun ein Tag startet die Stage deploy-tag automatisch und führt das Script aus. Push ihr kein Tag dann könnt ihr die Stage deploy manuell bei Bedarf über das Webfrontend starten.

Schnellanleitung, wie ein Tag per Git erstellt und gepusht wird.

#alles stagen
git add .
#alles committen
git commit -m "commit and tag 0.0.1"
#Tag erstellen
git tag -a 0.0.1 -m "pre alpha release"
#Pushen mit Tags
git push --tags

Klartextinformationen aus der .gitlab-ci.yml entfernen

Klartextdaten in Quelldateien sind immer ein Risiko, dass die Daten in die falschen Hände geraten. Um das Risiko zu minimieren zeige ich euch, wie ihr in Gitlab diese Daten hinterlegen könnt und der Pipeline nutzen könnt.

Öffnet im Browser euer Gitlab Projekt und navigiert in der Seitenleiste zu Settings -> CI/CD. Auf dieser Seite gibt es eine Sektion mit dem Namen Variables.

Gitlab CI/CD Variablen
Gitlab CI/CD Variablen

Per Add variable legt ihr alle Informationen an, die wir brauchen. In diesem Fall sind das Benutzername, Passwort und Server. Es kann bei Protect variable zu Problemen kommen, wenn eure Tags nicht als protected markiert sind (Referenz), daher deaktiviere ich die Option. Mask variable versteckt die Ausgabe des Values in der detaillierten Statusausgabe der Jobs. Prinzipiell reicht es das Passwort zu verstecken – ich verstecke jedoch den Benutzernamen zusätzlich.

Hinzufügen von CI/CD Variablen
Hinzufügen von CI/CD Variablen
Übersicht der CI/CD Variablen
Übersicht der CI/CD Variablen

Einfügen dieser Variablen in unsere bestehende .gitlab-ci.yml.

stages:          
  - deploy
  - deploy-tag

deploy-job:
  stage: deploy
  when: manual  
  image: mwienk/docker-lftp:latest
  script:
    - lftp -e "set ftp:ssl-allow false; mirror --exclude .git/ --exclude .gitlab-ci.yml -eRnv . /; exit;" -u $CI_USERNAME,$CI_PASSWORD $CI_HOST

deploy-tag-job:
  stage: deploy-tag
  only:
    - tags  
  image: mwienk/docker-lftp:latest
  script:
    - lftp -e "set ftp:ssl-allow false; mirror --exclude .git/ --exclude .gitlab-ci.yml -eRnv . /; exit;" -u $CI_USERNAME,$CI_PASSWORD $CI_HOST

Beitrage der gleichen Kategorie

Raspberry PI Logo

Ich möchte euch in diesem Artikel zeigen, wie ihr auf eurem Raspberry PI 4 einen Gitlab Runner installieren könnt. Das Ziel von diesem Gitlab Runner sind unbegrenzte Minuten für die CI/CD Pipeline. Mit einem kostenlosen Gitlab Account habt ihr im Monat 400 freie Minuten für die Pipeline verfügbar. Benötigt ihr mehr als 400 Pipeline Minuten […]

0 Kommentare

Bitte tragt euren Namen ein.
Bitte tragt eure Email-Adresse ein.
Top