Hej alla! I min , jag lovade att berÀtta om att köra Docker i Docker och de praktiska aspekterna av denna aktivitet. Det Àr dags att hÄlla mitt löfte. En erfaren DevOps kanske invÀnder att de som behöver Docker inuti Docker bara vidarebefordrar Docker daemon-socket frÄn vÀrden in i containern och att detta rÀcker i 99 % av fallen. Men skynda er inte att kasta kakor pÄ mig, för det handlar om att faktiskt köra Docker inuti Docker. Denna lösning har mÄnga potentiella anvÀndningsomrÄden, och denna artikel handlar om ett av dem, sÄ sÀtt er bekvÀmt och strÀck ut hÀnderna framför er.

Början
Allt började en regnig söndagskvÀll nÀr jag rensade en hyrbil för $5 pÄ Digital Ocean, som helt hade hÀngt sig eftersom Docker hade fyllt ut alla 24 gigabyte tillgÀngligt diskutrymme med sina bilder och containrar. Irin var att alla dessa bilder och containrar var tillfÀlliga och behövdes bara för att testa min applikations funktionalitet varje gÄng en ny version av nÄgon bibliotek eller ramverk slÀpptes. Jag försökte skriva shell-skript och schemalÀgga cron-jobb för att rensa skrÀpet, men det hjÀlpte inte: varje gÄng slutade det oundvikligen med att mitt servers diskutrymme var uppÀtet och servern hÀngde sig (i bÀsta fall). Vid ett tillfÀlle snubblade jag över en artikel om hur man kör Jenkins i en container och hur den kan skapa och ta bort byggkonvejer via den vidarebefordrade Docker daemon-socketen. Idén tilltalade mig, men jag beslutade att gÄ lÀngre och experimentera med att köra Docker direkt inuti Docker. Det verkade logiskt att ladda ner Docker-bilder och skapa containrar för alla applikationer jag behövde för tester inuti en annan container (lÄt oss kalla det staging-container). Idén var att köra staging-containern med flaggan -rm, vilket automatiskt tar bort hela containern med allt dess innehÄll nÀr den stoppas. Jag grÀvde i Docker-bilden av sjÀlva Docker,, men den visade sig vara för otymplig och jag kunde inte fÄ den att fungera som jag ville, och jag ville gÄ hela vÀgen sjÀlv.
Praktik. Knoppar
Jag hade som mÄl att fÄ containern att fungera som jag ville och fortsatte mina experiment, vilket resulterade i ett otaliga misslyckanden. Resultatet av mina plÄgor blev följande algoritm:
Starta Docker-containern i interaktivt lÀge.
docker run --privileged -it docker:18.09.6Observera versionen av containern, ett steg Ät höger eller vÀnster och din DinD förvandlas till en pumpa. Faktum Àr att allt gÄr sönder ganska ofta med nya versioner.
Vi mÄste omedelbart komma in i shell.Vi försöker ta reda pÄ vilka containrar som körs (Svar: inga), men lÄt oss ÀndÄ köra kommandot:
docker psDu kommer att bli lite förvÄnad, men det visar sig att Docker-demon inte ens Àr igÄng:
error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such hostLÄt oss starta den sjÀlva:
dockerd &Ănnu en otrevlig överraskning:
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not foundInstallerar paketen iptables och bash (det Àr alltid trevligare att arbeta i bash Àn i sh):
apk add --no-cache iptables bashStartar bash. Ăntligen Ă€r vi tillbaka i vĂ„rt vanliga shell
vi försöker starta Docker igen:
dockerd &Vi bör se en lÄng strÀng av loggar som slutar med:
INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sockTryck pÄ Enter. Vi Àr tillbaka i bash.
FrÄn och med nu kan vi försöka köra andra containrar inom vÄr Docker-container, men vad hÀnder om vi vill starta Ànnu en Docker-container inom vÄr Docker-container eller om nÄgot gÄr fel och containern "flyger ut"? DÄ fÄr vi börja om frÄn början.
Egen DinD-container och nya experiment
För att undvika att upprepa ovanstÄende steg om och om igen har jag skapat en egen DinD-container:
En fungerande DinD-lösning gav mig möjligheten att köra Docker inuti Docker rekursivt och genomföra mer djÀrva experiment.
Ett sÄdant (lyckat) experiment med att köra MySQL och Nodejs kommer jag nu att beskriva.
De mest otÄliga kan se hur det gick till hÀr

SÄ lÄt oss börja:
Starta DinD i interaktivt lÀge. I denna version av DinD behöver vi manuellt mappa alla portar som vÄra underordnade containrar kan anvÀnda (detta arbetar jag redan med)
docker run --privileged -it -p 80:8080 -p 3306:3306 alekslitvinenk/dindVi gÄr in i bash, dÀr vi omedelbart kan börja starta underbehÄllare.
Startar MySQL:
docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysqlVi ansluter till databasen precis som vi skulle göra lokalt. Vi ser till att allt fungerar.
Startar den andra containern:
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-serverObservera att portmappningen hÀr kommer att vara just 8080:8080, eftersom vi redan har mappar port 80 frÄn vÀrden till den överordnade containern pÄ port 8080.
GÄ till localhost i webblÀsaren och se till att servern svarar "Hello World!".
I mitt fall har experimentet med inbÀddade Docker-containrar varit ganska positivt och jag kommer att fortsÀtta utveckla projektet och anvÀnda det för staging. Jag tycker att detta Àr en mycket lÀttare lösning Àn Kubernetes och Jenkins X. Men det Àr min subjektiva Äsikt.
Jag tror att det rÀcker för dagens artikel. I nÀsta artikel kommer jag att beskriva experimenten med rekursiv Docker-startning och montering av kataloger i djupet av inbÀddade containrar mer detaljerat.
P.S. Om du tycker att detta projekt Àr anvÀndbart, vÀnligen ge det ett stjÀrna pÄ GitHub, gör en fork och berÀtta för dina vÀnner.
Edit1 Har fixat felen, fokuserat pÄ 2 videor
KĂ€lla: habr.com
