- Containrar delar kärnan med värden, så deras isolering beror på namnrymder, cgroups och systemhärdning.
- Podman ger extra säkerhet jämfört med klassisk Docker genom att undvika en central root-daemon och underlätta rootless exekvering.
- Brygg-, värdens- och rotlösa nätverk (slirp4netns, paste) i Podman låter dig justera balansen mellan anslutning och isolering.
- Genom att kombinera KVM, containrar och bästa praxis (rootless, MAC, seccomp, bildskanning) skapas en robust plattform för produktion.

När man börjar sätta upp en seriös containermiljö på Linux uppstår omedelbart samma fråga: i vilken utsträckning är det säkert att enbart förlita sig på containrar, och när är det lämpligt att uppgradera till KVM eller mikro-VM? I företagsmiljöer, där Docker, Podman, LXC, virtuella KVM-maskiner och olika hypervisorer blandas, är en gedigen förståelse för isoleringsmodellen nyckeln till att undvika misstag.
Dessutom är något komplexa scenarier inte ovanliga, som att försöka använda Docker Desktop eller Podman i en virtuell maskin i VirtualBox eller KVM , där flera nivåer av virtualisering (kapslade eller inte) spelar in, och det är lätt att stöta på fel som "KVM är inte aktiverat på värden". Låt oss organisera alla dessa delar – containrar, virtuella maskiner, Podman, KVM, nätverk och säkerhet – och se hur man kombinerar dem för att uppnå verkligt säker och praktisk virtualisering.
Klassisk virtualisering med KVM och virtuella maskiner
Grunden för hela denna uppställning är fortfarande den fullständiga virtualiseringen av operativsystem med hjälp av hypervisorer som KVM, Xen eller ESXi . Här kör den fysiska hårdvaran en hypervisor som ansvarar för att "dela upp" maskinen i flera oberoende virtuella maskiner.
I den här modellen startar varje virtuell maskin sin egen kärna och gästoperativsystem , helt separat från värden. Hypervisorn (till exempel KVM, integrerad i Linuxkärnan) fungerar som en grindvakt mellan hårdvaran och de virtuella maskinerna och ansvarar för den starka isoleringen mellan dem.
Vi talar generellt om två typer av hypervisorer: Typ 1- eller bare metal-hypervisorer, som körs direkt på hårdvaran, och Typ 2-hypervisorer, som ligger ovanpå ett befintligt operativsystem. VirtualBox eller VMware Workstation skulle vara Typ 2 , medan en KVM som hanteras av libvirt på en Linux-server ligger närmare ett Typ 1-scenario, även om den delar utrymme med själva värden.
Den största fördelen med den här metoden är att varje virtuell maskin har sin egen kompletta stack: kärna, användarutrymme, tjänster, nätverk och lagring . Detta ger stor flexibilitet och möjligheten att köra olika operativsystem och kärnversioner på samma fysiska maskin.
För att hantera dessa virtualiserade plattformar i GNU/Linux används libvirt nästan alltid som ett orkestrerings-API , utöver vilket grafiska och kommandoradsverktyg stöds, eller större projekt som OpenStack, som bygger kompletta moln genom att kombinera virtuella maskiner, bare metal och containrar.
Hårdvarukrav och vanliga problem med KVM
Innan du kör KVM eller använder lösningar som är beroende av det (som vissa Docker Desktop- eller micro-VM-konfigurationer) måste du se till att processorn stöder hårdvaruvirtualisering (VT-x på Intel eller SVM/AMD-V på AMD) och att det är aktiverat i BIOS/UEFI.
I Linux har vi en snabb kontroll: om kommandot `grep -E 'svm|vmx' /proc/cpuinfo` inte returnerar något, eller om alternativet fortfarande är inaktiverat i firmware, kommer KVM inte att fungera. Dessutom, i scenarier där vi kör virtuella maskiner inuti en annan virtuell maskin (kapslad virtualisering), måste den översta hypervisorn explicit exponera dessa tillägg för gästen.
När något går fel visas typiska meddelanden, till exempel den ökända Docker Desktop-popupen i RHEL 9 i VirtualBox: "KVM är inte aktiverat på värden ." Problemet här ligger inte direkt i Docker eller RHEL, utan snarare i att den virtuella VirtualBox-maskinen inte får de nödvändiga virtualiseringstilläggen för att köra KVM i den.
Kommandon som `modprobe kvm` eller `modprobe kvm_amd / kvm_intel` bör ladda kärnmodulerna utan felmeddelanden. Om `dmesg` inte visar något relevant, eller `lsmod | grep kvm` bara visar en ren `kvm` och `irqbypass`, och de CPU-specifika modulerna saknas, är det mycket troligt att hårdvaruvirtualisering inte exponeras för gästsystemet eller är inaktiverad i den inbyggda programvaran.
I dessa scenarier, även om alla möjliga funktioner är aktiverade i gästmiljön, fungerar KVM helt enkelt inte om VirtualBox inte erbjuder kapslad virtualisering eller om den är felkonfigurerad . Lösningen innebär att granska värdhypervisorns konfiguration (VirtualBox, VMware, etc.) och aktivera kapslad virtualisering om tillgängligt.
Containrar: lätt virtualisering på operativsystemnivå
Till skillnad från traditionella virtuella maskiner erbjuder containrar ett annat tillvägagångssätt: de emulerar inte all hårdvara, utan återanvänder snarare värdkärnan och isolerar processer och resurser med hjälp av Linux-kärnfunktioner.
En container är i huvudsak en uppsättning processer inkapslade med hjälp av namnrymder och cgroups . Inom denna "miljö" tror applikationen att den körs på sin egen maskin, med sitt eget filsystem, nätverksgränssnitt och PID:er, men i verkligheten delar den kärnan med värden.
Containrar erbjuder nästan native prestanda eftersom det inte finns någon andra kärna inblandad och ingen fullständig hårdvaruemulering . Overheadkostnaden är minimal: precis tillräckligt för att montera namnrymder, begränsa resurser med cgroups och upprätthålla säkerhetspolicyer (seccomp, AppArmor, SELinux, etc.).
Denna design har dock en betydande konsekvens: alla arbetsbelastningar delar samma fysiska kärna . En allvarlig sårbarhet i den kärnan kan plötsligt bli en potentiell flyktvektor för alla containrar som körs på den noden.
Det är därför det ofta sägs att containerisolering inte är "absolut" som en virtuell maskin . Om någon lyckas utnyttja en kritisk kärnbugg upphör namnrymder att vara en effektiv barriär, och gränserna mellan containrar och värdar kan brytas.
Namnrymder och cgroups: grunden för containerisolering
I Linux bygger containerisolering på två huvudpelare: namnrymder för att separera systemvyer och cgroups för att begränsa och ta hänsyn till resurser.
Namnrymder isolerar saker som PID, nätverk, monteringspunkter, IPC, värdnamn (UTS) och användare . På så sätt "ser" en process bara processerna, nätverksgränssnitten, filsystemet och värdnamnet för sitt eget namnrymd, vilket ger den känslan av att befinna sig på ett annat system.
Med cgroups kan du ange hur mycket CPU, minne, disk-I/O, antal processer etc. en container kan förbruka . Detta förhindrar att okontrollerad belastning överbelastar hela värden, vilket är viktigt när man delar noder mellan team eller projekt.
Det är dock avgörande att förstå att namnrymder och cgroups i sig inte är ett komplett säkerhetssystem . De förhindrar inte utnyttjandet av kärnsårbarheter, filtrerar systemanrop eller hanterar detaljerade åtkomstpolicyer. De är grunden, men de behöver förstärkas.
Det förnuftiga sättet att härda miljön är att kombinera syscall-filter med seccomp, MAC-policyer (AppArmor eller SELinux) och en drastisk minskning av processkapacitet, helst tillsammans med användarnamnrymder och rotlöst läge för att minimera skador om någon lyckas ta sig ur containern.
Säkerhetshot på containerplattformar
I en riktig containerplattform är attackytan spridd över flera lager: kärnan och runtime (runc, containerd, CRI-O), avbildningsförsörjningskedjan, container-/orkestreringskonfigurationen och den underliggande infrastrukturen (moln, lagring, IAM, nätverk).
Vanliga attackvektorer inkluderar programvarusårbarheter i kärnan eller containerkörningen, användning av osäkra eller ounderhållna avbildningar, konfigurationsfel i Kubernetes eller Docker (privilegierade containrar, farliga värdmonteringar, alltför öppna nätverkslägen) och säkerhetsbrister i register eller CI/CD-pipelines.
I många verkliga incidenter finns det ingen enskild "magisk bugg", utan snarare en kombination av känd sårbarhet plus slapp konfiguration : containrar som körs som root, användning av flaggan --privileged, montering av värdfilsystemet i containern och avsaknad av seccomp eller MAC.
Till allt detta kommer problemet med leveranskedjan: publika basavbildningar innehåller ofta CVE:er, föråldrade paket och dåligt kontrollerade beroenden . Det är relativt lätt för skadlig kod att slinka igenom eller för ett komprometterat bibliotek att förbli vilande tills förutsättningarna är rätt för att det ska kunna köras.
Därför är det inte valfritt i produktion: du måste skanna avbildningar efter sårbarheter med verktyg som Trivy, Clair eller Grype , kontrollera vilka register som används (Harbor, Quay, GHCR med policyer) och signera/verifiera avbildningarna innan du distribuerar dem i ett kluster.
Docker vs Podman: Påverkan på hotmodellen
Inom applikationscontainrar täcker Docker och Podman liknande funktioner, men deras arkitektur skiljer sig avsevärt, och det förändrar säkerhetsmodellen vi arbetar med på en värd.
Docker, i sitt klassiska rootful-läge, förlitar sig på en central daemon (dockerd) som körs som root . CLI kommunicerar med denna daemon via /var/run/docker.sock eller via TCP, och det är denna privilegierade process som skapar och förstör containrar, hanterar avbildningar, nätverk och volymer, och interagerar med register.
Det här innebär att alla med åtkomst till Docker-socketen praktiskt taget har root-åtkomst till värden , eftersom de kan starta privilegierade containrar, montera godtyckliga filsystem och modifiera kritisk konfiguration. Daemonen blir i praktiken en enda felpunkt.
Podman, å andra sidan, föddes med idén att vara en daemonfri containermotor som är så "native" till Linux som möjligt. Det finns ingen permanent central process; containrar styrs av användaren eller av systemd, och integration med det senare gör att containrar kan styras via serviceenheter.
Denna metod stämmer bättre överens med Unix-modellen där "varje process tillhör den användare som startar den" och undviker att förlita sig på en daemon med höga privilegier. Dessutom erbjuder Podman kompatibilitet med Docker-kommandon, vilket förenklar migrering (du kan till och med alias `docker=podman` i miljöer där du inte vill installera Docker CE).
Rootless-läge och användarnamnrymder
Ett av de största praktiska framstegen för att minska effekterna av en potentiell containerescape är rotlöst läge i kombination med användarnamnrymder . Frågan som detta syftar till att besvara är: "Vad händer om containern faktiskt escapear?"
Användarnamnrymder låter dig mappa om containerns UID 0 till ett oprivilegierat UID på värden . Med andra ord, inuti containern tror applikationen att den är root, men ur värdens perspektiv är den processen i själva verket en vanlig användare med ett tilldelat subuid/subgid-intervall.
På så sätt, även om en angripare får root-privilegier inuti containern och lyckas kedja en kernel- eller runtime-exploit, gör de det som en oprivilegierad användare när de återvänder till värden . De kan inte skriva över root-binärfiler, montera känsliga filsystem eller manipulera enheter där de saknar nödvändiga behörigheter.
Podman designades från början med den här modellen i åtanke: rotlös containerisering som standard när det är möjligt , användning av SELinux/AppArmor och cgroups även utan root, och en stark betoning på att minimera strukturella privilegier.
Docker erbjuder nu även ett verkligt rotlöst läge , där dockerd och containrar finns inom ett användarnamnsområde, till skillnad från det äldre userns-remap där daemonen förblev root. Ur säkerhetssynpunkt förhindrar detta att en exploit mot dockerd ger automatisk root-åtkomst till värden.
Containernätverk med Podman: brygga, värd, macvlan och rotlösa gränssnitt
En annan viktig del för säkerhet och praktisk drift är containernätverkslagret . Podman erbjuder olika mekanismer för att tillhandahålla anslutning, med särskild tonvikt på rotlösa scenarier.
Podman 4 introducerade netavark, en nätverksdrivrutin som följer CNI-modellen för att förse containrar med IP-adresser på bryggnätverk, macvlans etc. Med netavark ansluter rootful-containrar vanligtvis som standard till ett nätverk som heter "podman" och är associerat med en Linux-brygga (podman0) på värden, med adresseringen 10.88.0.0/16.
Detta standardbryggnätverk tillhandahåller grundläggande internetanslutning via SNAT-regler och låter dig exponera containerportar för värden med hjälp av `-po --publish`, vilket genererar DNAT-regler i iptables/nftables. För Docker-kompatibilitet kör detta nätverk inte en intern DNS-server.
Vi kan också skapa användardefinierade bryggnätverk , som isolerar grupper av containrar från varandra och tillhandahåller intern DNS. Detta gör det möjligt för containrar att identifieras efter namn inom sitt privata nätverk, gör det enklare att separera tjänster som inte ska kunna se varandra och ger mer kontroll över MTU, brandväggar och andra funktioner.
I mer avancerade miljöer är det möjligt att använda macvlan- eller ipvlan-nätverk för att ansluta containrar direkt till värdens fysiska nätverk. Macvlan tillåter containrar att kommunicera med varandra, medan ipvlan tenderar att isolera dem mer; dessa är användbara alternativ i distributioner där varje container behöver ses som en riktig värd av resten av nätverket.
Rotlösa nätverk: slirp4netns och pasta
När användaren inte är root blir saker komplicerade: en användare utan behörigheter kan inte fritt ändra det globala nätverksnamnutrymmet eller skapa godtyckliga gränssnitt, så Podman måste tillgripa användarutrymmeslösningar för att tillhandahålla anslutning.
Det är här slirp4netns kommer in i bilden , den klassiska mekanismen som används av Podman rootless . Projektet skapar en isolerad nätverksmiljö i containern och använder kärnans slirp-modul för att utföra adressöversättning (NAT) och låta containern komma åt internet via värdens nätverk.
I praktiken skapar slirp4netns ett TAP-gränssnitt inom containerns nätverksnamnrymd (till exempel tap0 med IP 10.0.2.100 och gateway 10.0.2.2) och dirigerar trafik via en TCP/IP-stack implementerad i användarrymden. Det är funktionellt, men lägger till viss overhead och vissa begränsningar.
En av dessa begränsningar är att oprivilegierade användare inte kan använda portar under 1024. Sysctl-parametern net.ipv4.ip_unprivileged_port_start markerar vilken port de anses vara "oprivilegierade" från (som standard 1024), även om detta kan justeras noggrant om säkerhetsmodellen tillåter det.
I Podman 5 ersätts slirp4netns av pasta som standardmekanismen för rotlös data . Pasta fungerar också helt i användarutrymmet, men tack vare tap-gränssnittet och nollkopieringsteknikerna uppnår den nästan nativ nätverksprestanda, vilket minskar påverkan på latens och dataflöde jämfört med slirp4netns.
Brygga och värda nätverk i rotlösa containrar
Även när vi arbetar i icke-root-läge kan vi ansluta rotlösa containrar till standardbryggnätverket "podman" med hjälp av `--network=podman`. Detta utnyttjar netavarks funktioner och mappar portar till värden med `-p`, precis som i rootful-läge.
Det är också möjligt att skapa användardefinierade bryggnätverk i rotlösa miljöer . I det här fallet skapas inte bryggorna och tillhörande enheter i värdens globala nätverksnamnrymd, utan i användarens namnrymd, så dessa gränssnitt kommer inte att synas från värden med ett enkelt `sudo ip a`-kommando.
För att inspektera dessa rotlösa bryggor erbjuder Podman kommandot `podman unshare --rootless-netns` , vilket öppnar ett skal i användarens nätverksnamnrymd. Därifrån kan de interna bryggorna observeras och direkt anslutning till containrarna verifieras.
Denna isolering har en märklig effekt: Det kanske inte finns direkt anslutning från värden till IP-adresserna för dessa rotlösa behållare.men det fungerar med portar mappade till värdens egen IP-adress, vilka fungerar som ingångspunkt till tjänsten.
För kommunikation mellan containrar tillåter DNS-servern som är integrerad i det användardefinierade bryggnätverket dem att tala vid namn, vilket avsevärt förenklar konfigurationen av distribuerade applikationer.
I andra änden finns värdnätverket (--network=host) , där containern delar nätverksstacken med värden utan egen IP-adress. I det här läget, om en rotlös container startar en server på port 8080/tcp, kommer tjänsten att vara direkt tillgänglig på värdens port 8080, vilket sparar portmappning men minskar isoleringen.
Podman Desktop, bildverktyg och lokal orkestrering
För de som föredrar något mer visuellt erbjuder Podman Desktop en grafisk miljö för att hantera containrar, poddar, avbildningar och nätverkskonfigurationer på utvecklingsmaskiner, och fungerar som ett direkt alternativ till Docker Desktop men förlitar sig på den daemonlösa motorn.
Avbildningar hämtas med `podman pull`, som laddar ner från registren definierade i `/etc/containers/registries.conf` . Om avbildningen anges utan ett registernamn försöker Podman hitta den inom den konfigurerade registerordningen, med hjälp av `latest`-taggen som standard.
Utöver Podman CLI kan vi använda skopeo som ett dedikerat verktyg för att hantera, inspektera och kopiera bilder mellan register och lokala arkiv. Kommandon som kopiera, delete och synkronisera låter oss automatisera synkronisering mellan arkiv, markera bilder för sophämtning och flytta artefakter mellan miljöer.
När avbildningen har laddats ner låter `podman run` dig starta containrar genom att ange transport och sökväg (som standard Docker-transport och sökning i det konfigurerade registret). De vanliga alternativen (-d, -p, --name, --pod, etc.) täcker både labscenarier och mer seriösa distributioner.
Daglig hantering utförs med `podman ps` för att lista containrar, `podman stop/start` för att stoppa eller starta befintliga instanser och `podman rm` för att ta bort stoppade containrar . Om en container har modifierats och vi vill konvertera den till en ny avbildning, sparar `podman commit` dessa ändringar under ett nytt namn.
Podar och avancerade exekveringsmodeller med Podman
Inspirerad av Kubernetes låter Podman dig gruppera containrar i poddar som delar samma nätverksstack och vissa resurser . Det är ett perfekt mönster för saker som en databas och dess klient, eller flera mikrotjänster som behöver kommunicera med låg latens.
Kommandot `podman pod create` skapar en ny pod och returnerar dess ID, men som standard förblir poden stoppad tills en associerad container startas eller den explicit startas med `podman pod start`.
För att se vilka poddar som finns i systemet, använd `podman pod ls` , som också listar INFRA-containern som är associerad med var och en. Denna speciella container håller nätverket och andra delade resurser i podden igång, så antalet containrar är aldrig noll.
Podman erbjuder specifika kommandon för att starta, stoppa eller starta om hela poddar (podman pod start/stop/restart) , men vi kan också agera på endast en specifik behållare i podden utan att modifiera resten, vilket bibehåller processisolering på applikationsnivå.
För att lägga till fler containrar till en befintlig pod, använd `podman run --pod POD_NAME` , följ samma syntax som för enskilda containrar. Du kan inte ta bort en container från en pod utan att förstöra den, eftersom pod-medlemskap är knutet till dess livscykel.
Övervakning utförs med podman ps –pod eller specifika kommandon för att övervaka processerna för alla containrar i alla poddar , vilket snabbt identifierar vad som tillhör vilken grupp och hur tjänsterna distribueras.
Containrar, LXC och applikationsvirtualisering
Även om Docker och Podman dominerar diskussionen är de inte de enda containeriseringsalternativen i GNU/Linux . Lösningar som LXC/LXD, systemd-nspawn och Kata Containers tar itu med problemet från lite olika vinklar.
LXC tillhandahåller mycket lätta systemcontainrar, med eget värdnamn, IP-adress, filsystem och komplett init-system . Kombinerat med LXD, som fungerar som en hypervisor för containrar och virtuella maskiner, levererar det en upplevelse som liknar flera lätta maskiner med nästintill bare-metal-prestanda.
Medan Docker/Podman fokuserar på OCI-kompatibla applikationscontainrar , lyser LXC när persistenta miljöer med flera tjänster och processer behövs, och beter sig som en virtuell maskin men med mindre overhead och en mycket naturlig integration med Linuxkärnan.
Ur prestandasynpunkt kan LXC köra dataintensiva företagsapplikationer praktiskt taget utan några problem , vilket gör det till ett kraftfullt val för latenskänsliga arbetsbelastningar som inte kräver den starka isoleringen hos en traditionell virtuell maskin.
Vid sidan av detta har tekniker inriktade på mikro-VMs och förbättrad isolering också fått fäste, såsom Kata Containers , som startar varje pod i en liten virtuell maskin med sin egen kärna, eller gVisor, som infogar en "kärnesandlåda" skriven i Go mellan applikationen och Linux. Båda minskar beroendet av den delade kärnan och närmar sig säkerhetsmodellen för virtuella maskiner samtidigt som användarvänligheten hos containrar bibehålls.
Bästa praxis för att härda Docker och Podman
Med allt ovanstående är den rimliga metoden för en robust containerplattform att arbeta i lager: segmentering med namnrymder/cgroups, filtreringspolicyer med seccomp och MAC, och strukturell privilegiebegränsning genom rootless-läge.
I praktiken är det lämpligt att använda standardmetoden att köra containrar i icke-root-läge när det är möjligt , särskilt i miljöer med flera hyresgäster eller inom delade moln. Podman underlättar detta som standard, och Docker rootless omfattar samma filosofi när kompatibilitet krävs.
Värdkärnan måste hållas uppdaterad med säkerhetsuppdateringar . Sårbarheter som Dirty COW, Dirty Pipe och andra åtgärdas med uppdateringar som måste tillämpas relativt snabbt om vi inte vill lämna dörren öppen för containerläckor.
En annan mycket effektiv åtgärd är att använda oföränderliga, containerorienterade distributioner, såsom openSUSE MicroOS eller Flatcar Linux . Deras skrivskyddade rot- och atomuppdateringssystem minskar attackytan avsevärt och underlättar återställningar om något går fel efter en patch.
Angående konfiguration: inga privilegierade containrar i produktion förutom i extremt kontrollerade fall , kör inte applikationer som root inuti containern, använd skrivskyddade filsystem när det är möjligt och begränsa funktionerna till ett absolut minimum. SELinux/AppArmor- och seccomp-profiler anpassade till applikationens faktiska anrop är praktiskt taget obligatoriska.
Slutligen får vi inte glömma aspekten av runtime-övervakning . Verktyg som Falco, Sysdig Secure eller Aqua hjälper till att upptäcka avvikelser, flyktförsök (som ovanlig åtkomst till /proc eller /sys), atypisk nätverkstrafik eller misstänkta kommandon, vilket ger tid att reagera innan attacken får fäste.
Genom att kombinera klassisk virtualisering med KVM, Podman-hanterade containrar (helst i rotlöst läge), välsegmenterade nätverk och robusta härdningsprocesser kan en mycket flexibel och ganska säker virtualiseringsplattform byggas. Att förstå att den delade kärnan är den mest kritiska punkten, att förlita sig på virtuella maskiner eller mikro-VM när risk eller regelefterlevnad kräver det, och att noggrant hantera avbildningsförsörjningskedjan gör hela skillnaden mellan en labbmiljö och en produktionsklar infrastruktur.