diff --git a/listings/exercises/ex05-networking/commands.sh b/listings/exercises/ex05-networking/commands.sh
new file mode 100755
index 0000000..303f210
--- /dev/null
+++ b/listings/exercises/ex05-networking/commands.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+# Exercise 5 — Container Networking
+
+podman network create appnet
+
+podman run -d --name backend --network appnet nginx:1.27
+podman run -d --name frontend --network appnet -p 8080:80 nginx:1.27
+
+podman network inspect appnet
+
+# Container-to-container (DNS im appnet)
+podman exec -ti frontend curl backend
+
+# Host-to-container (Port-Mapping)
+curl localhost:8080
+
+# Cleanup
+podman rm -f frontend backend
+podman network rm appnet
diff --git a/listings/exercises/ex06-bind-mount/commands.sh b/listings/exercises/ex06-bind-mount/commands.sh
new file mode 100755
index 0000000..dc6f622
--- /dev/null
+++ b/listings/exercises/ex06-bind-mount/commands.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+# Exercise 6 — Bind Mounts
+
+# Terminal 1: write dates to /tmp/output
+podman run -v /tmp:/data --rm -ti busybox \
+ sh -c 'while true; do sleep 1; date >> /data/output; done'
+
+# Terminal 2: watch the output
+podman run -v /tmp:/data --rm busybox tail -f /data/output
+
+# Cleanup
+rm -f /tmp/output
diff --git a/listings/exercises/ex07-named-volume/commands.sh b/listings/exercises/ex07-named-volume/commands.sh
new file mode 100755
index 0000000..57510a4
--- /dev/null
+++ b/listings/exercises/ex07-named-volume/commands.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+# Exercise 7 — Named Volumes (shared between containers)
+
+podman volume create pizza
+
+# Terminal 1: write dates into the volume
+podman run -v pizza:/data --rm -ti busybox \
+ sh -c 'while true; do sleep 1; date >> /data/output; done'
+
+# Terminal 2: watch the output
+podman run -v pizza:/data --rm busybox tail -f /data/output
+
+# Cleanup
+podman volume rm pizza
diff --git a/listings/exercises/ex08-persistence/commands.sh b/listings/exercises/ex08-persistence/commands.sh
new file mode 100755
index 0000000..9a06c55
--- /dev/null
+++ b/listings/exercises/ex08-persistence/commands.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# Exercise 8 — Volume Persistence (data survives container removal)
+
+podman volume create pasta
+
+# Create a file inside the container
+podman run -v pasta:/data --name pasta --rm -ti busybox \
+ sh -c 'touch /data/hello && echo "file created"'
+
+# Container is gone — volume still exists
+podman volume inspect pasta
+
+# New container, same volume (different mountpoint)
+podman run -v pasta:/mnt --name pasta2 --rm -ti busybox \
+ ls -la /mnt
+
+# Cleanup
+podman volume rm pasta
diff --git a/listings/exercises/ex09-env-variables/app.env b/listings/exercises/ex09-env-variables/app.env
new file mode 100644
index 0000000..3382f0d
--- /dev/null
+++ b/listings/exercises/ex09-env-variables/app.env
@@ -0,0 +1,3 @@
+POSTGRES_DB=myapp
+POSTGRES_USER=app
+POSTGRES_PASSWORD=secret
diff --git a/listings/exercises/ex09-env-variables/commands.sh b/listings/exercises/ex09-env-variables/commands.sh
new file mode 100755
index 0000000..835bac7
--- /dev/null
+++ b/listings/exercises/ex09-env-variables/commands.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# Exercise 9 — Environment Variables
+
+# Single variables via -e
+podman run -d --name mydb \
+ -e POSTGRES_DB=myapp \
+ -e POSTGRES_USER=app \
+ -e POSTGRES_PASSWORD=secret \
+ postgres:16-alpine
+
+# Verify
+podman exec -ti mydb psql -U app myapp -c "\l"
+
+podman rm -f mydb
+
+# Via env-file
+podman run -d --name mydb \
+ --env-file app.env \
+ postgres:16-alpine
+
+podman exec -ti mydb psql -U app myapp -c "\l"
+
+# Cleanup
+podman rm -f mydb
diff --git a/listings/exercises/ex10-compose-basic/docker-compose.yml b/listings/exercises/ex10-compose-basic/docker-compose.yml
new file mode 100644
index 0000000..b29f133
--- /dev/null
+++ b/listings/exercises/ex10-compose-basic/docker-compose.yml
@@ -0,0 +1,21 @@
+services:
+ db:
+ image: postgres:16-alpine
+ environment:
+ POSTGRES_DB: myapp
+ POSTGRES_USER: app
+ POSTGRES_PASSWORD: secret
+ networks:
+ - backend
+
+ web:
+ image: nginx:1.27-alpine
+ ports:
+ - "8080:80"
+ depends_on:
+ - db
+ networks:
+ - backend
+
+networks:
+ backend:
diff --git a/listings/exercises/ex11-compose-volume/docker-compose.yml b/listings/exercises/ex11-compose-volume/docker-compose.yml
new file mode 100644
index 0000000..5111b62
--- /dev/null
+++ b/listings/exercises/ex11-compose-volume/docker-compose.yml
@@ -0,0 +1,26 @@
+services:
+ db:
+ image: postgres:16-alpine
+ environment:
+ POSTGRES_DB: myapp
+ POSTGRES_USER: app
+ POSTGRES_PASSWORD: secret
+ volumes:
+ - db-data:/var/lib/postgresql/data
+ networks:
+ - backend
+
+ web:
+ image: nginx:1.27-alpine
+ ports:
+ - "8080:80"
+ depends_on:
+ - db
+ networks:
+ - backend
+
+volumes:
+ db-data:
+
+networks:
+ backend:
diff --git a/listings/exercises/ex12-build-inspect/Containerfile b/listings/exercises/ex12-build-inspect/Containerfile
new file mode 100644
index 0000000..a5d3b0a
--- /dev/null
+++ b/listings/exercises/ex12-build-inspect/Containerfile
@@ -0,0 +1,2 @@
+FROM docker.io/library/nginx:1.27
+COPY index.html /usr/share/nginx/html/index.html
diff --git a/listings/exercises/ex12-build-inspect/docker-compose.yml b/listings/exercises/ex12-build-inspect/docker-compose.yml
new file mode 100644
index 0000000..c15fb62
--- /dev/null
+++ b/listings/exercises/ex12-build-inspect/docker-compose.yml
@@ -0,0 +1,5 @@
+services:
+ nginx:
+ build: ./
+ ports:
+ - "80:80"
diff --git a/listings/exercises/ex12-build-inspect/index.html b/listings/exercises/ex12-build-inspect/index.html
new file mode 100644
index 0000000..de2015e
--- /dev/null
+++ b/listings/exercises/ex12-build-inspect/index.html
@@ -0,0 +1,4 @@
+
+
DEMO
+ Nothing to see here!
+
diff --git a/listings/exercises/ex13-multistage/Containerfile b/listings/exercises/ex13-multistage/Containerfile
new file mode 100644
index 0000000..a2c58f6
--- /dev/null
+++ b/listings/exercises/ex13-multistage/Containerfile
@@ -0,0 +1,8 @@
+FROM golang:1.24-alpine AS build
+WORKDIR /src
+COPY go.mod main.go .
+RUN go build -o /bin/hello .
+
+FROM scratch
+COPY --from=build /bin/hello /bin/hello
+CMD ["/bin/hello"]
diff --git a/listings/exercises/ex13-multistage/go.mod b/listings/exercises/ex13-multistage/go.mod
new file mode 100644
index 0000000..3aade56
--- /dev/null
+++ b/listings/exercises/ex13-multistage/go.mod
@@ -0,0 +1,3 @@
+module hello
+
+go 1.24
diff --git a/listings/exercises/ex13-multistage/main.go b/listings/exercises/ex13-multistage/main.go
new file mode 100644
index 0000000..635db7a
--- /dev/null
+++ b/listings/exercises/ex13-multistage/main.go
@@ -0,0 +1,7 @@
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("hello, world")
+}
diff --git a/listings/exercises/ex14-push/commands.sh b/listings/exercises/ex14-push/commands.sh
new file mode 100755
index 0000000..478bab0
--- /dev/null
+++ b/listings/exercises/ex14-push/commands.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Exercise 14 — Push image to local registry
+
+# Tag and push
+podman build -t localhost:5000/hello:latest .
+# OR tag an existing image:
+# podman tag hello:latest localhost:5000/hello:latest
+
+podman push --tls-verify=false localhost:5000/hello:latest
+
+# Verify
+curl http://localhost:5000/v2/_catalog
+curl http://localhost:5000/v2/hello/tags/list
diff --git a/listings/exercises/ex15-registry-api/commands.sh b/listings/exercises/ex15-registry-api/commands.sh
new file mode 100755
index 0000000..78c27d0
--- /dev/null
+++ b/listings/exercises/ex15-registry-api/commands.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+# Exercise 15 — Query the local registry API
+
+# List all repositories in the registry
+curl http://localhost:5000/v2/_catalog
+
+# List tags for a specific image
+curl http://localhost:5000/v2/hello/tags/list
+
+# Inspect a specific manifest (optional)
+curl http://localhost:5000/v2/hello/manifests/latest \
+ -H "Accept: application/vnd.docker.distribution.manifest.v2+json"
diff --git a/setup/setup-ubuntu2404.sh b/setup/setup-ubuntu2404.sh
new file mode 100755
index 0000000..2532eef
--- /dev/null
+++ b/setup/setup-ubuntu2404.sh
@@ -0,0 +1,150 @@
+#!/bin/bash
+# Container Training — Ubuntu 24.04 (Noble) Setup
+# Als root oder mit sudo ausführen: sudo bash setup-ubuntu2404.sh
+
+set -e
+
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m'
+
+ok() { echo -e "${GREEN}[OK]${NC} $*"; }
+warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
+fail() { echo -e "${RED}[FEHLER]${NC} $*"; exit 1; }
+
+[ "$(id -u)" -eq 0 ] || fail "Bitte als root oder mit sudo ausführen."
+
+# Ubuntu 24.04 prüfen
+if [ -f /etc/os-release ]; then
+ . /etc/os-release
+ if [ "$ID" != "ubuntu" ] || [ "$VERSION_CODENAME" != "noble" ]; then
+ warn "Dieses Script ist für Ubuntu 24.04 (Noble) geschrieben — läuft auf: $PRETTY_NAME"
+ fi
+fi
+
+echo "================================================"
+echo " Container-Schulung — Setup (Ubuntu 24.04)"
+echo "================================================"
+echo ""
+
+# Trainingsuser ermitteln
+TRAINING_USER=${SUDO_USER:-""}
+if [ -z "$TRAINING_USER" ]; then
+ warn "SUDO_USER nicht gesetzt — Linger wird nicht konfiguriert."
+ warn "Ggf. manuell ausführen: loginctl enable-linger "
+fi
+
+# -------------------------------------------------------
+echo ""
+echo "[1/5] Basis-Tools..."
+# -------------------------------------------------------
+apt-get update -q
+apt-get install -y \
+ iputils-ping \
+ iproute2 \
+ net-tools \
+ dnsutils \
+ curl \
+ wget \
+ git \
+ vim \
+ jq \
+ bash-completion
+ok "Basis-Tools installiert."
+
+# -------------------------------------------------------
+echo ""
+echo "[2/5] Podman + rootless-Abhängigkeiten..."
+# -------------------------------------------------------
+# Ubuntu 24.04 liefert Podman >= 4.9 aus dem universe-Repo — kein Fremdrepo nötig
+add-apt-repository -y universe
+apt-get update -q
+apt-get install -y \
+ podman \
+ slirp4netns \
+ fuse-overlayfs \
+ uidmap \
+ dbus-user-session \
+ systemd-container
+
+PODMAN_VER=$(podman --version | awk '{print $3}')
+PODMAN_MINOR=$(echo "$PODMAN_VER" | cut -d. -f2)
+PODMAN_MAJOR=$(echo "$PODMAN_VER" | cut -d. -f1)
+
+if [ "$PODMAN_MAJOR" -gt 4 ] || { [ "$PODMAN_MAJOR" -eq 4 ] && [ "$PODMAN_MINOR" -ge 4 ]; }; then
+ ok "Podman $PODMAN_VER — Quadlets werden unterstützt."
+else
+ warn "Podman $PODMAN_VER — Quadlets brauchen >= 4.4! Tag 3 könnte Probleme machen."
+fi
+
+# -------------------------------------------------------
+echo ""
+echo "[3/5] Registry-Konfiguration..."
+# -------------------------------------------------------
+# Drop-in statt Hauptdatei überschreiben — sauber und updatefest
+mkdir -p /etc/containers/registries.conf.d
+cat > /etc/containers/registries.conf.d/10-unqualified-search.conf << 'EOF'
+# Kurzname-Auflösung: docker.io und quay.io werden automatisch durchsucht
+unqualified-search-registries = ['docker.io', 'quay.io']
+EOF
+ok "unqualified-search-registries konfiguriert (docker.io, quay.io)."
+
+# -------------------------------------------------------
+echo ""
+echo "[4/5] podman-compose + trivy..."
+# -------------------------------------------------------
+apt-get install -y podman-compose 2>/dev/null \
+ || pip3 install --quiet podman-compose
+ok "podman-compose installiert."
+
+# trivy
+curl -fsSL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
+ | sh -s -- -b /usr/local/bin latest
+ok "trivy installiert: $(trivy --version | head -1)"
+
+# -------------------------------------------------------
+echo ""
+echo "[5/5] Benutzer-Setup ($TRAINING_USER)..."
+# -------------------------------------------------------
+if [ -n "$TRAINING_USER" ]; then
+ loginctl enable-linger "$TRAINING_USER"
+ ok "Linger aktiviert für $TRAINING_USER — systemctl --user überlebt Logout."
+
+ # subuid/subgid für rootless Container
+ if ! grep -q "^${TRAINING_USER}:" /etc/subuid 2>/dev/null; then
+ usermod --add-subuids 100000-165535 "$TRAINING_USER"
+ usermod --add-subgids 100000-165535 "$TRAINING_USER"
+ ok "subuid/subgid konfiguriert."
+ else
+ ok "subuid/subgid bereits vorhanden."
+ fi
+
+ # podman socket für den User aktivieren (für podman compose)
+ systemctl enable --now podman.socket 2>/dev/null || true
+ su - "$TRAINING_USER" -c "systemctl --user enable --now podman.socket" 2>/dev/null || true
+ ok "Podman socket aktiviert."
+else
+ warn "Kein Trainingsuser — Linger, subuid/subgid und socket übersprungen."
+fi
+
+# -------------------------------------------------------
+echo ""
+echo "================================================"
+echo " Zusammenfassung"
+echo "================================================"
+podman --version
+podman-compose --version 2>/dev/null | head -1 || true
+trivy --version | head -1
+echo ""
+echo "Registry-Konfiguration:"
+cat /etc/containers/registries.conf.d/10-unqualified-search.conf
+echo ""
+
+if [ -n "$TRAINING_USER" ]; then
+ echo "Benutzer: $TRAINING_USER"
+ echo "Linger: $(loginctl show-user "$TRAINING_USER" --property=Linger --value 2>/dev/null || echo 'unbekannt')"
+fi
+
+echo ""
+ok "Setup abgeschlossen. Bitte einmal aus- und wieder einloggen."