Modul 9 · 9.1
Förstå containrar
Modul 9: Docker och docker compose · Lästid: 10 minuter
Lärandemål: Efter den här lektionen kan du förklara vad en container är, hur den skiljer sig från en virtuell maskin, var en containers data finns kvar och när Docker är vettigt på din server.
Nyckelbegrepp: image, container, lager, registry (Docker Hub), tagg, digest, namespaces, cgroups, delad kärna, flyktigt filsystem, volym, bind mount, publicera port, officiell image
Varför containrar?
Säg att du vill köra en statussida på din VPS som visar om din webbplats fungerar. Programmet är skrivet i Node.js, behöver en viss version av det och dessutom ett par hundra bibliotek. Utan containrar installerar du allt det på din server, bredvid din webbserver och din databas. Ett år senare vill du ha ett andra program som behöver en annan Node.js-version. Då börjar pusslandet.
En container löser det. Den som gör programmet levererar det tillsammans med allt det behöver, i ett enda paket: en image. På din server startar du den imagen som en container. Programmet ser sina egna filer, sin egen Node.js, sina egna bibliotek och krockar inte med resten av din server. Vill du bli av med det? Ta bort containern och imagen, så blir ingenting kvar i /usr eller /etc.
Docker är det mest kända verktyget för att hämta images och köra containrar. Det finns alternativ (Podman, containerd självt), men begreppen är desamma överallt.
Image, container och registry
Tre ord som du stöter på hela tiden:
- Image: en skrivskyddad mall med ett filsystem (program, bibliotek, inställningar) och kommandot som ska starta. En image är uppbyggd av lager: ett baslager (till exempel ett naket Debian), ovanpå det ett lager med Node.js och ovanpå det programmet. Två images med samma baslager delar det lagret på din disk.
- Container: ett körande (eller stoppat) exemplar av en image. Ovanpå de skrivskyddade lagren får containern ett eget tunt skrivlager. Du kan starta tio containrar från en och samma image.
- Registry: platsen där images finns, till exempel Docker Hub (
docker.io) eller GitHubs registry (ghcr.io). Docker hämtar en image meddocker pull.
Namnet på en image ser ut så här:
louislam/uptime-kuma:2
caddy:2
vaultwarden/server:latestDelen efter kolonet är taggen: en etikett för en version. En tagg kan ändras: caddy:2 pekar i dag på ett annat bygge än om tre månader, så fort en ny 2.x kommer ut. Vill du låsa exakt vilken image du kör, använd då digesten: ett fingeravtryck av innehållet, till exempel caddy@sha256:.... Den ändras aldrig. Taggen latest är bara ett namn som utvecklaren väljer. Den betyder inte automatiskt "den senaste stabila versionen" och är därför ett dåligt val om du vill veta vad som körs.
Ingen virtuell maskin
En container liknar en liten virtuell maskin, men är det inte. Den skillnaden är viktig för säkerheten.
| Virtuell maskin (som din VPS) | Container | |
|---|---|---|
| Kärna | Egen kärna | Delar värdens kärna |
| Uppstart | Sekunder till minuter, ett helt operativsystem | Oftast inom en sekund, bara programmet |
| Separering | Genom hypervisorn, på hårdvarunivå | Genom kärnan: namespaces och cgroups |
| Storlek | Gigabyte | Ofta tiotals till hundratals megabyte |
En container är i grunden en vanlig process på din server, som kärnan placerar i en avskärmad miljö:
- namespaces ser till att processen har en egen bild av filer, processer, nätverk och användare. I containern ser programmet ut att vara process nummer 1 och ser inte resten av din server;
- cgroups begränsar hur mycket processor och minne den får använda.
Eftersom alla containrar delar samma kärna är separeringen mindre strikt än mellan två VPS:er. En sårbarhet i kärnan eller en container som får för många rättigheter kan drabba värden. Därför gäller reglerna i den här modulen: kör bara images som du litar på, ge inte containrar fler rättigheter än nödvändigt och montera aldrig /var/run/docker.sock eller / i en container (lektion 9.3 och 10.2).
Var hamnar dina data?
Det här är den klassiska fällan för nybörjare. En containers skrivlager är flyktigt: tar du bort containern (till exempel vid en uppdatering, lektion 9.4) försvinner allt som programmet skrev där. Data som ska finnas kvar hör därför hemma utanför containern:
- Volym: en lagringsplats som Docker själv hanterar (under
/var/lib/docker/volumes/). Du ger den ett namn, till exempeluptime-kuma, och kopplar den till en mapp i containern:-v uptime-kuma:/app/data. - Bind mount: en vanlig mapp på din server som du hänger in i containern:
-v /srv/vaultwarden:/data. Praktiskt, eftersom du ser filerna direkt och enkelt får med dem i din säkerhetskopia (modul 8).
En container med bra volymer kan du slänga och skapa på nytt utan att förlora något. Det är precis så uppdatering fungerar: hämta en ny image, ta bort den gamla containern, starta en ny container på samma volymer. Ta därför med volymerna i din plan för säkerhetskopior (lektion 8.1).
Publicera portar
En container har ett eget nätverk. Ett webbprogram som lyssnar på port 3001 i containern går inte att nå utanför servern förrän du publicerar den porten: -p 3001:3001 (värdport:containerport). Observera: utan adress publicerar Docker porten på alla serverns adresser, alltså 0.0.0.0 och [::]. Det betyder att den kan nås från hela internet, och Docker ordnar det förbi ufw (lektion 9.3). Den säkra vanan är att publicera på loopback, -p 127.0.0.1:3001:3001, med en omvänd proxy med https framför (lektion 9.4).
Vem gör imagen?
En image är någon annans programvara som kan köras som root på din server. Kontrollera därför vem som står bakom den:
- Docker Official Images (som
caddy,nginx,postgres) underhålls av Docker tillsammans med utvecklarna; - images från utvecklarna själva (som
louislam/uptime-kumaochvaultwarden/server), som du känner igen på namnet som projektets webbplats anger; - images från okända med namn som liknar dem: använd inte.
Använd alltid namnet som står på projektets officiella webbplats, inte det första som en sökning ger.
När ja, när nej?
Docker är praktiskt för program som utvecklaren levererar som image, för tjänster som du snabbt vill kunna slänga eller flytta och för att köra flera program med olika krav bredvid varandra. För grunden i din server (SSH, brandvägg, uppdateringar) använder du inga containrar. Och en enda webbplats med nginx och PHP från paketkällan (lektion 7.2) fungerar utmärkt utan Docker. En container lägger till ett lager som du måste förstå och hålla uppdaterat. Använd det när det ger något.
Sammanfattning
- En image är en skrivskyddad mall i lager; en container är ett körande exemplar med ett eget skrivlager.
- Containrar delar värdens kärna och avskärmas med namespaces och cgroups: lättare än en VM, men mindre strikt separerade.
- Skrivlagret är flyktigt: beständiga data hör hemma i en volym eller bind mount, och de hör hemma i din säkerhetskopia.
- En tagg kan ändras, en digest inte;
latestsäger lite. - Publicera portar på 127.0.0.1 och använd bara images från utvecklaren eller officiella images.
Quiz
Uppgift
Uppgift O9.1: Container eller inte? Välj två program som du vill köra på din server (eller använd Uptime Kuma och en WordPress-webbplats som exempel). Ta för varje program reda på om utvecklaren levererar en officiell image och under vilket namn, vilken tagg du skulle välja, vilken mapp som innehåller beständiga data och vilken port det lyssnar på. Förklara sedan om du skulle köra det i en container eller från paketkällan, och varför.
Uppgift O9.1: Container eller inte?
Den här uppgiften gör du själv; ingen kontrollerar den. Bocka av vad du har gjort och markera uppgiften som klar.
Uptime Kuma: louislam/uptime-kuma med en versionstagg, data i /app/data, port 3001, publicera på 127.0.0.1 bakom en reverse proxy. Välj en image från utvecklaren eller en Official Image, med en versionstagg och en namngiven datamapp.
Dina bockar och anteckningar sparas bara i den här webbläsaren; vi skickar dem ingenstans. Är du inloggad sparar vi i Mina kurser bara att du har gjort uppgiften.
Läs mer
- Docker-dokumentationen, What is a container?: https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/
- Docker-dokumentationen, Volumes: https://docs.docker.com/engine/storage/volumes/
- Docker-dokumentationen, 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/
