Linux-behållareguide: En introduktion till behållare

Containers har varit ett modeord i flera år... men vad är de exakt?

Behållare är en metod för att köra virtualiserade applikationer på din dator, liknande virtuella maskiner, men med en annan uppsättning underliggande teknologier. De kan vara komplicerade att förstå, men de är viktiga för att driva allt från Minecraft servrar till Google. Och vi kommer att visa dig hur du ställer in dem.

Vi kommer att använda Linux, ett operativsystem byggt med fokus på portabilitet, modularitet och stabilitet. Linux finns i allt från servrar till mikrovågor till videospelskonsoler. Behållare är inte begränsade till att köras på Linux, men tekniken bakom dem är bäst lämpade för och körs bäst på Linux. Om du är ny på Linux rekommenderar vi att du kollar in vår nybörjarguide innan du dyker in.

Är behållare virtuella maskiner?

Behållare kan vara ett komplext ämne, men det är bäst att börja med en viktig punkt: En behållare är inte en virtuell maskin. En virtuell maskin är en simulerad version av specifik hårdvara och dess mjukvara som körs i vad som kallas en hypervisor. Om du någonsin har använt programvara som VirtualBox eller

multipass, då har du använt en hypervisor.

Hypervisorn körs vanligtvis antingen som sitt eget operativsystem (känd som en typ 1 hypervisor) eller inom gränserna för ett annat operativsystem som Windows eller Ubuntu (en typ 2 hypervisor). Hypervisorns ansvar är att presentera gästoperativsystemet med den simulerade hårdvara som krävs för att köras. Hela operativsystemet kan sedan köras ovanpå. Detta inkluderar allt från en simulerad CPU och RAM till databussar, diskenheter eller nätverkskort. Denna simulering är beräkningsmässigt dyr, så virtuella maskiner har vanligtvis betydande omkostnader.

Så, vad är en behållare?

En behållare liknar en virtuell maskin genom att den innehåller och kör programvara i en isolerad miljö på ett värdsystem. Behållare ersätter dock traditionell hårdvaruvirtualisering genom att förlita sig på värdoperativsystemet direkt. Behållare delar biblioteken och binärerna i värdoperativsystemet och har bara de resurser och beroenden som behövs för att köra den specifika applikation de innehåller. Detta innebär att det inte finns något behov av ett fullständigt operativsystem per behållare, eftersom alla behållare körs på en systemet kan dela det enda värdoperativsystemet samtidigt som den segregation du får med virtuella bibehålls maskiner.

Behållare får åtkomst till värdoperativsystemet via en behållaremotor, som hanterar körande behållare och kontrollerar deras åtkomst till det underliggande operativsystemet. Detta kan innefatta att upprätthålla säkerhet mellan behållare och att bevilja eller neka åtkomst till operativsystemfiler eller nätverksanslutningar.

Vad är några avvägningar för att använda behållare?

Medan virtuella maskiner och behållare liknar varandra, har användningen av behållare sina nackdelar. För det första anses virtuella maskiner vara säkrare, eftersom attackytan för att "fly" den virtuella maskinen är betydligt mindre och svårare att penetrera. En behållare kanske inte är lämplig för att testa skadlig programvara, till exempel.

Den största fördelen med att använda containrar är att de är lätta, att undvika behovet av att virtualisera ett helt operativsystem innebär minimala starttider och minskade systemkostnader. Detta innebär att många fler behållare kan köras på en värd, vilket inte skulle vara möjligt med virtuella maskiner.

Eftersom behållare inte kräver ett fullständigt operativsystem kan de enkelt paketeras till mindre bilder och distribueras. Medan en fullständig virtuell maskinbild lätt kan vara tiotals gigabyte, kan behållare komma i bilder så små som 15Kb. Detta gör det extremt enkelt att distribuera och använda behållare. Vi kommer att visa detta genom att köra några enkla exempelbehållare i Docker.

Installerar Docker

Det är mycket teori, så låt oss bli praktiska. För att visa dig hur du ställer in en behållare kommer vi att installera Docker i Ubuntu 23.10 och använda den för att köra en enkel Hello World-behållare. Våra steg är testade på en virtuell maskin, men du kan också dubbelstarta från din Windows-dator eller använda en bra bärbar dator för Linux.

Docker har snabbt blivit det de facto containeriseringsverktyget. Medan andra verktyg finns, är Docker allmänt antagen och är perfekt för alla utom de mest krävande applikationerna. Det finns dokumentation om de olika sätten att installera Docker, men vi kommer att använda skriptet för bekvämlighetsinstallation. Detta kommando kommer att ladda ner ett skript från get.docker.com till din lokala dator:

$ curl -fsSL https://get.docker.com -o get-docker.sh

Du kan sedan köra det här skriptet för att installera Docker. Du kan verifiera att Docker är korrekt installerat genom att kontrollera versionen med:

$ sudo sh ./get-docker.sh

Följt av en versionskontroll med:

$ sudo docker version

Du kan också verifiera att docker-tjänsten körs i bakgrunden med:

$ sudo systemctl status docker

Det bör indikera "aktiv (kör)" i grön text, som markerats i skärmdumpen nedan. Versionen av Docker-motorn bör också skrivas ut utan fel.

Kör ett enkelt exempel

Nu när Docker är installerat kan du använda den för att ladda ner en containeravbildning. Behållarbilder är mycket som ISO: er för virtuella maskiner, förutom att de vanligtvis är mindre och lättare att bygga. Ladda ner en enkel hello-world-containerbild med följande kommando:

$ sudo docker pull hello-world

När den bilden har laddats ner kan du verifiera genom att lista bilderna som laddats ner på ditt system med hjälp av följande:

$ sudo docker images

Du bör nu se hello-world nedladdad. Notera den mycket lilla storleken (13Kb på vår testmaskin), såväl som dess tagg. Taggen för en bild är faktiskt dess version. Som standard kommer Docker att ladda ner den senaste versionen av en bild. Kör en behållare baserat på den här bilden med:

$ sudo docker run hello-world: latest

Detta kommer att mata ut Dockers hello-world-spel, som körs från ett mycket litet C-program (som du kan kolla in på GitHub).

Grattis; du har kört din första container! I det här fallet har programmet matat ut sitt resultat och avslutat sin körning. Containern är nu död och går inte längre.

Hur man håller behållarna vid liv

Efter att ha kört en grundläggande behållare kan vi nu bygga ett mer komplext exempel som inte avslutas omedelbart när det har slutfört en uppgift. Behållare är ofta byggda kring en enda process, vilket kan skapa fler processer. När denna basprocess avslutas kommer hela behållaren att avslutas med den. Detta kan låta som en begränsning, men det är faktiskt väldigt likt hur init-system i hela Linux-kärnan fungerar.

För att köra ett ihärdigt exempel kan vi dra en bild för Nginx, som är en webbserver som används för att vara värd för en betydande andel av världens webbplatser. Vi har valt Nginx för det här exemplet eftersom det är enkelt, kräver ingen avancerad konfiguration och är lätt. Ladda ner den senaste Nginx-bilden med följande kommando:

$ sudo docker pull nginx

Vi har lagt till -s flagga här för att konfigurera portvidarebefordran från behållaren till värdoperativsystemet. Port 80 används för okrypterad HTTP-trafik (dvs. webb). Detta gör att du kan komma åt behållaren från din värddator:

$ sudo docker run -p 80:80 nginx

Detta kommando kommer att köras i din terminal i anslutet läge vilket betyder att behållaren bokstavligen är kopplad till din terminal, så alla loggar från behållaren kommer att skrivas ut där. Öppna behållaren när behållaren har startat http://localhost i din webbläsare. Du kommer att se en Nginx välkomstskärm som liknar nedan:

Nginx-behållaren körs nu inuti din containermotor. Medan Nginx körs i kopplat läge, kommer det bara att fortsätta köras så länge det är öppet. Du kan avsluta Nginx-behållaren genom att trycka på Ctrl + C i din terminal.

Hur man kör behållare i bakgrunden

För att köra Nginx i bakgrunden lägger vi till ytterligare en flagga, -d, för fristående läge. Detta kommer att starta behållaren lossad från din terminal, vilket betyder att den är i bakgrunden. Till exempel:

$ sudo docker run -d -p 80:80 nginx

Du kan lista körande behållare på ett system. Lägg märke till hur din Nginx-behållare nu körs i bakgrunden och har tilldelats ett ID.

$ sudo docker ps

En bakgrundsbehållare som körs kan dödas med dess ID. Du kanske också märker att behållaren har fått ett namn. När en inte specificeras kommer Docker att ge varje container ett slumpmässigt, unikt namn.

$ sudo docker kill 

Du kan dock testa detta med några mer intressanta bilder. Det finns massor tillgängliga över på Docker nav, som fungerar som ett centralt arkiv för offentliga containerbilder.

Dykning djupare med containrar

Detta har varit en kort introduktion till containrar. Behållare kan vara oändligt komplexa, men de är en grundläggande byggsten i de högdistribuerade systemen som driver mycket av vårt moderna internet. Den kraften tar dock inte ifrån deras användning i mindre skala. Förtrogenhet med grunderna för containrar och Docker kan vara inkörsporten till att köra användbara lokala tjänster som en Minecraft-server eller Plex på en gammal PC.