Hei alle sammen! I hans Jeg lovet å fortelle deg om å kjøre Docker i Docker og de praktiske aspektene ved å bruke den i denne leksjonen. Det er på tide å oppfylle løftet mitt. En erfaren DevOps ville sannsynligvis innvende at de som trenger Docker i Docker, bare videresender Docker-daemon-socketen fra verten i containeren, og dette vil være nok i 99 % av tilfellene. Men ikke forhast deg med å kaste informasjonskapsler på meg, for vi skal snakke om den virkelige lanseringen av Docker i Docker. Denne løsningen har mange mulige bruksområder, og denne artikkelen handler om ett av dem, så len deg tilbake og strekk armene foran deg.

begynner
Det hele startet en regnfull septemberkveld da jeg rengjorde en leid maskin på Digital Ocean til 5 dollar, som hadde frosset i hjel fordi Docker hadde fylt opp alle 24 gigabyte tilgjengelig diskplass med sine bilder og containere. Ironien var at alle disse bildene og containerne var forbigående og bare var nødvendige for å teste funksjonaliteten til applikasjonen min hver gang en ny versjon av et bibliotek eller rammeverk ble utgitt. Jeg prøvde å skrive shell-skript og sette opp en cron-plan for å rydde opp i søppelet, men det hjalp ikke: hver gang endte det uunngåelig med at serverens diskplass ble spist opp og serveren frøs (i beste fall). På et tidspunkt kom jeg over en artikkel om hvordan man kjører Jenkins i en container og hvordan den kan opprette og slette build-pipelines gjennom en Docker-daemon-socket som sendes inn i den. Jeg likte ideen, men jeg bestemte meg for å gå lenger og prøve å eksperimentere med å kjøre Docker direkte inne i Docker. Det virket som en logisk løsning å laste ned Docker-bilder og opprette containere med alle applikasjonene jeg trenger for testing inne i en annen container (la oss kalle det en staging-container). Ideen var å kjøre staging-containeren med -rm-flagget, som automatisk sletter hele containeren med alt innhold når den stoppes. Jeg lette litt etter Docker-imaget fra selve Docker (), men det viste seg å være for tungvint, og jeg klarte aldri å få det til å fungere slik jeg trengte, og jeg ville gå gjennom hele prosessen selv.
Øvelse. Kjegler
Jeg satte meg som mål å få beholderen til å fungere slik jeg trengte og fortsatte eksperimentene mine, noe som resulterte i utallige støt. Resultatet av min selvtortur var følgende algoritme:
Vi starter Docker-containeren i interaktiv modus.
docker run --privileged -it docker:18.09.6Vær oppmerksom på beholderversjonen, et skritt til høyre eller venstre, og DinD-en din blir til et gresskar. Faktisk går alt i stykker ganske ofte med utgivelsen av en ny versjon.
Vi må komme oss inn i skallet umiddelbart.La oss prøve å finne ut hvilke containere som kjører (Svar: ingen), men la oss kjøre kommandoen uansett:
docker psDu vil bli litt overrasket, men det viser seg at Docker-daemonen ikke engang kjører:
error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such hostLa oss kjøre det selv:
dockerd &En annen ubehagelig overraskelse:
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not foundVi installerer iptables- og bash-pakkene (det er absolutt mer behagelig å jobbe i bash enn i sh):
apk add --no-cache iptables bashLaunch bash. Endelig er vi tilbake i det kjente skallet
La oss prøve å kjøre Docker igjen:
dockerd &Vi burde se et langt ark med logger som 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.sockTrykk Enter. Vi er tilbake i tårnet.
Fra dette tidspunktet kan vi prøve å kjøre andre containere inne i Docker-containeren vår, men hva om vi vil kjøre en annen Docker-container inne i Docker-containeren vår, eller noe går galt og containeren krasjer? Start på nytt.
Egen DinD-beholder og nye eksperimenter
For å unngå å gjenta trinnene ovenfor om og om igjen, opprettet jeg min egen DinD-container:
Det å ha en fungerende DinD-løsning ga meg muligheten til å kjøre Docker rekursivt i Docker og gjøre mer spennende eksperimenter.
Jeg skal nå beskrive et slikt (vellykket) eksperiment med å kjøre MySQL og Nodejs.
De mest utålmodige kan se hvordan det var her

Så, la oss starte:
Kjør DinD i interaktiv modus. I denne versjonen av DinD må vi manuelt tilordne alle porter som barnecontainerne våre kan bruke (jeg jobber allerede med dette).
docker run --privileged -it -p 80:8080 -p 3306:3306 alekslitvinenk/dindVi kommer inn i bashen, hvorfra vi umiddelbart kan begynne å lansere barnecontainere.
Start MySQL:
docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysqlVi kobler oss til databasen på samme måte som vi ville koblet oss til den lokalt. Vi sørger for at alt fungerer.
Vi lanserer den andre containeren:
docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-serverVær oppmerksom på at portkartleggingen her vil være nøyaktig 8080:8080, siden vi allerede har kartlagt port 80 fra verten til den overordnede containeren på port 8080.
Vi går til localhost i nettleseren, og sørger for at serveren svarer «Hei verden!».
I mitt tilfelle viste eksperimentet med nestede Docker-containere seg å være ganske positivt, og jeg vil fortsette å utvikle prosjektet og bruke det til staging. Det virker som om dette er en mye lettere løsning enn de samme Kubernetes og Jenkins X. Men dette er min subjektive mening.
Jeg tror det var alt for dagens artikkel. I neste artikkel skal jeg gå mer i detalj om eksperimenter med rekursiv Docker-oppstart i Docker og montering av kataloger dypt inn i nestede containere.
PS Hvis du synes dette prosjektet er nyttig, gi det en stjerne på GitHub, fork det og fortell det til vennene dine.
Edit1 Rettet feil, fokusert på 2 videoer
Kilde: www.habr.com
