Netresearch Blog

Blog

Hier erfahren Sie alle News und Insights. Wir stellen unser Wissen bereit, geben Tipps und informieren über alles, was intern und extern bei uns passiert.

Nightly Builds und automatische Updates dank Docker und CI/CD

Software und Systeme müssen regelmäßig aktualisiert werden, insbesondere um Sicherheitslücken schnell zu schließen oder Bugfixes und Patches anzuwenden. Im besten Fall läuft das automatisch ab, damit kein Mensch ständig daran denken muss, Updates zu installieren. Dieser Artikel beschreibt das Setup für Nightly Builds unserer Docker-Images und automatische Rollouts auf die Systeme unserer Kunden.

Vorgehensweise Nightly Build mit Docker

Als TYPO3-Agentur bauen wir und maintainen für zahlreiche Kunden verschiedenste Systeme, häufig auf Basis von TYPO3 oder Magento. Diese Systeme müssen permanent auf dem aktuellen Stand gehalten werden. Dabei gilt es, zahlreiche Komponenten zu berücksichtigen, wie z. B. Updates für das Betriebssystem, PHP, Webserver, Cachingserver, Datenbank-Engines usw.

Ein Großteil der von uns entwickelten Systeme läuft bereits in Form von Docker-Containern, was die Automatisierung des Update-Prozesses stark vereinfacht. Und Automatisierung ist immer unser Ziel, getreu dem Motto: “I don’t wanna do it, I want the silly machine to do it!

Dabei gehen wir in zwei Schritten vor.

Schritt 1: Nightly Build

Die Docker-Images für unsere Applikationen müssen regelmäßig neu gebaut werden. Beim Build-Prozess sollen alle verfügbaren Updates installiert werden.

Weil wir uns nicht darauf verlassen, dass die Maintainer der Basis-Docker-Images immer sofort die neuesten Linux-Updates installieren, erweitern wir den Build per Dockerfile um einen entsprechenden upgrade-Befehl:

FROM php:8.0-fpm-alpine as base
RUN apk upgrade --no-cache --available

Der Build erfolgt per Gitlab CI. Da wir die darin integrierte Registry nutzen, können wir die vordefinierten Variablen von Gitlab verwenden, was das Handling von Secrets (z. B. für den Registry-Login) sehr vereinfacht. Beispiel aus einer .gitlab-ci.yml:

docker-build:
  image: docker:latest
  stage: build
  services:
    - name: $CI_REGISTRY/ci-helper/gitlab-worker-dind:latest
      alias: docker
  script:
    - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
    - tag='latest'
    - docker build --pull -t "$CI_REGISTRY_IMAGE:${tag}" .
    - echo "Installed versions are:"
    - docker run --rm "$CI_REGISTRY_IMAGE:${tag}" nginx -v
    - docker run --rm "$CI_REGISTRY_IMAGE:${tag}" php -v
    - echo "Syntax check for nginx:"
    - docker run --rm "$CI_REGISTRY_IMAGE:${tag}" nginx -t
    - docker push --quiet "$CI_REGISTRY_IMAGE:${tag}"
    - docker logout $CI_REGISTRY
  rules:
    - if: ($CI_PIPELINE_SOURCE == "schedule")

Für den Build ist ein Docker-in-Docker-Setup nötig (DIND), weil der CI-Job nicht direkt mit dem Docker-Daemon des Gitlab-Workers sprechen darf. Wir stellen also einen Service mit einem separaten Docker-Daemon bereit (Zeilen 4-6), der nur für den Build verwendet und anschließend weggeworfen wird.

Damit Fehler in der Konfiguration von nginx sofort auffallen, wird die Syntax vor dem Push geprüft (Zeile 15). Ein Fehler in der Konfiguration würde dazu führen, dass nginx nicht starten kann und das Image damit unbenutzbar wäre. Deswegen lassen wir den Build an dieser Stelle abbrechen. Gitlab sagt uns darüber per Chat Bescheid.

Der Build kann nur per Gitlab Schedule angestoßen werden (Zeile 19) und soll nicht bei jedem “git push” loslaufen. Bei Bedarf kann man aber den Prozess auch manuell per Play-Button im Browser anstoßen und ist nicht gezwungen, auf den Schedule zu warten.

Das oben gezeigte Setup existiert in Gitlab für alle Komponenten (sprich Container) der Applikation. Die Schedules laufen leicht versetzt, um die Last auf den Gitlab-Workern zeitlich zu verteilen.

Schritt 2: Rollout

Für die Rollouts recyclen wir unseren bestehenden Deployment-Prozess, der per Ansible ausgeführt wird. Es genügt, das Playbook mit entsprechenden Tags so zu unterteilen, dass bei Updates die nicht benötigten Schritte ausgelassen oder angepasst werden. Auszug aus dem Ansible-Playbook:

 - name: Pull image
   community.docker.docker_compose:
     project_src: "{{ remote_app_directory }}"
     pull: true
   register: docker_compose_output
   retries: 3
   delay: 30
   until: docker_compose_output is not failed
   tags:
     - always
  - name: Stop services and remove volumes + orphans
    community.docker.docker_compose:
      project_src: "{{ remote_app_directory }}"
      state: absent
      remove_orphans: true
      remove_volumes: true
    register: docker_compose_output
    tags:
      - deploy
  - name: Stop services, keep volumes
    community.docker.docker_compose:
      project_src: "{{ remote_app_directory }}"
      state: absent
      remove_volumes: false
    register: docker_compose_output
    tags:
      - update

Die Ausführung des Playbooks und damit das tatsächliche Update der Kundensysteme erfolgt per Timer Trigger in Concourse CI. Wir triggern Concourse nicht durch neu gebaute Images, damit wir die mit den Kunden vereinbarten Zeitfenster möglichst exakt einhalten können.

In diesem Beispiel versorgen wir drei Kundensysteme mit Updates, jeweils in unterschiedlichen Intervallen, um den Betrieb so wenig wie möglich zu stören.

Gitlab vs. Concourse CI

Warum nutzen wir für die Deployments/Updates nicht ebenfalls Gitlab CI?

Technisch wäre das durchaus möglich, aber in unserem konkreten Fall benötigt der Prozess Credentials und weitere Secrets, die in Hashicorp Vault abgelegt sind. Concourse CI bietet einen einfacheren, transparenteren Weg, um auf diese Secrets während der Pipeline-Ausführung zuzugreifen. In Gitlab ist das zwar auch möglich, aber es erfordert mehr Klimmzüge – oder man bezahlt alternativ die Premium-Variante, was wir momentan nicht wollen.

Fazit

Zusammengefasst sieht unser Setup so aus:

  • Gitlab CI baut Docker-Images, testet sie und pusht sie in die Registry
  • Concourse CI führt Updates zeitgesteuert per Ansible aus. Docker-Images werden auf Kundensystemen aktualisiert und Container neu gestartet
  • Im Fehlerfall bekommen wir (und je nach Projekt auch der Kunde) eine Meldung per Mail/Chat

Das Hauptziel ist die Gewährleistung der Sicherheit durch sehr schnelle Installation von Updates und Patches (Stichwort Zero Day Exploit).

Ein entscheidender Faktor ist, dass die Applikation vollständig dockerisiert ist. Dadurch werden sichere, klar abgegrenzte Updates möglich, ohne Gefahr zu laufen, den ganzen Server versehentlich vollautomatisch stillzulegen. Falls aber ein Container nach einem Update nicht mehr funktioniert, kann schnell ein Rollback auf einen früheren Image-Tag gemacht werden.

Ein detailliertes Monitoring der Zielsysteme ist aber trotzdem wichtig, damit wir es sofort merken, wenn doch mal ein Update Probleme bereitet. Dafür nutzen wir u. a. Uptime Robot, Newrelic und Instana.


Tobias Hein
Head of DXP

Sie sind neugierig geworden oder haben auch ein TYPO3-Projekt, für das Sie einen kompetenten Ansprechpartner mit über 20 Jahren Erfahrung suchen? Dann zögern Sie nicht und kontaktieren Sie noch heute unseren TYPO3-Experten.

Artikel teilen:

Newsletter abonnieren

 Newsletter zu B2B-E-Commerce- & TYPO3-Lösungen
 Netresearch Insights
Webinare & Events

Neueste Beiträge

Von Axel Seemann

TYPO3Camp Dresden 2024: Sessions, Erkenntnisse & Impressionen

Auch dieses Jahr waren wir als Sponsor und Teilnehmer beim TYPO3Camp in Dresden präsent. Im…

Weiterlesen
TYPO3 v13: Highlights in Core & Backend
Von Caroline Kindervater
TYPO3 v13: TOP 5 Highlights in Core und Backend

Jede neue TYPO3-Version hat neue Features, welche die Arbeit mit der Software erleichtern und den…

Weiterlesen
E-Commerce in Theorie & Praxis: Studenten BA Sachsen zu Besuch
Von Luca Becker
B2B-Commerce: Studenten der BA Sachsen zu Gast bei Netresearch

Netresearch engagiert sich unter der Leitlinie “enable & connect” dafür, junge Menschen in den…

Weiterlesen
B2B-Shop OroCommerce 5.1 für Petromax
Von Caroline Kindervater
Outdoor-Spezialist Petromax startet neuen B2B-Shop mit OroCommerce 5.1

Petromax vertreibt seine einzigartigen Outdoor-Artikel über zwei Online-Shops: einen für Endkunden…

Weiterlesen