diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..a35ed00b5a4a0b270fa25ef36cf686eccae38038 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,2 @@ +FROM nginx +COPY html-dir /usr/share/nginx/html \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..17f4fe59ea78d724a6012c6941d1268340010e0c --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,9 @@ +version: '2' + +services: + web: + image: nginx + volumes: + - "./html-dir:/usr/share/nginx/html:ro" + ports: + - "8082:80" \ No newline at end of file diff --git a/docker/html-dir/index.html b/docker/html-dir/index.html new file mode 100644 index 0000000000000000000000000000000000000000..e2febd784640fbd3c6fa669671c0dea7ee0c321c --- /dev/null +++ b/docker/html-dir/index.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Hello World</title> +</head> +<body> + <h1>Hello SE3!</h1> +</body> +</html> \ No newline at end of file diff --git a/website/container-ci-cd.html b/website/container-ci-cd.html index 3af18de9e74a331a05ead1a85c1ffce8947881e9..06b6c20005e3e09f66eeedd7659e3d816af935b8 100644 --- a/website/container-ci-cd.html +++ b/website/container-ci-cd.html @@ -81,7 +81,6 @@ </head> <body> <textarea id="source"> - class: center, middle, first # Software-Entwicklung 3 @@ -95,41 +94,9 @@ class: center, middle, first 1. Recap 2. Container 3. CI/CD - -Container -* Was sind die Probleme? -* Was sind die Alternativen? Z.B. VM -* Warum keine VM? -* Lösung der Probleme mit Containern -* Wie unterscheiden sich Container von VMs? - * "Anwendungsvirtualisierung" - * Kernel des Hosts wird durchgereicht -* Container-Grundprinzipien - * Keine Daten im Container speichern - * Persistente Daten werden außerhalb des Containers abgelegt -* Container mit Docker - * Kurze Historie - * Probleme (root, Lizenz für Desktop-Client in Unternehmen) - * Alternativen (z.B. Podman) -* Demo: Aufruf von CLI-Tools per Docker-Container -* Wie wird ein Container definiert? `Dockerfile`, `docker-compose.yml` -* Demo: Start von `node`-Server inkl. Mounts des working-dir -* Wie kommen Daten in und aus den Container? - * Volume-Mounts - * Bind Mounts - * Port-Tunneling -* Ausblick: - * Microservices - * Containerregistry - -CI/CD -* Was ist CI? -* Was ist CD? -* Warum ist CI/CD sinnvoll? Was ist die Konsequenz wenn man darauf verzichtet? - --- -# Recap: Was haben wir letzte Woche besprochen? +# Recap: Was haben wir in der letzten Vorlesung besprochen? * Build Management mit Maven * Testing mit JUnit @@ -147,230 +114,208 @@ class: center, middle * Kompatibilitätsprobleme --- -# Build Management Tools +# Möglichkeiten zur Problemlösung -* Unterstützung bei Projekterstellung -* Standardisierung: Reproduzierbare Builds -* Automatisierung -* Verwaltung von Abhängigkeiten -* Durchführen von Tests -* Bündeln der Software -* Bereitstellung +* ... +* Virtuelle Maschinen +* Containerisierte Anwendungen -> Unterstützung des Entwicklungszyklus +> Kapselung der Anwendung mit zugehöriger Umgebung --- -# Beispiele -* Java: Maven, Gradle -* NodeJS: `npm`, `yarn` (Packagemanager) -* Unix: `make` -* Python: `pip` (Packagemanger), PyBuilder -* ... +# Virtuelle Maschinen + +_Schematische Darstellung_ + +<img src="img/container-ci_cd/vm.png" alt="VM Aufbau" width="100%"> --- -# Build Management Tool: Maven +# Container -* Grundprinzipien: Phasenmodell/Build Lifecycle & Konvention über Konfiguration & DRY -* Template-basierte (Java-)Projekterstellung mit **Archetypes** -* Dependeny Management -* Erweiterbar durch Plugins -* Unterstützung durch IDEs +_Schematische Darstellung_ + +<img src="img/container-ci_cd/container.png" alt="Container Aufbau" width="100%"> + +--- +# Docker + +* Umsetzung für Container +* Erste Version 2013 +* Container sind OCI (Open Container Initiative) kompatibel +* Enthält Versionsverwaltung für Images + * Sammlung von Images auf https://hub.docker.com +* Alternative `podman` +* Teilweise lizenzpflichtig (Docker Desktop) +* `root`-Problematik -## Standardverzeichnisstruktur -```bash -. project-root -├── pom.xml # Projektkonfiguration -├── src # Source Code -│ ├── main -│ │ ├── java # Java Code und Packages -│ │ └── resources # Dateien, die zur Laufzeit benötigt werden -│ └── test # Test Code -│ └── java -└── target -``` --- -# Maven: Build Lifecycle +# Begriffe -Werden bis zur angegebenen Phase durchgeführt. +**Image**: Containerabbild, das sämtliche Applikationen und Konfigurationen enthält. Kann auf bestehenden Images aufbauen. -1. `validate`: Überprüfen, ob alle Informationen vorhanden sind. -2. `compile`: Kompilieren der in `src` vorhandenen Dateien -3. `test`: Durchführen der in `test` vorhandenen Tests -4. `package`: Erstellen von z.B. `jar`-Dateien -5. `verify`: Nutzbar z.B. für statische Codeanalyse -6. `install`: Kopieren der `jar` nach `~/.m2/repository` -7. `deploy`: Veröffentlichen der `jar` in ein öffentliches Repo +**Container**: Instanziierung eines Images. Aus einem Image können beliebig viele Container gestartet werden. -Beispielaufruf: `mvn package` +**Dockerfile**: Beschreibt die Konfiguration eines Images. -Weitere Informationen: [Maven Build Lifecycle](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html) +**docker-compose.yml**: Konfigurationsdatei zur Ausführung ein oder mehrer Container. --- -# `pom.xml` Beispiel - General - -```xml -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <groupId>de.hdm.jordine</groupId> - <artifactId>musicmanager</artifactId> - <version>0.1.0-SNAPSHOT</version> - - <properties> - <maven.compiler.source>17</maven.compiler.source> - <maven.compiler.target>17</maven.compiler.target> - </properties> -``` +# Grundprinzipien + +* Jeder Container sollte nur einen Zweck erfüllen +* In Containern werden keine persistenten Daten gespeichert +* Sollen Daten persistiert werden, können z.B. `Volumes` oder `bind mounts` genutzt werden +* (weitere Prinzipen können folgen, abhängig von der Systemarchitektur) + --- -# `pom.xml` Beispiel - Dependencies - -```xml - <dependencies> - <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-engine</artifactId> - <version>5.8.2</version> - <scope>test</scope> - </dependency> - - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <version>4.4.0</version> - <scope>test</scope> - </dependency> - - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-api</artifactId> - <version>2.17.2</version> - </dependency> - - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-core</artifactId> - <version>2.17.2</version> - </dependency> - </dependencies> -``` +# Beispiele + +* Bauen eines Containers +* Starten eines Containers +* Containerzugriff +* Einbinden von Dateien des Hostsystems +* Zusammenfassendes Beispiel mit `docker compose` + +## Dokumentationen/Links +* [Docker Installation](https://docs.docker.com/compose/install/) +* [Dockerfile](https://docs.docker.com/engine/reference/builder/) +* [Docker Compose - Getting started](https://docs.docker.com/compose/gettingstarted/) +* [Nginx Docker Doku](https://hub.docker.com/_/nginx) + --- -# `pom.xml` Beispiel - Plugins - -```xml - <build> - <plugins> - <plugin> - <!-- https://stackoverflow.com/a/27168770 --> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <version>3.2.2</version> - <configuration> - <archive> - <manifest> - <addClasspath>true</addClasspath> - <mainClass>de.hdm.jordine.musicmanager.app.MusicManagerApp</mainClass> - </manifest> - </archive> - </configuration> - </plugin> - </plugins> - </build> - -</project> +# Bauen eines Containers + +## `Dockerfile` + ``` ---- -class: center, middle -# Warum ist Testing wichtig? +FROM nginx +COPY html-dir /usr/share/nginx/html +``` +## Bauen +```bash +docker build -t se3-nginx:0.0.1 . +``` --- -class: center, middle -# Welche Testarten kennen Sie? +# Starten eines Container +```bash +# Starten +docker run --rm -d se3-nginx:0.0.1 + +# Prüfen, ob der Container läuft +docker ps + +# Logs überprüfen (Containername entweder beim Start vergeben +# oder per docker ps) +docker logs <CONTAINER NAME> + +# Container beenden +docker stop <CONTAINER NAME> +``` --- -# Testarten +# Containerzugriff -* Usabilitytests -* **Softwaretests** -* Hardwaretests -* Securitytests -* ... +```bash +docker run --rm -d - p 8080:80 se3-nginx:0.0.1 +``` +## Öffnen der Website +> http://localhost:8080 +## Alternative Variante (ohne Dockerfile) +```bash +docker run --rm -d -p 8081:80 -v $(pwd)/html-dir:/usr/share/nginx/html:ro nginx +``` --- -# Testebenen +# `docker-compose` + +```yaml +version: '2' +services: + web: + image: nginx + volumes: + - "./html-dir:/usr/share/nginx/html:ro" + ports: + - "8082:80" +``` + +## Start +`docker-compose.yml` muss sich im aktuellen Verzeichnis befinden -* **Unittests**: Test einzelner Funktionen und Methoden -* **Integrationtests**: Test des Zusammenspiels mehrerer Module -* **Funktionstests**: Überprüfen der Geschäftslogik +```bash +# Mit M1 Chip docker compose, sonst docker-compose +docker compose up -d +``` + +--- +class: center, middle -* **End-to-End-Tests**: Testen echter Benutzungsszenarien (bspw. von UI bis DB) -* **Leistungstests**: Überprüfung der Performance -* **Reggressionstests**: Sicherstellung nach Änderungen, dass Bestandsfunktionen weiterhin funktionieren -* **Smoketests**: Grundlegende Funktionsüberprüfung, z.B. nach Release +# CI/CD -_nach: https://www.atlassian.com/de/continuous-delivery/software-testing/types-of-software-testing_ +## Continuous Integration & Continuous Deployment --- -# Testprinzip F.I.R.S.T +# Was ist Continuous Integration? -* **F**ast: Tests sollen schnell durchlaufen, damit diese häufig durchgeführt werden. -* **I**solated: Jeder Test sollte unabhängig sein und sein eigenes Enviroment mitbringen. -* **R**epeatable: Auch nach mehrfachen Durchläufen soll das Ergebnis identisch sein. -* **S**elf-validating: Automatische Überprüfung, ob Test erfolgreich war. -* **T**imely: Test sollte beim Entwickeln der Funktionalität geschrieben werden. +_nach ["What is Continuous Integration?", AWS, 2022](https://aws.amazon.com/devops/continuous-integration/?nc1=h_ls)_ -> Blick auf Demo-Projekt +* DevOps-Verfahren +* Zentrales Repository +* Automatisiertes testen und bauen der Anwendung +* Früher: + * Isolierte Arbeit an einzelnen Aufgaben + * Code wurde spät zusammengeführt (=Integration) +* Ziele: + * Bugs früher erkennen + * Kürzere Veröffentlichungszeiten + * Steigerung der Produktivität -> Warum? --- -# Unittests mit JUnit +# Mögliche Continuous Integration Vorgehensweise -* Nutzen der `assert`-Methoden, zum Überprüfen von erwarteten und tatsächlichen Werten -* Nutzen der Test-Annotations, z.B. - * `@Test` - * [`@RepeatedTest`](https://junit.org/junit5/docs/current/user-guide/#writing-tests-repeated-tests) - * [`@ParameterizedTest`](https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests) - * `@BeforeEach`/`@AfterEach` - * `@BeforeAll`/`@AfterAll` - * [`@DisplayName`](https://junit.org/junit5/docs/current/user-guide/#writing-tests-display-names) -* Integration in CI/CD-Prozesse +_angepasst nach ["Continuous Integration", Martin Fowler, 2006](https://www.martinfowler.com/articles/continuousIntegration.html)_ -Dokumentation: https://junit.org/junit5/docs/current/user-guide/ +* Code muss zentral in einem Repository abliegen. Definition eines Integrationsbranches. +* Automatisieren des Build-Prozesses +* Automatisieren des Test-Prozesses +* Regelmäßiger `merge` auf den Integrationsbranch +* Jeder `commit` auf den Integrationsbranch baut die Anwendung +* Schlägt ein Build fehl, soll dieser so schnell wie möglich repariert werden +* Build-Zeiten so schnell halten (nicht immer möglich) +* Testen in einem Klon der Produktionsumgebung +* Einfaches Bereitstellen der aktuellsten (kompilierten) Version --- -# Was sollte getestet werden? +# Was ist Continuous Deployment? -* "Happy path" - der einfachste Fall -* Randbedingungen -* Fehlerfälle +_nach ["What is Continuous Deployment?", AWS, 2022](https://aws.amazon.com/devops/continuous-delivery/)_ +* Automatisches Veröffentlichen der Software auf einer Testumgebung +* Unterschied zu Continuous Deployment + * Continuous Deployment: Automatische Veröffentlichung auf Produktionsumgebung + * Continuous Deployment: Manuelle Veröffentlichung inkl. Freigabe auf Produktionsumgebung --- -# Testing: Begrifflichkeiten +# Was ist Continuous Deployment? -## Mock -* Objekt, dass ein bestimmtes Verhalten simuliert -* Erlaubt schnelleres Testen -> **F**.I.R.S.T -* Framework-Beispiel: [Mockito](https://site.mockito.org) +_nach ["What is Continuous Deployment?", AWS, 2022](https://aws.amazon.com/devops/continuous-delivery/)_ -## Code coverage -* Gibt an, wieviel Prozent des Codes durch Tests abgedeckt sind -* Je höher der Wert, umso besser +<img src="img/container-ci_cd/ci_cd.png" alt="Ablauf CI/CD" width="100%"> --- -# Testdriven Development (TDD) +# CI/CD mit GitLab -* Entwicklungsmethode -* Tests werden vor dem eigentlichen Code entwickelt -* Mögliches Vorgehen (_nach: [it-agile.de](https://www.it-agile.de/agiles-wissen/agile-entwicklung/was-ist-testgetriebene-entwicklung/)): - * **Test "rot"**: Test erstellen, der auf einfachste Art und Weise die gewünschte Funktionalität erfüllt. Da kein Code besteht, der die Funktion abdeckt, schlagen die Tests fehl. - * Einfachste Umsetzung der Funktionalität bis der **Test "grün"** wird. - * **Refactoring** des Codes. Tests werden weiterhin regelmäßig durchgeführt und müssen grün bleiben. +* Repository wird für CI/CD genutzt +* (Shared) Runner führen Aktionen in definierten Phasen(=Stages) aus +* Eine Stage kann auf einem Docker-Image basieren +* Innerhalb des Image können Skripte ausgeführt werden +* Eine Pipeline besteht aus einer oder mehreren Stages --- -# Projektdemo - +# Beispiel CI/CD mit GitLab +* Beschreibung in `.gitlab-ci.yml` +> Blick ins Projekt </textarea> <script src="js/remark.min.js"> </script> diff --git a/website/img/.DS_Store b/website/img/.DS_Store index f493a5139ba44fb88a05dbb372e5aef51ea73c18..cd33953fadb95088298974018f972ee550907311 100644 Binary files a/website/img/.DS_Store and b/website/img/.DS_Store differ diff --git a/website/img/container-ci_cd/ci_cd.png b/website/img/container-ci_cd/ci_cd.png new file mode 100644 index 0000000000000000000000000000000000000000..481e89ed02613b09a9f04b3fd60d6595f6489615 Binary files /dev/null and b/website/img/container-ci_cd/ci_cd.png differ diff --git a/website/img/container-ci_cd/container.png b/website/img/container-ci_cd/container.png new file mode 100644 index 0000000000000000000000000000000000000000..8909a2c110acd5cf8b64eec69e842e60f763f81c Binary files /dev/null and b/website/img/container-ci_cd/container.png differ diff --git a/website/img/container-ci_cd/vm.png b/website/img/container-ci_cd/vm.png new file mode 100644 index 0000000000000000000000000000000000000000..8e88571011df10518f6de24ae5bb2178ed142a39 Binary files /dev/null and b/website/img/container-ci_cd/vm.png differ