Block 5 – Dockerfiles lesen & verstehen (Optional)
Dauer: ca. 20 Minuten
Ziel: Dockerfiles lesen und verstehen – nicht selbst schreiben, sondern wissen was ein Container macht.
⚡ Dieser Block ist optional – er wird durchgeführt wenn Zeit vorhanden ist.
5.1 Was ist ein Dockerfile?
Ein Dockerfile (auf RHEL auch Containerfile genannt) ist die Bauanleitung für ein Image. Als Sysadmin musst du es nicht selbst schreiben – aber lesen können ist wichtig um zu verstehen warum ein Container so läuft wie er läuft.
# Jede Zeile = ein Layer im Image
FROM ubi9/ubi-minimal # Basis-Image
RUN dnf install -y nginx # Paket installieren → Layer
COPY nginx.conf /etc/nginx/ # Datei kopieren → Layer
EXPOSE 80 # Port dokumentieren (kein Forwarding!)
CMD ["nginx", "-g", "daemon off;"] # Startbefehl
5.2 Die wichtigsten Anweisungen
| Anweisung | Bedeutung | Beispiel |
|---|---|---|
FROM |
Basis-Image | FROM ubi9/ubi-minimal |
RUN |
Befehl beim Bauen ausführen | RUN dnf install -y nginx |
COPY |
Datei ins Image kopieren | COPY index.html /usr/share/nginx/html/ |
ADD |
Wie COPY, entpackt auch Archive | ADD app.tar.gz /opt/ |
EXPOSE |
Port dokumentieren | EXPOSE 80 |
ENV |
Umgebungsvariable setzen | ENV APP_PORT=3000 |
USER |
User für Prozess setzen | USER nginx |
WORKDIR |
Arbeitsverzeichnis setzen | WORKDIR /opt/app |
CMD |
Standardbefehl beim Start | CMD ["nginx", "-g", "daemon off;"] |
ENTRYPOINT |
Fest gesetzter Startbefehl | ENTRYPOINT ["/docker-entrypoint.sh"] |
CMD vs ENTRYPOINT
# CMD kann überschrieben werden:
CMD ["nginx", "-g", "daemon off;"]
# → podman run nginx bash (bash statt nginx)
# ENTRYPOINT wird immer ausgeführt, CMD sind Argumente:
ENTRYPOINT ["/entrypoint.sh"]
CMD ["nginx"]
# → /entrypoint.sh nginx (immer entrypoint.sh)
5.3 Layer-Caching verstehen
Beim Bauen eines Images cached Podman jeden Layer. Ändert sich eine Zeile, werden alle folgenden Layers neu gebaut:
FROM ubi9/ubi-minimal
RUN dnf install -y nginx # Layer 1 – gecacht solange sich nix ändert
COPY nginx.conf /etc/nginx/ # Layer 2 – neu wenn nginx.conf sich ändert
COPY index.html /usr/share/nginx/html/ # Layer 3
"Layer-Caching ist wie
make– nur die Schritte die sich verändert haben, werden neu ausgeführt. Deshalb: Sachen die sich selten ändern (Pakete installieren) an den Anfang, Sachen die sich oft ändern (App-Code) ans Ende."
5.4 Ein Image bauen
# Containerfile erstellen
mkdir -p ~/mein-image && cd ~/mein-image
cat > Containerfile << 'EOF'
FROM docker.io/library/nginx:latest
COPY index.html /usr/share/nginx/html/
EOF
# Eigene index.html
echo "<h1>Mein eigenes Image</h1>" > index.html
# Image bauen
podman build -t mein-nginx:v1 .
# Image anzeigen
podman images | grep mein-nginx
# Container aus eigenem Image starten
podman run -d --name eigenes-nginx -p ${PORT}:80 mein-nginx:v1
curl http://localhost:${PORT}
💡 buildah: Podman verwendet intern
buildahzum Bauen. Im Alltag reichtpodman buildvollständig.
Image-Grösse im Blick behalten
podman images
# Eigenes Image sollte nicht viel grösser sein als Basis
# History zeigt Layer-Grössen
podman history mein-nginx:v1
Häufige Fehler die Images unnötig gross machen:
# Schlecht – Package-Cache bleibt im Layer
RUN dnf install -y nginx
# Besser – Cache bereinigen im gleichen Layer
RUN dnf install -y nginx && dnf clean all
5.5 Environments und Secrets
Umgebungsvariablen
# Beim Start übergeben
podman run -e APP_ENV=production nginx
podman run -e DB_HOST=mydb -e DB_PORT=5432 nginx
# Aus einer Datei laden
cat > ~/app.env << EOF
DB_HOST=mydb
DB_PORT=5432
APP_ENV=production
EOF
podman run --env-file ~/app.env nginx
# Im Container prüfen
podman exec mein-nginx env | grep DB_
"Konfiguration via Umgebungsvariablen statt in Config-Dateien hardcoded – der Container bleibt generisch, die Umgebung macht ihn spezifisch."
Podman Secrets
Für sensitive Daten wie Passwörter:
# Secret erstellen
echo "geheim123" | podman secret create db-password -
# Secret anzeigen (Wert nicht sichtbar!)
podman secret ls
# Container mit Secret starten
podman run -d \
--secret db-password \
--name meine-app \
nginx
# Im Container unter /run/secrets/<name> verfügbar
podman exec meine-app cat /run/secrets/db-password
"Secrets sind sicherer als
-e PASSWORD=...weil sie nicht inpodman inspectoderpsauftauchen."
Übung 5 – Eigenes Image bauen (optional)
Aufgabe 5a – Dockerfile lesen
Schau dir folgendes Dockerfile an und beantworte die Fragen:
FROM docker.io/library/nginx:latest
ENV NGINX_HOST=localhost
RUN mkdir -p /usr/share/nginx/html/app
COPY --chown=nginx:nginx ./html/ /usr/share/nginx/html/app/
EXPOSE 80 443
USER nginx
CMD ["nginx", "-g", "daemon off;"]
Fragen: 1. Welches Basis-Image wird verwendet? 2. Mit welchem User startet nginx? 3. Wohin werden die HTML-Dateien kopiert? 4. Welche Ports werden exponiert?
Aufgabe 5b – Eigenes Image bauen
mkdir -p ~/mein-image && cd ~/mein-image
cat > Containerfile << 'EOF'
FROM docker.io/library/nginx:latest
COPY index.html /usr/share/nginx/html/
EOF
echo "<h1>Gebaut von $(whoami)</h1>" > index.html
podman build -t mein-nginx:v1 .
podman images | grep mein-nginx
podman run -d --name eigenes-nginx -p ${PORT}:80 mein-nginx:v1
curl http://localhost:${PORT}
Musterlösung
5a
docker.io/library/nginx:latestnginx(USER-Anweisung)/usr/share/nginx/html/app/- Port 80 und 443
5b
podman build -t mein-nginx:v1 .
# STEP 1/2: FROM nginx:latest
# STEP 2/2: COPY index.html /usr/share/nginx/html/
# Successfully tagged localhost/mein-nginx:v1
curl http://localhost:${PORT}
# <h1>Gebaut von teilnehmer01!</h1>
Weiterführende Links
| Thema | Link |
|---|---|
| Containerfile Referenz | docs.podman.io – Containerfile |
| Red Hat – Images bauen | access.redhat.com – Building container images |