Ihr habt eine Gitlab-Instanz in eurer Firma stehen? Ihr wollt mit Deployments anfangen, habt aber keine Lust auf Jenkins? Überraschung: Mit Gitlab könnt ihr auch Deployments durchführen!
Schon lange sind die Zeiten vorbei, in denen man einfach via FTP Dateien vom heimischen Rechner auf den Kundenserver hochschieben sollte. Wenn ihr händisch mittels rsync
oder git
Quellcode auf Develop-, Staging- oder Produktiv-System schiebt, ist der Sprung zu einem automatischen Deployment gar nicht mehr so weit, wenn ihr Gitlab verwendet.
Warum solltet ihr automatische Deployments verwenden?
- Ihr benötigt keine SSH-Zugangsdaten mehr
- Ihr vergesst nie wieder, vor dem Deployment ein Backup zu machen
- Ihr vergesst nie wieder, nach erfolgtem Deployment den Cache zu leeren
- Ihr vergesst nie wieder, nach dem Deployment zu überprüfen, ob die Seite noch funktioniert 😉
Nachfolgend findet ihr ein Deployment via git
, ohne weitere Zusätze. Nachdem das Prinzip verstanden ist, kann das Rezept auch für rsync
, npm
, composer
oder jede andere Form von Transportmethode angepasst werden, und um beliebige andere schlaue Handgriffe erweitert werden.
Vorbereitung
Ein Git-Deployment sieht für euch normalerweise wie folgt aus:
- Ihr wechselt per SSH auf den Zielhost.
- Dort wechselt ihr in das Projektverzeichnis, in der per
git clone
das Projekt ausgecheckt war. - Ihr führt ein
git pull
(plus ggf. weitere Kommandos durch). - Ihr beendet die SSH-Verbindung.
Genau diese Handgriffe führt ein Gitlab-Deployment für euch automatisch durch, wenn bestimmte Bedingungen im Git erfüllt sind. In der Regel ist diese Bedingung ein Commit in einen bestimmten Branch, oder das Auftauchen eines neuen Tags.
Falls ihr der ganzen Automatik nicht traut, könnt ihr auch festlegen, dass das Deployment mit einem Knopf aus dem Webfrontend von Gitlab gestartet wird.
Auftritt Gitlab
Dreh- und Angelpunkt ist das installierte Gitlab-CI-Modul von Gitlab. Dies wird eurer lokalen Gitlab-Installation hinzugefügt. Danach könnt ihr jedes eurer Projekte mit einer Datei namens gitlab-ci.yml
ausstatten, in der ihr das Deployment beschreibt.
Meine Vorlage dafür sieht inzwischen wie folgt aus:
# Never use Docker image without pinned version
image: governmentpaas/git-ssh:f120938e7390ec36314ec037465a1b35a079243e
before_script:
- eval $(ssh-agent -s)
- mkdir -p ~/.ssh
- echo "${SSH_CONFIG}" > ~/.ssh/config
- echo "${SSH_KNOWNHOSTS}" > ~/.ssh/known_hosts
- ssh-add <(echo "${SSH_PRIVATEKEY}")
# Hier könnte Testing durchgeführt werden.
# Das Deployment wird nur durchgeführt, wenn der Test erfolgreich ist.
# test:
# image: cytopia/eslint
# stage: test
# only:
# - master
# - merge_requests
# script:
# - tools/ci/test.sh
deploy_production:
stage: deploy
environment:
name: production
url: ${PRODUCTION_URL}
variables:
ENVIRONMENT_HOST: ${CI_ENVIRONMENT_NAME}
ENVIRONMENT_DIR: ${PRODUCTION_DIR}
ENVIRONMENT_URL: ${PRODUCTION_URL}
only:
- master
# - tags
# when: manual
script:
#- ssh ${ENVIRONMENT_HOST} "cd ${ENVIRONMENT_DIR} && echo 'Start DB backup...'"
- ssh ${ENVIRONMENT_HOST} "cd ${ENVIRONMENT_DIR} && git pull && git checkout ${CI_COMMIT_SHA} ."
#- ssh ${ENVIRONMENT_HOST} "cd ${ENVIRONMENT_DIR} && echo 'Clear cache...'"
# deploy_staging:
# deploy_develop:
# Hier könnten weitere Deployments für andere Zielsysteme stehen,
# die man einfach von "deploy_production" kopieren kann
In dem Skript sind die Schritte für Building und Testing aktuell ausgeklammert, können von euch aber einfach aktiviert werden. Der eigentliche Clou ist hier, dass Gitlab mit einigen von euch hinterlegten Variablen in der letzten Zeile der Datei aufgefordert wird, eine SSH-Verbindung zu dem Zielhost aufzumachen und dort ein git checkout
durchzuführen.
Die eigentliche Magie ist dabei, dass Gitlab exakt den aktuellen ausgewählten Commit auf dem betreffenden Zielsystem auscheckt. Mit der direktive only
legt ihr z.B. einen bestimmten Branch oder ein Tag fest, mit when: manual
eine manuelle Ausführung. Und im Falle eines verpfuschten Deployments, könnt ihr aus dem Gitlab-Webfrontend auch einen älteren Commit deployen lassen!
Das Deployment-Skript lässt sich natürlich um weitere Kommandos erweitern, die man auf dem Zielsystem ausführen möchte. Caches leeren, Composer ausführen oder Backups anlegen – all dies kann man hier problemlos hinzufügen. Und außerdem sehr ihr bereits, wie man z.B. für ein Develop- oder Staging-System das Skript erweitern könnt. Mehr Informationen über das Thema findet ihr in der offizielen Gitlab-CI-Dokumentation.
Variablen
Das obige Deployment-Skript ist ohne große Änderungen für viele Projekte verwendbar. Pro Projekt hinterlegt man in Gitlab nur noch ein paar Pipeline-Settings:
Variable | Inhalt |
---|---|
SSH_CONFIG |
Hier muss eine SSH-Config z.B. für production hinterlegt werden. Siehe unten. |
SSH_KNOWNHOSTS |
Hier muss das Ergebnis von ssh-keyscan [-p PORT] HOSTNAME für jeden der Hosts in SSH_CONFIG hinterlegt werden. |
SSH_PRIVATEKEY |
Der SSH-Key, mit dem sich Gitlab zum Produktions-System verbinden darf. |
PRODUCTION_URL |
Die URL, unter der das Produktions-System erreichbar ist. |
PRODUCTION_DIR |
Der Pfad, in dem die Produktions-Installation liegt. |
Die letzten drei Variablen kann man ggf. noch für DEVELOP_
und STAGING_
ausführen.
SSH-Config
Die Variable SSH_CONFIG
benutzt einen kleinen Trick, um die für das Deployment notwendigen SSH-Zugangsdaten zu speichern: Eine sehr kompakte Art und Weise, um Serverdaten inklusive Ports, Benutzernamen und IPs aufzulisten, ist die SSH-Config. Für Gitlab kann man dieses Format ganz wunderbar verwenden, um die Server-Konfiguration für die Deployment-Server in einer Pipeline-Variable zu hinterlegen.
Host production
Hostname 192.168.178.12
Port 22
User www-data
Zu beachten ist dabei, dass in der SSH-Config keine Passwörter gespeichert werden können. Das ist aber auch in Ordnung, da man sinnigerweise die Authentifizierung des Zugangs über einen SSH-Schlüssel durchführt.
Fazit
Nachdem all diese Handgriffe vollbracht sind, könnt ihr im Idealfall 30 Sekunden nach eurem Commit bereits euren Quellcode auf der jeweiligen Zielumgebung bewundern. Projektmanager und Tester werden es euch danken, jederzeit den aktuellsten Stand auf dem Entwicklungssystem vorzufinden – und ihr werdet es euch selber danken, beim Deployment nicht das Backup vergessen zu haben. 😉
Außerdem müsst ihr dem Rest des Teams nicht großartig erklären, wie Deployments jetzt funktionieren: Jedes Teammitglied, dass Git benutzt, kann ohne weiteres Vorwissen mustergültige Deployments hinlegen.
Update: Inzwischen gibt es eine überarbeitete Version des Artikels „Fehlerfreie Gitlab-Deployments für Shopware & Co“ auf den Seiten meines Arbeitgebers.