Docker Images erstellen mit Packer

30. Sep. 2020 | DevOps, Hashicorp, Packer, Testumgebung

Wie in einem frühreren Blog-Post beschrieben, erstellen wir Test- und Schulungsumgebungen auf einer speziell dafür erstellten Plattform. Die Kernkomponente davon ist Docker. Wir ersparen uns so die manuellen Installationsschritte der Atlassian Applikationen. Wie die Images erstellt werden möchte ich in diesem Post ein wenig erläutern.

Docker

Bei Docker handelt es sich um eine Software zum Verwalten von Linux-Containern. Das ist eine Technologie, die ein wenig an virtuelle Maschinen erinnert, aber wesentlich weniger schwergewichtig ist. Bei einer virtuellen Maschine wird ein kompletter Computer in Software abgebildet. Speicher wird ihr fest zugeteilt, und Festplattenplatz wird exklusiv reserviert. Das heisst, auch nicht benötigte Ressourcen sind besetzt. Docker hingegen isoliert nur den Prozess, der darin läuft, von allen anderen Prozessen des Host-Systems. Ein Docker-Container hingegen benutzt nach Möglichkeit die Ressourcen des Hosts. Man kann z.B. Node.js in ein Docker-Image installieren ohne, dass der Host davon betroffen ist. Alle Dateien, die auf dem Host installiert sind, können in dem Image weiterverwendet werden. So enthält ein Image z.B. keinen Linux-Kernel, es wird immer der vom Host-System verwendet. Auch kann man in einem Container beliebig Dateien schreiben und verändern, der Host ist davon nicht betroffen, solange das nicht explizit konfiguriert wird.

Packer

Docker erstellt einen laufenden Container aus einem sogenannten Image. Das sind Archive, die die Dateien enthalten, die der laufende Container benutzen soll. Um diese zu erstellen, benutzt man meistens ein Docker-File. Darin kann man z.B. Shell Befehle ausführen, und Dateien in das Ziel-Image kopieren. Das ist zwar praktisch, wir wollten aber auch Synergien mit anderen Tools nutzen:

  • Vagrant ist schon im Einsatz, der Build Prozess sollte auch dafür funktionieren.
  • Der Build Prozess sollte auch für die VM Images unseres Cloud-Providers funktionieren.

Da wir schon mehrere Hashicorp-Tools im Einsatz haben, fiel die Entscheidung auf Packer.

Build-File

Der Build-Prozess mit Packer wird mit einer Datei im JSON-Format konfiguriert. Am Beispiel von Jira soll die Erstellung eines Images demonstriert werden. Die Datei besteht aus mehreren Sektionen. Die erste, die man anschauen muss, ist Builders:

"builders": [
    {
        "communicator": "ssh",
        "source_path": "bento/ubuntu-18.04",
        "provider": "virtualbox",
        "add_force": true,
        "type": "vagrant"
    },
    {
        "type": "docker",
        "image": "ubuntu:18.04",
        "commit": true,
        "changes": [
            "WORKDIR /tmp",
            "USER jirauser",
            "ENV HOSTNAME jira",
            "Volume /var/atlassian/jira",
            "EXPOSE 8080",
            "ONBUILD RUN date",
        "CMD ["/usr/local/startup.sh"]"
    ]
  }]

Hier sieht man, dass zwei Builds konfiguriert sind. Einmal für Vagrant (Virtualbox) und einmal für Docker. Bei Virtualbox passiert nicht viel, man konfiguriert ein Basisimage. In Docker müssen ein paar Sachen mehr konfiguriert werden.

Die wichtigsten Parameter:

  • image: Bei Docker geht man (fast) immer von einem Basisimage aus, auf das man aufbaut. Man findet sie auf Docker Hub.
  • CMD: Der Befehl, der beim Start des Images ausgeführt wird.
  • ENV: Man kann beim Build Umgebungsvariablen verwenden. Der ENV-Parameter kann mehrfach verwendet werden.
  • Volume: Ordner, die vom laufenden Container auf den Host verbunden werden. Dateien, die dort hinein geschrieben werden überstehen auch einen Container-Neustart, alle anderen nicht.
  • EXPOSE: Gibt die Netzwerk-Ports an, die der Container benötigt.

Der nächste wichtige Block sind die Provisioner. Damit kann man automatisieren, wie und mit was das Image erstellt und konfiguriert wird:

"provisioners": [{
            "type": "file",
            "source": "resources/",
            "destination": "/tmp"
        },
        {
            "type": "file",
            "source": "scripts/jira/",
            "destination": "/tmp"
        },
        {
            "type": "file",
            "source": "scripts/jira/startup.sh",
            "destination": "/usr/local/"
        },
        {
            "type": "shell",
            "inline": "chmod u+x /usr/local/startup.sh"
        },
        {
            "type": "shell",
            "inline": "chmod u+x /tmp/*.sh"
        },
        {
            "type": "shell",
            "scripts": [
                "scripts/jira/docker-base.sh",
                "scripts/common/java.sh"
            ]
        },
        {
            "type": "shell",
            "inline": "bash /tmp/jira.sh {{user `version`}} {{user `software_memory_min`}} {{user `software_memory_max`}}"
        }
    ]

Der wichtigsten Provisioner sind:

  • file: Kopiert Dateien vom Host in den Container. Kann auch ganze Verzeichnisse kopieren.
  • shell: Führt Shell Scripts oder Shell Befehle aus. Man kann entweder Dateien angeben (scripts) oder direkt ein oder mehrere Befehle (inline).

Hier tauchen auch zum ersten Mal Variablen auf. Man kann sie aber überall in der Datei verwenden.

{
    "type": "shell",
    "inline": "bash /tmp/jira.sh {{user `version`}} {{user `software_memory_min`}} {{user `software_memory_max`}}"
}

Packer ersetzt ein Konstrukt wie {{user `version`}} durch den Wert, der in der Variable version konfiguriert ist.

Variablen können auf mehrere Arten gesetzt werden. Beim Start von Packer als Kommandozeilenargument, in einer weiteren Konfigurationsdatei, oder im variables Block:

"variables": {
    "compression_level": "6",
    "software_memory_max": "2048m",
    "software_memory_min": "1024m"
}

Damit kann man Defaultwerte für die Variablen vorgeben. Sie können aber auch mit den anderen beiden Varianten überschrieben werden.

Der letzte Block sind die post-processors. Die Provisioners sind unabhängig von den Buildern. Viele Aktionen, die man gerne automatisieren möchte, sind aber abhängig vom Builder. Z.B. benutzt man für Docker und Vagrant verschiedene Repositories, Docker Hub und Vagrant Cloud. Auch kann man mit dem Virtualbox-Builder das Image kompimieren, bei Docker nicht. Beispiel Vagrant Builder:

"post-processors": [{
    "type": "vagrant",
    "compression_level": "{{user `compression_level`}}",
    "keep_input_artifact": true,
    "output": "zuara-base-{{user `version`}}-{{.Provider}}.box",
    "only": ["vagrant"]
},
{
    "type": "vagrant-cloud",
    "box_tag": "mairer/zuara-base",
    "access_token": "{{user `cloud_token`}}",
    "version": "{{user `version`}}",
    "only": ["vagrant"]
}]

Hier sind zwei Post Processors konfiguriert, einmal zum Nachbearbeiten des Images (vagrant) und einmal zum Hochladen des Images (vagrant-cloud). Auch hier können Variablen verwendet werden. Mit der Option „only“: [„vagrant“] sagt man Packer, dass der Post-Processor nur beim Vagrant-Build ausgeführt werden soll. Ein Beispiel, um nach dem Docker-Build das Image zu taggen:

{
    "type": "docker-tag",
    "repository": "zuara/jira",
    "tag": "{{user `version`}}"
    "only": ["docker"]
}

Build

Ein Build kann jetzt mit folgendem Befehl gestartet werden:

packer build --only=docker -var 'version=7.13.3' buildfile.json

Dieser Befehl erstellt das Docker Image. Der Vagrant-Build kann entsprechend mit folgendem Befehl ausgeführt werden:

packer build --only=vagrant -var 'version=7.13.3' buildfile.json

Somit können wir beliebige Jira-Versionen für verschiedene Virtualisierungstechniken mit kleinstem Aufwand erstellen.

Haben Sie Fragen oder Anregungen zum diesem Blog-Beitrag? Dürfen wir Sie unterstützen?
Schreiben Sie uns auf hallo@zuara.ch oder rufen Sie uns an: 031 302 60 00. Wir freuen uns auf Ihre Anfrage!

Der Autor:

Roman Maire

Roman Maire

roman.maire@zuara.ch

Direkt: +41 79 307 60 29

      

Weitere Fachartikel und Neuigkeiten von Zuara

Denkanstösse zum Arbeiten mit E-Mails und Chat

Schon seit 10 Jahren wurde der Tod von E-Mail angekündigt. E-Mail hat jedoch weiterhin ihren Platz in der heutigen Welt. Chat-Lösungen und E-Mail existieren im Unternehmen nebeneinander. In diesem Blog zeige ich Ihnen, wann und wie Sie am besten welches Tool...

Portfolio for JIRA® – Strategische Projektplanung direkt in JIRA®

Portfolio for JIRA® ist ein Add-on für die Projektmanagement- und Issue-Tracking Software JIRA®, die von Atlassian® entwickelt wird. Das Add-on ermöglicht eine GANTT-ähnliche Echtzeitplanung in JIRA®. Die Informationen für die Planung werden den JIRA® Issues...

Dateien auf Share direkt aus Confluence heraus öffnen mit Zuara User Makro

Einleitung Hatten Sie bereits einmal das Problem, dass Sie eine Datei aus Confluence aus verlinken wollten, die auf einem Share liegt? Die meisten Browser verhindern dies aus Sicherheitsgründen und je nach Browser ist die Syntax der geforderten URL unterschiedlich....

KPI-Reporting in Jira

Jira ist viel mehr als nur eine Projektmanagementsoftware. Es können damit zum Beispiel auch interne Prozesse abgewickelt, Arbeitszeiten rapportiert oder - mit Jira Service Desk - ein komplettes IT Service Desk damit betrieben werden. Ein weiterer Anwendungsfall ist...

Confluence als Dateiablage

Sie brauchen ein paar Denkanstösse, wie man Confluence als Dateiablage sinnvoll verwendet? Lesen Sie diesen Blog-Artikel und zwei bis drei Minuten später werden Sie wissen, wie Sie Ihre Ablage verbessern können. Kennen Sie das Problem, tonnenweise Ordner mit...

Word Integration in Confluence

Eine häufige Anforderung bei der Arbeit mit Confluence ist die Integration von Office. Office ist bei vielen Unternehmen im Einsatz und bei einer Einführung von Confluence stellt sich dann die Frage, wie sich die Microsoft-Welt mit der Atlassian-Welt verbinden lässt....

Kollaborationsarchitektur – weg mit dem Tool-Salat!

Im letzten Blog-Beitrag "Digital Workplace/Home-Office – wie verteilte Zusammenarbeit gut funktioniert und wie nicht" bin ich bereits kurz auf den sperrigen Begriff Kollaborationsarchitektur eingegangen. Hier soll es nun darum gehen, diesen Begriff zu erklären und...

Atlassian Testumgebungen automatisieren

Einleitung und Problemstellung Es gibt viele Situationen, in denen wir schnell eine Testinstanz von Jira oder Confluence benötigen: Demonstrationen für Verkaufsgespräche, Testsysteme für Konfigurationen, Proof of Concepts, Schulungssysteme, Entwicklungssysteme für...

Ineffektive Teams – Lösungsansätze

Oder warum Agile motiviert. In unserem vorderen Post haben wir die Phänomene ineffektiver Teams aufgeführt: Social Loafing (Soziales Faulenzen) Free Riding (Trittbrettfahren) Sucker-Effekt (Trottel-Effekt) Group Think Nun möchten wir Lösungsansätze liefern, um diesen...

Alle im Homeoffice – auch Schülerinnen und Schüler

Aus aktuellem Anlass stellt sich für viele Schulen und Organisationen die Frage, wie ihre Mitarbeitenden weiterhin möglichst reibungslos zusammenarbeiten können und wie der Schulunterricht fortgesetzt werden kann. Teams und Klassen haben die folgenden Ansprüche, um...