Modul 9 · 9.1
Forstå containere
Modul 9: Docker og docker compose · Lesetid: 10 minutter
Læringsmål: Etter denne leksjonen kan du forklare hva en container er, hvordan den skiller seg fra en virtuell maskin, hvor dataene i en container blir av, og når Docker er nyttig på serveren din.
Nøkkelbegreper: image, container, lag, registry (Docker Hub), tag, digest, namespaces, cgroups, delt kjerne, flyktig filsystem, volum, bind mount, publisere porter, offisielt image
Hvorfor containere?
Tenk deg at du vil kjøre en statusside på VPS-en din som viser om nettstedet ditt fungerer. Programmet er skrevet i Node.js, trenger en bestemt versjon av det, pluss et par hundre biblioteker. Uten containere installerer du alt dette på serveren din, ved siden av webserveren og databasen. Et år senere vil du ha et program til som trenger en annen Node.js-versjon. Da begynner puslespillet.
En container løser dette. Den som har laget programmet, leverer programmet sammen med alt det trenger, i én pakke: et image. På serveren din starter du dette imaget som en container. Programmet ser sine egne filer, sin egen Node.js og sine egne biblioteker, og kommer ikke i konflikt med resten av serveren. Vil du bli kvitt det? Fjern containeren og imaget, så blir det ikke liggende noe igjen i /usr eller /etc.
Docker er det mest kjente verktøyet for å hente images og kjøre containere. Det finnes alternativer (Podman, containerd selv), men begrepene er de samme overalt.
Image, container og registry
Tre ord du kommer til å møte hele tiden:
- Image: en skrivebeskyttet mal med et filsystem (program, biblioteker, innstillinger) og kommandoen som skal starte. Et image er bygd opp av lag: et basislag (for eksempel en naken Debian), oppå det et lag med Node.js, og oppå det programmet. To images med samme basislag deler dette laget på disken din.
- Container: en kjørende (eller stoppet) forekomst av et image. Oppå de skrivebeskyttede lagene får containeren sitt eget tynne skrivelag. Du kan starte ti containere fra ett image.
- Registry: stedet der images ligger, som Docker Hub (
docker.io) eller registryet til GitHub (ghcr.io). Docker henter et image meddocker pull.
Navnet på et image ser slik ut:
louislam/uptime-kuma:2
caddy:2
vaultwarden/server:latestDelen etter kolonet er taggen: en etikett for en versjon. En tag kan endre seg: caddy:2 peker i dag på en annen build enn om tre måneder, så snart en ny 2.x kommer ut. Vil du låse nøyaktig hvilket image du kjører, bruker du digesten: et fingeravtrykk av innholdet, som caddy@sha256:.... Den endrer seg aldri. Taggen latest er bare et navn som utvikleren velger. Den betyr ikke automatisk "den nyeste stabile versjonen", og er derfor et dårlig valg hvis du vil vite hva som kjører.
Ikke en virtuell maskin
En container ligner en liten virtuell maskin, men er det ikke. Denne forskjellen er viktig for sikkerheten.
| Virtuell maskin (som VPS-en din) | Container | |
|---|---|---|
| Kjerne | Egen kjerne | Deler kjernen med verten |
| Oppstart | Sekunder til minutter, et helt operativsystem | Vanligvis på et sekund, bare programmet |
| Isolasjon | Via hypervisoren, på maskinvarenivå | Via kjernen: namespaces og cgroups |
| Størrelse | Gigabyte | Ofte titalls til hundrevis av megabyte |
En container er egentlig en vanlig prosess på serveren din, som kjernen plasserer i et avskjermet miljø:
- namespaces sørger for at prosessen har sitt eget syn på filer, prosesser, nettverk og brukere. Inne i containeren ser programmet ut til å være prosess nummer 1, og det ser ikke resten av serveren;
- cgroups begrenser hvor mye prosessor og minne den får bruke.
Fordi alle containere deler samme kjerne, er isolasjonen mindre streng enn mellom to VPS-er. En sårbarhet i kjernen eller en container som får for mange rettigheter, kan ramme verten. Derfor gjelder reglene i denne modulen: kjør bare images du stoler på, gi ikke containere flere rettigheter enn nødvendig, og mount aldri /var/run/docker.sock eller / i en container (leksjon 9.3 og 10.2).
Hvor blir dataene dine av?
Dette er den klassiske fellen for nybegynnere. Skrivelaget i en container er flyktig: sletter du containeren (for eksempel ved en oppdatering, leksjon 9.4), er alt programmet skrev der borte. Data som skal bli værende, hører derfor hjemme utenfor containeren:
- Volum: et lagringssted som Docker selv administrerer (under
/var/lib/docker/volumes/). Du gir det et navn, for eksempeluptime-kuma, og kobler det til en mappe i containeren:-v uptime-kuma:/app/data. - Bind mount: en vanlig mappe på serveren din som du henger inn i containeren:
-v /srv/vaultwarden:/data. Praktisk fordi du ser filene direkte og enkelt tar dem med i sikkerhetskopien (modul 8).
En container med gode volumer kan du kaste og lage på nytt uten å miste noe. Det er nettopp slik oppdatering fungerer: hent nytt image, fjern den gamle containeren, start en ny container på de samme volumene. Ta derfor volumene med i sikkerhetskopiplanen din (leksjon 8.1).
Publisere porter
En container har sitt eget nettverk. Et webprogram som lytter på port 3001 i containeren, kan ikke nås utenfra serveren før du publiserer porten: -p 3001:3001 (vertsport:containerport). Merk: uten adresse publiserer Docker porten på alle adressene til serveren, altså 0.0.0.0 og [::]. Det betyr at den kan nås fra hele internett, og Docker ordner dette utenom ufw (leksjon 9.3). Den trygge vanen er å publisere på loopback, -p 127.0.0.1:3001:3001, med en reverse proxy med https foran (leksjon 9.4).
Hvem lager imaget?
Et image er programvare fra noen andre som kan kjøre som root på serveren din. Sjekk derfor hvem som har laget det:
- Docker Official Images (som
caddy,nginx,postgres) vedlikeholdes av Docker sammen med utviklerne; - images fra utvikleren selv (som
louislam/uptime-kumaogvaultwarden/server), som du kjenner igjen på navnet prosjektets nettsted oppgir; - images fra ukjente med navn som ligner: ikke bruk dem.
Bruk alltid navnet som står på det offisielle nettstedet til prosjektet, ikke det første et søk gir deg.
Når passer det, og når ikke?
Docker er nyttig for programmer som utvikleren leverer som image, for tjenester du raskt vil kunne kaste eller flytte, og for å kjøre flere programmer med ulike krav side om side. For grunnmuren på serveren din (SSH, brannmur, oppdateringer) bruker du ikke containere. Og ett enkelt nettsted med nginx og PHP fra pakkekilden (leksjon 7.2) fungerer fint uten Docker. En container legger til et lag du må forstå og holde oppdatert. Bruk det når det gir noe tilbake.
Sammendrag
- Et image er en skrivebeskyttet mal i lag. En container er en kjørende forekomst med sitt eget skrivelag.
- Containere deler kjernen med verten og er avskjermet med namespaces og cgroups: lettere enn en VM, men mindre strengt isolert.
- Skrivelaget er flyktig: varige data hører hjemme i et volum eller en bind mount, og de hører hjemme i sikkerhetskopien din.
- En tag kan endre seg, en digest ikke.
latestsier lite. - Publiser porter på 127.0.0.1 og bruk bare images fra utvikleren eller offisielle images.
Quiz
Oppgave
Oppgave O9.1: Container eller ikke? Velg to programmer du vil kjøre på serveren din (eller bruk Uptime Kuma og et WordPress-nettsted som eksempel). Finn ut for hvert program om utvikleren leverer et offisielt image og under hvilket navn, hvilken tag du ville valgt, hvilken mappe som inneholder de varige dataene, og hvilken port det lytter på. Forklar deretter om du ville kjørt det i en container eller fra pakkekilden, og hvorfor.
Oppgave O9.1: Container eller ikke?
Denne oppgaven gjør du selv; ingen kontrollerer den. Kryss av det du har gjort, og merk oppgaven som fullført.
Uptime Kuma: louislam/uptime-kuma med en versjonstagg, data i /app/data, port 3001, publiser på 127.0.0.1 bak en reverse proxy. Velg et image fra utvikleren eller et Official Image, med en versjonstagg og en navngitt datamappe.
Avkrysningene og notatene dine blir kun i denne nettleseren; vi sender dem ikke noe sted. Er du logget inn, lagrer vi kun i Mine kurs at du har gjort oppgaven.
Les mer
- Docker-dokumentasjonen, What is a container?: https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/
- Docker-dokumentasjonen, Volumes: https://docs.docker.com/engine/storage/volumes/
- Docker-dokumentasjonen, 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/
