Hur (och varför) kör Docker Inside Docker

0
130

Att köra Docker inuti Docker låter dig bygga bilder och starta behållare i en redan containeriserad miljö. Det finns två möjliga tillvägagångssätt för att uppnå detta beroende på om du vill starta barn- eller syskonbehållare.

Tillgång till Docker inifrån en Docker-container är oftast önskvärt i samband med CI- och CD-system. Det är vanligt att vara värd för agenterna som driver din pipeline i en Docker-container. Du kommer att sluta använda en Docker-in-Docker-strategi om ett av dina pipelinesteg sedan bygger en bild eller interagerar med containrar.

Docker-in-Docker-bilden

Docker tillhandahålls som en fristående bild via docker:dind-taggen på Docker Hub. Att starta den här bilden ger dig en fungerande Docker-demoninstallation i din nya behållare. Den kommer att fungera oberoende av din värds demon som kör dind-behållaren, så docker ps inuti behållaren kommer att ge andra resultat än docker ps på din värd.

docker run -d –privileged –name docker -e DOCKER_TLS_CERTDIR=/certs -v docker-certs-ca:/certs/ca -v docker-certs-client:/certs/client docker:dind

Använda Docker- in-Docker kommer på detta sätt med en stor varning: du måste använda privilegierat läge. Denna begränsning gäller även om du använder rotlösa behållare. Privilegerat läge aktiveras av flaggan –privileged i kommandot som visas ovan.

Att använda privilegierat läge ger behållaren fullständig åtkomst till ditt värdsystem. Detta är nödvändigt i ett Docker-in-Docker-scenario så att din inre Docker kan skapa nya behållare. Det kan dock vara en oacceptabel säkerhetsrisk i vissa miljöer.

Annons

Det finns andra problem med dind också. Vissa system kan uppleva konflikter med Linux Security Modules (LSM) som AppArmor och SELinux. Detta inträffar när den inre Docker tillämpar LSM-policyer som den yttre demonen inte kan förutse.

En annan utmaning gäller containerfilsystem. Den yttre demonen kommer att köras ovanpå din värds vanliga filsystem som ext4. Alla dess behållare, inklusive den inre Docker-demonen, kommer dock att sitta på ett CoW-filsystem (copy-on-write). Detta kan skapa inkompatibiliteter om den inre demonen är konfigurerad att använda en lagringsdrivrutin som inte kan användas ovanpå ett befintligt CoW-filsystem.

Montera din värds dockaruttag istället

Utmaningarna förknippade med dind löses bäst genom att helt undvika användningen av den. I många scenarier kan du uppnå den avsedda effekten genom att montera din värds Docker-socket i en vanlig docker-container:

docker run -d –name docker -v /var/run/docker.sock:/var/run/docker.sock docker:senaste

Docker CLI inuti docker-bilden interagerar med Docker-demonsocket som den hittar på /var/run/docker.sock. Att montera din värds socket på den här sökvägen innebär att docker-kommandon som körs inuti behållaren kommer att köras mot din befintliga Docker-demon.

Detta innebär att behållare som skapats av den inre Docker-enheten kommer att finnas på ditt värdsystem, tillsammans med Docker container själv. Alla behållare kommer att existera som syskon, även om det känns som att den kapslade Docker är ett barn till föräldern. Att köra docker ps ger samma resultat, oavsett om det körs på värden eller inuti din behållare.

Denna teknik mildrar implementeringsutmaningarna för dind. Det tar också bort behovet av att använda privilegierat läge, även om montering av Docker-uttaget i sig är ett potentiellt säkerhetsproblem. Allt med åtkomst till socket kan skicka instruktioner till Docker-demonen, vilket ger möjlighet att starta behållare på din värd, dra bilder eller radera data.

När man ska använda varje metod

Docker-in-Docker via dind har historiskt sett använts flitigt i CI-miljöer. Det betyder det “inre” behållare har ett lager av isolering från värden. En enda CI-runner-behållare stöder varje pipeline-behållare utan att förorena värdens Docker-demon.

Annons

Även om det ofta fungerar, är detta fyllt med biverkningar och inte det avsedda användningsfallet för dind . Den lades till för att underlätta utvecklingen av själva Docker, inte ge slutanvändarstöd för kapslade Docker-installationer.

Enligt Jérôme Petazzoni, skaparen av dind-implementeringen, bör antagandet av den socket-baserade metoden vara din föredragna lösning. Bindmontering av din värds demonsocket är säkrare, mer flexibelt och lika komplett som att starta en dind-container.

Om ditt användningsfall innebär att du absolut behöver dind, finns det ett säkrare sätt att distribuera det. Det moderna Sysbox-projektet är en dedikerad containerruntime som kan kapsla andra körtider utan att använda privilegierat läge. Sysbox-behållare blir VM-liknande så att de kan stödja programvara som vanligtvis körs bara-metal på en fysisk eller virtuell maskin. Detta inkluderar Docker och Kubernetes utan någon speciell konfiguration.

Slutsats

Att köra Docker inom Docker är ett relativt vanligt krav. Det är mest sannolikt att du ser det när du ställer in CI-servrar som måste stödja byggande av containeravbildningar inifrån användarskapade pipelines.

Att använda docker:dind ger dig en oberoende Docker-demon som körs i sin egen behållare. Det skapar effektivt underordnade behållare som inte är direkt synliga från värden. Även om det verkar erbjuda stark isolering, hyser dind faktiskt många problem och säkerhetsproblem. Dessa beror på Dockers operativsystems interaktioner.

Annons

Att montera din värds Docker-socket i en container som inkluderar docker-binären är ett enklare och mer förutsägbart alternativ. Detta låter den kapslade Docker-processen starta behållare som blir sina egna syskon. Inga ytterligare inställningar behövs när du använder den socket-baserade metoden.