Modul 9 · 9.1
Forstå containere
Modul 9: Docker og docker compose · Læsetid: 10 minutter
Læringsmål: Efter denne lektion kan du forklare, hvad en container er, hvordan den adskiller sig fra en virtuel maskine, hvor en containers data bliver af, og hvornår Docker giver mening på din server.
Centrale begreber: image, container, lag, registry (Docker Hub), tag, digest, namespaces, cgroups, delt kerne, flygtigt filsystem, volume, bind mount, publicering af porte, officielt image
Hvorfor containere?
Forestil dig, at du vil køre en statusside på din VPS, der viser, om dit website virker. Programmet er skrevet i Node.js, kræver en bestemt version af det og derudover et par hundrede biblioteker. Uden containere installerer du det hele på din server, ved siden af din webserver og din database. Et år senere vil du køre et andet program, der kræver en anden Node.js-version. Så begynder puslespillet.
En container løser det. Programmets udvikler leverer programmet sammen med alt, hvad det har brug for, i én pakke: et image. På din server starter du det image som en container. Programmet ser sine egne filer, sin egen Node.js og sine egne biblioteker og kommer ikke i konflikt med resten af din server. Vil du af med det? Fjern containeren og imaget, så er der intet tilbage i /usr eller /etc.
Docker er det mest kendte værktøj til at hente images og køre containere. Der findes alternativer (Podman, containerd selv), men begreberne er de samme overalt.
Image, container og registry
Tre ord, du hele tiden støder på:
- Image: en skrivebeskyttet skabelon med et filsystem (program, biblioteker, indstillinger) og den kommando, der skal starte. Et image er bygget op af lag: et basislag (for eksempel en minimal Debian), oven på det et lag med Node.js, og oven på det programmet. To images med samme basislag deler det lag på din disk.
- Container: en kørende (eller stoppet) instans af et image. Oven på de skrivebeskyttede lag får containeren sit eget tynde skrivelag. Du kan starte ti containere fra ét image.
- Registry: stedet, hvor images ligger, for eksempel Docker Hub (
docker.io) eller GitHubs registry (ghcr.io). Docker henter et image meddocker pull.
Navnet på et image ser sådan ud:
louislam/uptime-kuma:2
caddy:2
vaultwarden/server:latestDelen efter kolonet er tagget: en etiket for en version. Et tag kan ændre sig: caddy:2 peger i dag på et andet build end om tre måneder, så snart der kommer en ny 2.x. Vil du fastlægge præcis, hvilket image du kører, så brug digesten: et fingeraftryk af indholdet, for eksempel caddy@sha256:.... Den ændrer sig aldrig. Tagget latest er bare et navn, som udvikleren vælger; det betyder ikke automatisk "den nyeste stabile version" og er derfor et dårligt valg, hvis du vil vide, hvad der kører.
Ikke en virtuel maskine
En container ligner en lille virtuel maskine, men er det ikke. Den forskel er vigtig for sikkerheden.
| Virtuel maskine (som din VPS) | Container | |
|---|---|---|
| Kerne | Egen kerne | Deler værtens kerne |
| Opstart | Sekunder til minutter, et helt styresystem | Som regel på et sekund, kun programmet |
| Adskillelse | Via hypervisoren, på hardwareniveau | Via kernen: namespaces og cgroups |
| Størrelse | Gigabytes | Ofte fra titals til hundredvis af megabytes |
En container er i bund og grund en almindelig proces på din server, som kernen placerer i et afskærmet miljø:
- namespaces sørger for, at processen har sit eget syn på filer, processer, netværk og brugere. I containeren ser programmet ud til at være proces nummer 1 og kan ikke se resten af din server;
- cgroups begrænser, hvor meget processorkraft og hukommelse den må bruge.
Fordi alle containere deler den samme kerne, er adskillelsen mindre streng end mellem to VPS'er. En sårbarhed i kernen eller en container med for mange rettigheder kan ramme værten. Derfor reglerne i dette modul: kør kun images, du har tillid til, giv ikke containere flere rettigheder end nødvendigt, og mount aldrig /var/run/docker.sock eller / i en container (lektion 9.3 og 10.2).
Hvor bliver dine data af?
Det er den klassiske faldgrube for begyndere. En containers skrivelag er flygtigt: sletter du containeren (for eksempel ved en opdatering, lektion 9.4), er alt, hvad programmet skrev i den, væk. Data, der skal bevares, hører derfor hjemme uden for containeren:
- Volume: et lagersted, som Docker selv administrerer (under
/var/lib/docker/volumes/). Du giver det et navn, for eksempeluptime-kuma, og kobler det til en mappe i containeren:-v uptime-kuma:/app/data. - Bind mount: en almindelig mappe på din server, som du monterer i containeren:
-v /srv/vaultwarden:/data. Praktisk, fordi du kan se filerne direkte og nemt tage dem med i din backup (modul 8).
En container med gode volumes kan du smide væk og oprette igen uden at miste noget. Det er præcis sådan, opdatering fungerer: hent det nye image, fjern den gamle container, start en ny container på de samme volumes. Tag derfor dine volumes med i din backupplan (lektion 8.1).
Publicering af porte
En container har sit eget netværk. Et webprogram, der lytter på port 3001 i containeren, kan ikke nås uden for serveren, før du publicerer porten: -p 3001:3001 (værtsport:containerport). Bemærk: uden en adresse publicerer Docker porten på alle din servers adresser, altså 0.0.0.0 og [::]. Det betyder, at den kan nås fra hele internettet, og Docker ordner det uden om ufw (lektion 9.3). Den sikre vane er at publicere på loopback, -p 127.0.0.1:3001:3001, med en reverse proxy med https foran (lektion 9.4).
Hvem har lavet imaget?
Et image er software fra en anden, som kan køre som root på din server. Tjek derfor, hvem der står bag:
- Docker Official Images (som
caddy,nginx,postgres) vedligeholdes af Docker sammen med udviklerne; - images fra udvikleren selv (som
louislam/uptime-kumaogvaultwarden/server), som du kan genkende på det navn, projektets website angiver; - images fra ukendte med navne, der ligner: brug dem ikke.
Brug altid det navn, der står på projektets officielle website, ikke det første, en søgning giver.
Hvornår ja, hvornår nej?
Docker er praktisk til programmer, som udvikleren leverer som image, til tjenester, du hurtigt vil kunne smide væk eller flytte, og til at køre flere programmer med forskellige krav side om side. Til grundlaget for din server (SSH, firewall, opdateringer) bruger du ikke containere. Og et enkelt website med nginx og PHP fra pakkearkivet (lektion 7.2) fungerer fint uden Docker. En container tilføjer et lag, som du skal forstå og holde opdateret; brug det, når det giver noget.
Opsummering
- Et image er en skrivebeskyttet skabelon i lag; en container er en kørende instans med sit eget skrivelag.
- Containere deler værtens kerne og er afskærmet med namespaces og cgroups: lettere end en VM, men mindre strengt adskilt.
- Skrivelaget er flygtigt: varige data hører hjemme i et volume eller en bind mount, og de hører med i din backup.
- Et tag kan ændre sig, en digest kan ikke;
latestsiger ikke meget. - Publicér porte på 127.0.0.1, og brug kun images fra udvikleren eller officielle images.
Quiz
Opgave
Opgave O9.1: Container eller ej? Vælg to programmer, du vil køre på din server (eller brug Uptime Kuma og et WordPress-site som eksempel). Find for hvert program ud af, om udvikleren leverer et officielt image og under hvilket navn, hvilket tag du ville vælge, hvilken mappe der indeholder de varige data, og hvilken port det lytter på. Forklar derefter, om du ville køre det i en container eller fra pakkearkivet, og hvorfor.
Opgave O9.1: Container eller ej?
Denne opgave laver du selv; ingen tjekker den. Afkryds hvad du har gjort, og markér opgaven som udført.
Uptime Kuma: louislam/uptime-kuma med et versions-tag, data i /app/data, port 3001, publiceret på 127.0.0.1 bag en reverse proxy. Vælg et image fra udvikleren eller et Official Image, med et versions-tag og en navngivet datamappe.
Dine afkrydsninger og noter forbliver kun i denne browser; vi sender dem ingen steder hen. Er du logget ind, gemmer vi kun i Mine kurser, at du har udført opgaven.
Læs mere
- Docker-dokumentation, What is a container?: https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/
- Docker-dokumentation, Volumes: https://docs.docker.com/engine/storage/volumes/
- Docker-dokumentation, Port publishing and mapping: https://docs.docker.com/engine/network/port-publishing/
- Docker Official Images: https://docs.docker.com/docker-hub/repos/manage/trusted-content/official-images/
