Commit b59b76e6 authored by Nane Kratzke's avatar Nane Kratzke
Browse files

Übung 01 bis 03

parent 7c288b22
Dockerfile
FROM alpine:3.12
LABEL maintainer="Nane Kratzke <nane.kratzke@th-luebeck.de>"
RUN apk update
RUN apk add nginx
# Add to remove unnecessary package manager data
# RUN rm -rf /var/cache/apk/*
# Image Shrinking effect
# - activate to perform all steps ending in one image layer
# - deactivate all RUN commands above
# RUN apk update && \
# apk add nginx && \
# rm -rf /var/cache/apk/*
ADD web /var/www/html
ADD nginx.conf /etc/nginx/conf.d/localhost.conf
EXPOSE 80
ENTRYPOINT ["nginx", "-g", "daemon off;pid /tmp/nginx.pid;"]
\ No newline at end of file
FROM nginx:1.19
LABEL maintainer="Nane Kratzke <nane.kratzke@th-luebeck.de>"
ADD web /usr/share/nginx/html/
\ No newline at end of file
FROM ubuntu:18.04
LABEL maintainer="Nane Kratzke <nane.kratzke@th-luebeck.de>"
# Dies lädt die verfügbaren Ubuntu Packages und installiert
# NGINX in einem nicht interaktiven Modus.
RUN apt-get update
RUN apt-get install -y --no-install-recommends nginx
# Add to remove unnecessary package manager data
# RUN apt-get clean
# RUN rm -rf /var/lib/apt/lists/*
# Image Shrinking effect
# - activate to perform all steps ending in one image layer
# - deactivate all RUN commands above
# RUN apt-get update && \
# apt-get install -y --no-install-recommends nginx && \
# apt-get clean && \
# rm -rf /var/lib/apt/lists/*
# Das Webverzeichnis dieses Repos wird in das Container-Image
# kopiert, an der die Ubuntu Stanard NGINX-Installation
# statischen Webcontent ausliefert (Achtung, dieser Pafd ist
# sehr häufig Distributions-spezifisch).
ADD web /var/www/html/
# Der Port 80 (HTTP) wird nach außen exponiert
EXPOSE 80
# Wenn der Container gestartet wird, soll folgendes Kommando ausgeführt
# werden, das letztlich nur den Webserver NGINX wie konfiguriert startet.
ENTRYPOINT ["nginx", "-g", "daemon off;"]
# Achtung in Containern können Sie keine Daemon Prozesse mittels systemd
# (systemctl enable nginx) o. ähnl. starten, da diese in den Hintergrund
# geschickt werden. Der Entry-Prozess wird danach aber weiterlaufen und
# dann terminieren und somit den Container sofort beenden (was bei Servern
# meist nicht gewollt ist). Server-Prozesse müssen Sie in Containern also
# immer in einer "blockierenden" Art starten.
\ No newline at end of file
......@@ -4,17 +4,24 @@ to be done
## Inhalt
- [Übung 1: Installation von Docker](#übung-1-installation-von-docker)
- [Übung 2: Erstellung von einem Image](#übung-2-erstellung-von-einem-image)
- [Übung 3: Image Shrinking](#übung-3-image-shrinking)
- [Übung 4: Push von einem Image in eine Registry](#übung-4-push-von-einem-image-in-eine-registry)
- [Übung 5: Pipeline zum Bau und Test eines Images](#übung-5-pipeline-zum-bau-und-test-eines-umages)
- Deployments to Kubernetes
- Deployments to Serverless Environments
- [Lab 05: Containerization](#lab-05-containerization)
- [Inhalt](#inhalt)
- [Übung 01: Installation von Docker](#übung-01-installation-von-docker)
- [Übung 02: Erstellung von einem Image](#übung-02-erstellung-von-einem-image)
- [Aufgabe 02.1 HTTP-Service mittels eines NGINX-Basisimages](#aufgabe-021-http-service-mittels-eines-nginx-basisimages)
- [Aufgabe 03.2: HTTP-Service mittels eines generellen Basisimages](#aufgabe-032-http-service-mittels-eines-generellen-basisimages)
- [Übung 03: Vergleich von Imagegrößen](#übung-03-vergleich-von-imagegrößen)
- [Aufgabe 03.1: Unnötige Dateien löschen](#aufgabe-031-unnötige-dateien-löschen)
- [Aufgabe 03.2: Image Layer einsparen](#aufgabe-032-image-layer-einsparen)
- [Aufgabe 03.3: Kleinere Basis Images nutzen](#aufgabe-033-kleinere-basis-images-nutzen)
- [Übung 04: Push von einem Image in eine Registry](#übung-04-push-von-einem-image-in-eine-registry)
- [Übung 05: Pipeline zum Bau und Test eines Images](#übung-05-pipeline-zum-bau-und-test-eines-images)
- [Quellen und Referenzen](#quellen-und-referenzen)
- [Was sollten Sie mitnehmen ...](#was-sollten-sie-mitnehmen-)
## Übung 01: Installation von Docker
- [Installieren](https://docs.docker.com/engine/install/) Sie Docker für Ihr System:
- [Installieren](https://docs.docker.com/engine/install/) Sie gem. den verlinkten Anweisungen Docker für Ihr System:
- [Mac](https://www.docker.com/products/docker-desktop)
- [Windows](https://www.docker.com/products/docker-desktop)
- [Linux](https://docs.docker.com/engine/install/)
......@@ -29,10 +36,180 @@ to be done
## Übung 02: Erstellung von einem Image
Sie werden in diesem Teil sehen, wie man Images baut. Häufig benötigt man Images für spezfische Dienste, wie bspw. Datenbanken, Webserver, usw. Hierfür bieten die Hersteller meist vorkonfigurierte Images an, die man nur noch mit einer kleinen Konfiguration (z.B. Access Credentials, Dateipfade, etc.) auf die spezifischen Bedürfnisse anpassen muss. Man kann aber auch Images auf Basis einer Standard Linux-Distribution aufsetzen. Sie werden beides am Beispiel eines kleinen Webservers sehen.
Klonen Sie sich bitte hierzu als Vorbereitung dieses Repository mittels:
```
git clone https://git.mylab.th-luebeck.de/cloud-native/lab-containerization.git
cd lab-containerization
```
### Aufgabe 02.1 HTTP-Service mittels eines NGINX-Basisimages
1. Öffnen Sie nun bitte die Datei `Dockerfile.nginx` (diese ist recht übersichtlich, versuchen Sie diese zu verstehen und nachzuvollziehen)
2. Erzeugen Sie aus dieser nun das für Docker verarbeitete Dockerfile mittles `cp Dockerfile.nginx Dockerfile`.
3. Bauen Sie nun ein Container-Image mittels `docker build -t web:nginx .` (vergessen Sie nicht die Punkt am Ende, der gibt das Current Directory an und ist wichtig!).
4. Prüfen Sie mittels `docker image list web*`, ob Ihr Image gebaut wurde. Sie sollten eine Ausgabe wie folgt (o. ähnl.) erhalten.
```
REPOSITORY TAG IMAGE ID CREATED SIZE
web nginx ca0547d1d208 seconds ago 133MB
```
5. Starten Sie dieses Image nun bitte mittels `docker run -p 8080:80 web:nginx` (Sie binden dadurch Ihren lokalen Port 8080 an den Port 80 des Containers).
6. Prüfen Sie, ob Ihre Website ausgeliefert wird, in dem Sie [http://localhost:8080](http://localhost:8080) aufrufen. Sie sollten dann folgende Webpage sehen.
![screenshot](index.html.png)
7. Beenden Sie den HTTP-Service in dem Sie in Ihre Konsole CTRL-C drücken (Sie senden damit das SIGTERM Signal an den NGINX Server-Prozess und der Container wird terminiert).
Das war ja einfach.
### Aufgabe 03.2: HTTP-Service mittels eines generellen Basisimages
In Fällen von weit verbreiteten Diensten und Produkten wie NGINX, Apache, Redis, Memcached, CouchDB, MySQL, usw. finden sich häufig solche Basisimages der entsprechenden Projekte. Das geht meist sehr schnell und ist unkompliziert, sie verlieren aber auch Kontrolle und Konfigurationsmöglichkeiten. In Fällen spezifischerer Produkte oder selbst geschriebener Software sind Sie sogar ggf. gezwungen selber ein Image zu erstellen und die entsprechende Software darauf zu installieren. Man geht in diesen Fällen üblicherweise von einem Distributions Basis-Image aus (wie bspw. dem Ubuntu 18.04 LTS Image).
Wir wollen nun denselben Service mit einem anderen Image bauen, um diesen generelleren Ansatz zu demonstrieren.
1. `cp Dockerfile.ubuntu Dockerfile`
2. Öffen Sie das `Dockerfile` in einem Editor und versuchen Sie es zu verstehen. Sie sehen es ist etwas länger, als das vorherige Image, aber Sie sollten die Wirkungsweise mittels der Kommentare nachvollziehen können.
3. Bauen Sie nun das Image zu diesem Ubuntu-basierten `Dockerfile` mittels `docker build -t web:ubuntu .`.
4. Prüfen Sie wieder mittels `docker image list web*`, ob Ihr Image gebaut wurde. Sie sollten eine Ausgabe wie folgt (o. ähnl.) erhalten.
```
REPOSITORY TAG IMAGE ID CREATED SIZE
web ubuntu 8032bb56c82d seconds ago 154MB
web nginx ca0547d1d208 minutes ago 133MB
```
5. Starten Sie dieses Image nun bitte mittels `docker run -p 8080:80 web:ubuntu`.
6. Prüfen Sie, ob Ihre Website ausgeliefert wird, in dem Sie [http://localhost:8080](http://localhost:8080) aufrufen. Sie sollten wieder dieselbe Webpage sehen, wie im vorherigen Teil.
## Übung 03: Vergleich von Imagegrößen
Sie haben in Übung 02 einen einfachen Webserver samt Inhalt als Docker Image erzeugt.
- Einmal haben Sie auf dem von NGINX selbst bereitgestellten Image nur Ihren Inhalt (`web`-Verzeichnis) hinzugefügt.
- Im zweiten Fall haben Sie auf Basis eines Ubuntu 18.04 LTS Basis Images auch den Webserver NGINX installiert, den Inhalt hinzugefügt und den Entrypoint für den Container konfiguriert. Das war aufwändiger, Sie hatten aber dadurch letztlich mehr Kontrolle über die Konfiguration.
Sie sehen also, dass bereitgestellte Community-Images häufig komfortabler sind. Doch wie sieht es mit dem Größenbedarf der resultierenden Images aus?
Geben Sie dazu bitte folgendes in Ihrer Shell ein.
```
docker image list web*
```
Dies sollte folgende (o. ähnl.) Ausgabe erzeugen:
```
REPOSITORY TAG IMAGE ID CREATED SIZE
web ubuntu 8032bb56c82d 57 minutes ago 154MB
web nginx ca0547d1d208 14 hours ago 133MB
```
Sie sehen, Ihr selbst gebautes Ubuntu Image ist etwas größer. Das ist nicht wirklich erstaunlich, denn die NGINX Macher wissen vermutlich besser als Sie und ich, wie man eine NGINX-Basisinstallation effizient konfiguriert. Doch Images lassen sich auch "shrinken". Sie sollten sich dazu ins Bewusstsein rufen, dass Container Overlay-Dateisysteme nutzen, und jede Anweisungszeile eines Dockerfiles ein Image-Layer (mit Platzbedarf) erzeugt. Man kann sich das zu nutze machen und Images auf mehrere Arten "kleiner" machen:
1. Indem man für den Betrieb unnötige Dateien nicht in den Layer mit aufnimmt.
2. Indem man unnötige Image-Layer einspart.
3. Und indem man kleinere Basis-Images nutzt.
Die folgenden Aufgaben dienen dazu, Ihnen zu zeigen, was für Effekte diese drei Möglichkeiten auf die resultierenden Imagegrößen haben.
### Aufgabe 03.1: Unnötige Dateien löschen
Wir gehen von unserem `web:ubuntu` Image aus.
1. `cp Dockerfile.ubuntu Dockerfile`
2. Löschen Sie nun unnötige Package Manager Dateien mittels `apt-get clean` und `rm -rf /var/lib/apt/lists/*` in dem Sie die im Dockerfile dafür vorgesehenen Zeilen einkommentieren.
3. Bauen Sie nun ein neues Package mittels `docker build -t web:ubuntu-cleaned .`
4. Lassen Sie sich nun die Größen aller drei Packages mittels `docker image list web*` anzeigen.
Sie sehen, dass dadurch Ihr Image bereits etwas kleiner geworden ist, aber noch größer als das NGINX-Image ist.
### Aufgabe 03.2: Image Layer einsparen
In Linux/UNIX Shells kann man, um zwei Kommandos nacheinander auszuführen, entweder dies
```
cat /file/exists
echo "success"
```
oder dies
```
cat /file/exists && echo "success"
```
schreiben. "Success" wird im zweiten Fall sogar nur dann ausgegeben, wenn das erste Kommando `cat /file/exists` mit einem Exit-Code von 0 (also erfolgreich) beendet werden konnte. Das entspricht exakt der Ausführungsweise sequentiell aufeinander folgender `RUN`-Anweisungen. Mittels des `&&` Operators lassen sich also
mehrere Shell-Kommandos in einer `RUN`-Anweisung eines Dockerfiles unterbringen. Anstatt mehrere `RUN`-Anweisungen (also mehrere Image-Layers) benötigt man so nur eine `RUN`-Anweisung (und erzeugt nur einen Image-Layer).
Dieses __RUN-Chaining__ genannte Prinzip werden wir anwenden und sehen welchen Effekt dies auf Image-Größen haben kann.
1. `cp Dockerfile.ubuntu Dockerfile`
2. Kommentieren Sie nun alle `RUN`-Anweisungen im Dockerfile aus.
3. Kommentieren Sie nun bitte die einzelne `RUN`-Anweisung unter dem `Image Shrinking Effect`-Kommentar ein.
4. Bauen Sie nun ein neues Package mittels `docker build -t web:ubuntu-shrinked .`
5. Lassen Sie sich nun die Größen aller vier Packages mittels `docker image list web*` anzeigen.
Sie sollten etwa folgende (o. ähnl.) Ausgabe erhalten:
```
REPOSITORY TAG IMAGE ID CREATED SIZE
web ubuntu-shrinked f5f33804dcf2 38 minutes ago 117MB
web ubuntu-cleaned 4f345b6cac34 48 minutes ago 147MB
web ubuntu 8032bb56c82d 57 minutes ago 154MB
web nginx ca0547d1d208 14 hours ago 133MB
```
### Aufgabe 03.3: Kleinere Basis Images nutzen
Alle Images haben bislang Größen, die deutlich die 100 MB sprengen. Das ist zwar kleiner als viele VM-Images, aber immer noch recht groß, um ein paar HTML-Seiten von wenigen KBs auszuliefern.
Aus diesem Grund gibt es Linux-Distributionen (Basis-Images), die deutlich kleiner sind, als die Standard-Distributionen. Diese beinhalten nur das absolut Wesentliche (quasi die POSIX-Schnittstelle) eines Linux-Betriebssystems. Hier gibt es mehrere Distributionen, die häufig verwendet werden. Bspw.:
- [Alpine Linux](https://alpinelinux.org)
- [Atomic](https://www.projectatomic.io)
- [Busybox](https://busybox.net)
- [RancherOS](https://rancher.com/rancher-os)
- [Photon](https://vmware.github.io/photon)
Wir werden die Übung 02 nun mit dem Alpine Linux Basis-Image wiederholen und sehen, wie sich diese Distribution auf die Image-Größen auswirkt.
1. `cp Dockerfile.alpine Dockerfile`
2. `docker build -t web:alpline .`
3. Kommentieren Sie dann folgende Zeile im Dockerfile ein: `RUN rm -rf /var/cache/apk/*`
4. `docker build -t web:alpine-cleaned .`
5. Kommentieren Sie nun alle `RUN` Commands im Dockerfile aus.
6. Kommenteren Sie dann das `RUN`-Chaining im Dockerfile ein.
7. `docker build -t web:alpine-shrinked .`
8. Lassen Sie sich nun mittels `docker image list web*` alle Image-Größen im Überblick anzeigen.
Sie sollten nun folgende (o. ähnl.) Ausgabe erhalten:
```
REPOSITORY TAG IMAGE ID CREATED SIZE
web alpine-shrinked 647de3450afe 2 seconds ago ??.??MB
web alpine-cleaned 9a30127f52b1 About a minute ago ??.??MB
web alpine b9f1decf5a22 2 minutes ago ??.??MB
web ubuntu-shrinked f5f33804dcf2 38 minutes ago 117MB
web ubuntu-cleaned 4f345b6cac34 48 minutes ago 147MB
web ubuntu 8032bb56c82d 57 minutes ago 154MB
web nginx ca0547d1d208 14 hours ago 133MB
```
__Beantworten Sie nun die Frage, um wieviel Prozent der Image-Wechsel das resultierende Container-Image reduziert hat?__
Sie können auch gerne prüfen, dass die Images alle laufen, indem Sie diese jeweils mit den folgenden Kommandos starten
```
docker run -p 8080:80 web:alpine
docker run -p 8080:80 web:alpine-cleaned
docker run -p 8080:80 web:alpine-shrinked
```
und danach [http://localhost:8080](http://localhost:8080) aufrufen.
## Übung 04: Push von einem Image in eine Registry
## Übung 05: Pipeline zum Bau und Test eines Images
## Quellen und Referenzen
......@@ -44,5 +221,10 @@ to be done
## Was sollten Sie mitnehmen ...
to be done
1. Mittels der den meisten Distributionen beiliegenden Package Managern ist es über
`RUN`-Commands möglich in Basis-Images beliebige Software komfortabel und "non-interactive" zu installieren.
1. Eigener Code, Content oder Konfigurationen können mittels `ADD`-Commands dem Container-Image hinzugefügt werden (und danach mittels `RUN`-Commands auch kompiliert und installiert werden).
2. Sie können Server-Dienste mittels TCP-Ports nach außen `EXPOSE`n.
3. Über `ENTRYPOINT` können Sie hierzu den Prozess starten, der durch den Container bereitgestellt werden soll (vermeiden Sie dabei Prozesse als Daemons zu starten).
4. Image-Größen lassen sich mittels **RUN-Chaining** und der Wahl kleiner Basis-Images signifikant reduzieren.
server {
listen 0.0.0.0:80;
root /var/www/html;
server_name localhost;
}
server {
listen 0.0.0.0:80;
root /var/www/html;
server_name 127.0.0.1;
}
<!DOCTYPE html>
<html>
<head>
<title>Hello from Docker</title>
<style>
body {
width: 50%;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
background: lightgreen;
}
</style>
</head>
<body>
<h1>Hello from Docker</h1>
<p>Well done! This page is served from inside your</p>
<pre>
## .
## ## ## ==
## ## ## ## ===
/""""""""""""""""\___/ ===
~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ / ===- ~~~
\______ o __/
\ \ __/
\____\______/
| |
__ | __ __ | _ __ _
/ \| / \ / |/ / _\ |
\__/| \__/ \__ |\_ \__ |
</pre>
<p>container.</p>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment