Hej alle sammen! I min , jeg lovede at fortælle om at køre Docker i Docker og de praktiske aspekter ved at anvende dette koncept. Nu er det tid til at indfri mit løfte. En erfaren DevOps-udvikler vil muligvis indvende, at de, der har brug for Docker inden i Docker, blot kan videregive Docker demonens socket fra værten ind i containeren, og det er tilstrækkeligt i 99% af tilfældene. Men vent med at kaste småkager efter mig, for vi taler her om reel drift af Docker inden i Docker. Denne løsning har mange potentielle anvendelsesområder, og denne artikel handler om et af dem, så læn dig tilbage og stræk hænderne ud foran dig.

Start
Det hele begyndte en regnfuld septemberaften, da jeg rensede en lejet maskine til $5 på Digital Ocean, som var låst fast, fordi Docker fyldte alle 24 gigabyte tilgængelig diskplads med sine billeder og containere. Ironien var, at alle disse billeder og containere var midlertidige og kun blev brugt til at teste min applikations funktionalitet hver gang der kom en ny version af en hvilken som helst bibliotek eller framework. Jeg forsøgte at skrive shell-scripts og indstille cron-job til at rydde op, men det reddede ikke situationen: hvert gang endte det uundgåeligt med, at min servers diskplads blev opbrugt, og serveren låste sig (i bedste fald). På et tidspunkt stødte jeg på en artikel om hvordan man kører Jenkins i en container, og hvordan det kan oprette og slette bygge-pipelines via den videregivne Docker demon socket. Ideen appellerede til mig, men jeg besluttede at gå længere og forsøge at eksperimentere med direkte kørsel af Docker inden i Docker. På det tidspunkt syntes det logisk at hente Docker-billeder og oprette containere til alle de applikationer, jeg havde brug for til test, inde i en anden container (lad os kalde den staging container). Ideen var at starte staging containeren med flaget -rm, som automatisk fjerner hele containeren med alt dens indhold, når den stoppes. Jeg kiggede på Docker-billedet fra Docker selv (), men det viste sig at være for omfangsrigt, og jeg kunne ikke få det til at fungere, som jeg ønskede, og jeg ville gerne gennemgå hele processen selv.
Praksis. Udfordringer.
Jeg satte mig for at få containeren til at fungere, som jeg ønskede, og fortsatte med mine eksperimenter, hvilket resulterede i et stort antal skader. Resultatet af min selvplage blev følgende algoritme:
Lad os starte Docker-containeren i interaktiv tilstand.
docker run --privileged -it docker:18.09.6Bemærk versionen af containeren; et skridt til højre eller venstre, og din DinD bliver til et græskar. Faktisk går alt ofte i stykker med nye versioner.
Vi skal straks ind i shell.Lad os finde ud af, hvilke containere der kører (Svar: ingen), men lad os udføre kommandoen alligevel:
docker psDu vil blive lidt overrasket, men det viser sig, at Docker-dæmonen slet ikke kører:
error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such hostLad os starte den selv:
dockerd &Endnu en ubehagelig overraskelse:
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not foundVi installerer pakkerne iptables og bash (det er sjovere at arbejde i bash end i sh):
apk add --no-cache iptables bashLad os starte bash. Endelig er vi tilbage i den velkendte shell.
Lad os prøve at starte Docker igen:
dockerd &Vi skal se en lang række logs, der slutter 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.sockTryk på Enter. Vi er tilbage i bash.
Fra dette øjeblik kan vi begynde at prøve at starte andre containere inde i vores Docker-container, men hvad nu hvis vi vil starte endnu en Docker-container inden i vores Docker-container, eller hvis noget går galt, og containeren 'crasher'? Vi starter forfra.
Egen DinD-container og nye eksperimenter
For ikke at skulle gentage de ovenfor beskrevne trin igen og igen, har jeg lavet min egen DinD-container:
Den funktionelle DinD-løsning gav mig mulighed for at køre Docker inde i Docker rekursivt og udføre mere dristige eksperimenter.
Jeg vil nu beskrive et sådant (heldigt) eksperiment med at køre MySQL og Node.js.
De mest utålmodige kan se, hvordan det gik her.

Så lad os komme i gang:
Vi starter DinD i interaktiv tilstand. I denne version af DinD skal vi manuelt mappe alle de porte, som vores underliggende containere kan bruge (jeg arbejder allerede på det).
docker run --privileged -it -p 80:8080 -p 3306:3306 alekslitvinenk/dindVi får adgang til bash, hvorfra vi straks kan begynde at starte undercontainere.
Vi starter MySQL:
docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysqlVi opretter forbindelse til databasen, ligesom vi ville have gjort lokalt. Vi sikrer os, at alt fungerer.
Vi starter den anden container:
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-serverBemærk, at portmappingen her vil være præcis 8080:8080, da vi allerede har mappet port 80 fra værten til den overordnede container på port 8080.
Vi går til localhost i browseren og sikrer os, at serveren svarer "Hello World!".
I mit tilfælde var eksperimentet med indlejrede Docker-containere ret positivt, og jeg vil fortsætte med at udvikle projektet og bruge det til staging. Jeg mener, at det er en langt lettere løsning end f.eks. Kubernetes og Jenkins X. Men det er min subjektive mening.
Jeg tænker, at det er alt for denne artikel. I den næste artikel vil jeg mere detaljeret beskrive eksperimenterne med rekursivt at køre Docker i Docker og montere biblioteker dybt ind i de indlejrede containere.
P.S. Hvis du finder dette projekt nyttigt, så giv det venligst en stjerne på GitHub, lav en fork og fortæl dine venner.
Edit1 Jeg har rettet fejl og fokuseret på 2 videoer.
Kilde: habr.com
