dhbw: import original web-eng inhalte (testing, typescript, docker, best practices) + framework-übersicht, native html, prüfungsleistung-detail, sose 2026
This commit is contained in:
338
slides/dhbw/07_docker.md
Normal file
338
slides/dhbw/07_docker.md
Normal file
@@ -0,0 +1,338 @@
|
||||
---
|
||||
marp: true
|
||||
theme: gaia
|
||||
paginate: true
|
||||
backgroundColor: #fff
|
||||
header: "Web Engineering – DHBW Stuttgart"
|
||||
footer: "Michael Czechowski – SoSe 2026"
|
||||
title: Docker und Service Orchestration
|
||||
---
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--color-foreground: #1a1a2e;
|
||||
--color-highlight: #005f8a;
|
||||
--color-dimmed: #4a6a7a;
|
||||
}
|
||||
section.invert {
|
||||
--color-foreground: #fff;
|
||||
}
|
||||
section {
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
h1 {
|
||||
color: #005f8a;
|
||||
}
|
||||
section.invert h1 {
|
||||
color: #fff;
|
||||
}
|
||||
pre {
|
||||
background: #0f1e2e;
|
||||
color: #00b4d8;
|
||||
border-radius: 8px;
|
||||
border-left: 3px solid #005f8a;
|
||||
}
|
||||
pre code {
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
}
|
||||
code {
|
||||
background: #1a3a4a;
|
||||
color: #00b4d8;
|
||||
padding: 0.15em 0.4em;
|
||||
border-radius: 4px;
|
||||
}
|
||||
a {
|
||||
color: var(--color-highlight);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- _class: invert -->
|
||||
<!-- _header: '' -->
|
||||
<!-- _backgroundColor: #001520 -->
|
||||
|
||||
# Docker
|
||||
|
||||
## Service Orchestration
|
||||
|
||||
---
|
||||
|
||||
# Inhalt
|
||||
|
||||
1. Architektur: Reverse Proxy + API + DB
|
||||
2. Container vs VM
|
||||
3. `Dockerfile`
|
||||
4. `compose.yml`
|
||||
5. Docker CLI / Compose Befehle
|
||||
6. Live Demo: `dhbw-docker`
|
||||
|
||||
---
|
||||
|
||||
# Architektur
|
||||
|
||||
```
|
||||
Browser (localhost:10007)
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ Reverse Proxy │ (nginx / traefik)
|
||||
└─────────┬────────┘
|
||||
┌────┴────┐
|
||||
▼ ▼
|
||||
┌─────────┐ ┌────────┐
|
||||
│ Web │ │ API │
|
||||
│ App │ │ (Node) │
|
||||
└────┬────┘ └────┬───┘
|
||||
└─────┬──────┘
|
||||
▼
|
||||
┌────────┐
|
||||
│ DB │ (Postgres)
|
||||
└────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Container vs VM
|
||||
|
||||
| | VM | Container |
|
||||
|---|----|-----------|
|
||||
| Kernel | eigener | Host-Kernel |
|
||||
| Boot | Minuten | Sekunden |
|
||||
| Größe | GB | MB |
|
||||
| Isolation | stark | namespaces, cgroups |
|
||||
| Image | komplett | Layer (diff) |
|
||||
|
||||
→ **Docker** = Container-Engine + Image-Format + Registry.
|
||||
|
||||
---
|
||||
|
||||
# Dockerfile – Express API
|
||||
|
||||
```dockerfile
|
||||
FROM node:lts-slim AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY ./package*.json ./
|
||||
RUN npm ci --no-audit --no-fund --no-progress --loglevel=error
|
||||
|
||||
COPY ./ ./
|
||||
|
||||
ENV NODE_ENV="production"
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["npm", "start"]
|
||||
```
|
||||
|
||||
**`npm ci`** statt `npm i` für reproduzierbare Builds.
|
||||
|
||||
---
|
||||
|
||||
# Multi-Stage Build
|
||||
|
||||
```dockerfile
|
||||
FROM node:lts-slim AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
FROM node:lts-slim AS runtime
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY package*.json ./
|
||||
EXPOSE 8080
|
||||
CMD ["node", "dist/index.js"]
|
||||
```
|
||||
|
||||
→ kleines Final-Image, keine Build-Tools im Runtime.
|
||||
|
||||
---
|
||||
|
||||
# .dockerignore
|
||||
|
||||
```
|
||||
node_modules
|
||||
dist
|
||||
.git
|
||||
.env
|
||||
*.log
|
||||
coverage
|
||||
```
|
||||
|
||||
Spart Build-Kontext und verhindert Geheimnis-Leaks.
|
||||
|
||||
---
|
||||
|
||||
# compose.yml – Services
|
||||
|
||||
```yaml
|
||||
name: dhbw-docker-app
|
||||
|
||||
services:
|
||||
api:
|
||||
build: ./api
|
||||
container_name: dhbw-api
|
||||
environment:
|
||||
DATABASE_USERNAME: ${DATABASE_USERNAME}
|
||||
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
|
||||
DATABASE_NAME: ${DATABASE_NAME}
|
||||
DATABASE_HOST: db
|
||||
DATABASE_PORT: 5432
|
||||
ports:
|
||||
- "10000:8080"
|
||||
networks: [net, data]
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# compose.yml – Datenbank + Proxy
|
||||
|
||||
```yaml
|
||||
db:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_USER: ${DATABASE_USERNAME}
|
||||
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
|
||||
POSTGRES_DB: ${DATABASE_NAME}
|
||||
volumes:
|
||||
- dbdata:/var/lib/postgresql/data
|
||||
networks: [data]
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $$DATABASE_USERNAME"]
|
||||
interval: 5s
|
||||
retries: 5
|
||||
|
||||
proxy:
|
||||
image: nginx:alpine
|
||||
ports: ["10007:80"]
|
||||
volumes: ["./nginx.conf:/etc/nginx/nginx.conf:ro"]
|
||||
networks: [net]
|
||||
depends_on: [api]
|
||||
|
||||
volumes:
|
||||
dbdata:
|
||||
|
||||
networks:
|
||||
net:
|
||||
data:
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Docker Compose – Befehle
|
||||
|
||||
```bash
|
||||
docker compose -p "dhbw-docker-app" \
|
||||
-f compose.yml \
|
||||
--env-file .env \
|
||||
up \
|
||||
--build \
|
||||
--remove-orphans \
|
||||
--force-recreate
|
||||
```
|
||||
|
||||
| Flag | Bedeutung |
|
||||
|------|-----------|
|
||||
| `-p` | Projektname |
|
||||
| `-f` | mehrere Compose-Files möglich |
|
||||
| `--env-file` | `.env` einlesen |
|
||||
| `--build` | Images neu bauen |
|
||||
| `--remove-orphans` | verwaiste Container weg |
|
||||
| `--force-recreate` | Container neu starten |
|
||||
|
||||
---
|
||||
|
||||
# Compose – Alltag
|
||||
|
||||
```bash
|
||||
docker compose up -d # detached starten
|
||||
docker compose ps # Status
|
||||
docker compose logs -f api # Logs streamen
|
||||
docker compose exec api sh # Shell im Container
|
||||
docker compose down -v # Stop + Volumes löschen
|
||||
docker compose restart api # Neustart einzelner Service
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Health Checks
|
||||
|
||||
```yaml
|
||||
api:
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
start_period: 5s
|
||||
```
|
||||
|
||||
`depends_on: { condition: service_healthy }` wartet, bis Health passt.
|
||||
|
||||
---
|
||||
|
||||
# Networks: Segmentierung
|
||||
|
||||
- **`net`** – öffentlich erreichbar (Proxy ↔ App)
|
||||
- **`data`** – nur intern (App ↔ DB)
|
||||
- DB ist **nicht** vom Internet erreichbar
|
||||
- Service-DNS: `api`, `db`, `proxy` (Container-Name = Hostname)
|
||||
|
||||
→ Defense in Depth.
|
||||
|
||||
---
|
||||
|
||||
# Volumes – Daten persistent
|
||||
|
||||
```yaml
|
||||
volumes:
|
||||
dbdata: # benannt
|
||||
- ./code:/app # bind mount (dev)
|
||||
- /app/node_modules # anonymous (überschreibt bind)
|
||||
```
|
||||
|
||||
`docker compose down` ohne `-v` lässt Volumes leben.
|
||||
|
||||
---
|
||||
|
||||
# Live Demo
|
||||
|
||||
Repo: https://github.com/nextlevelshit/dhbw-docker
|
||||
|
||||
```bash
|
||||
git clone https://github.com/nextlevelshit/dhbw-docker
|
||||
cd dhbw-docker
|
||||
cp .env.example .env
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
→ http://localhost:10007
|
||||
|
||||
---
|
||||
|
||||
# 100 Concepts of Docker (Exkurs)
|
||||
|
||||
- Image · Container · Volume · Network
|
||||
- Dockerfile · Layer Cache · BuildKit
|
||||
- Compose · Stack · Swarm · Kubernetes
|
||||
- Registry · Tag · Digest
|
||||
- Dev/Prod-Parity (12-Factor)
|
||||
- Secrets · Configs
|
||||
- Logging Drivers
|
||||
- Health Checks · Restart Policies
|
||||
|
||||
---
|
||||
|
||||
<!-- _class: invert -->
|
||||
<!-- _backgroundColor: #001520 -->
|
||||
|
||||
# Fragen?
|
||||
|
||||
**Hausaufgabe:** Eigenes Projekt mit `Dockerfile` + `compose.yml` containerisieren.
|
||||
Reference in New Issue
Block a user