Cum am lansat Docker în Docker și ce a ieșit din asta

Salut tuturor! În cadrul meu articolul anterior, Țin să vă spun despre rularea Docker-ului în Docker și despre aspectele practice ale acestei activități. A sosit momentul să-mi îndeplinesc promisiunea. Un DevOps experimentat ar putea argumenta că pentru cei care au nevoie de Docker în interiorul Docker-ului, se poate pur și simplu să se redirecționeze socket-ul demonului Docker din gazdă în container, iar asta ar fi suficient în 99% din cazuri. Dar nu vă grăbiți să-mi aruncați biscuiți, deoarece vorbim despre o rulare reală a Docker-ului în interiorul Docker-ului. Această soluție are multe aplicații posibile și despre una dintre ele este acest articol, așa că așezați-vă confortabil și întindeți-vă mâinile în fața dumneavoastră.

Cum am lansat Docker în Docker și ce a ieșit din asta

Început

Totul a început într-o seară ploioasă de septembrie, când curățam o mașină închiriată pentru 5$ pe Digital Ocean, care s-a blocat complet deoarece Docker a ocupat toate cele 24 de gigaocteți de spațiu disc disponibil cu imaginile și containerele sale. Ironia era că toate aceste imagini și containere erau tranzitorii și erau necesare doar pentru a testa funcționalitatea aplicației mele de fiecare dată când ieșea o nouă versiune a unei biblioteci sau a unui cadru. Am încercat să scriu scripturi bash și să configurez un program de tip cron pentru a curăța gunoiul, dar asta nu m-a salvat: de fiecare dată, era inevitabil ca spațiul pe disc al serverului meu să fie consumat, iar serverul să se blocheze (în cel mai bun caz). La un moment dat, am dat peste un articol despre cum să rulezi Jenkins într-un container și cum el poate crea și șterge pipe-urile de construcție prin socket-ul redirecționat al demonului Docker. Mie mi-a plăcut ideea, dar am decis să merg mai departe și să încerc să experimentez cu rularea Docker-ului în interiorul Docker-ului. Atunci mi s-a părut o soluție logică să descarc imaginile Docker și să creez containere pentru toate aplicațiile de care aveam nevoie pentru testare în interiorul unui alt container (să-l numim containerul staging). Ideea era să rulez containerul staging cu flag-ul -rm, care șterge automat întregul container cu tot conținutul său la oprire. Am săpat în imaginea Docker a Docker-ului,https://hub.docker.com/_/docker, dar s-a dovedit a fi prea greoaie și nu am reușit să o fac să funcționeze așa cum aveam nevoie și am vrut să parcurg întregul proces singur.

Practică. Bătăi de cap

M-am decis să fac containerul să funcționeze așa cum aveam nevoie și am continuat experimentele mele, rezultatul cărora a fost un număr imens de greșeli. Concluzia autodistanțării mele este următorul algoritm:

  1. Lansăm containerul Docker în modul interactiv.

    docker run --privileged -it docker:18.09.6

    Atenție la versiunea containerului, un pas în dreapta sau în stânga și DinD-ul tău devine o dovleac. De fapt, totul se strică destul de des odată cu lansarea unei noi versiuni.
    Trebuie să ajungem imediat în shell.

  2. Încercăm să aflăm ce containere sunt active (Răspuns: niciunul), dar să executăm comanda oricum:

    docker ps

    Vei fi puțin surprins, dar se pare că demonul Docker nici măcar nu este pornit:

    eroare în timpul conectării: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 
    192.168.65.1:53: nu există un astfel de gazdă

  3. Hai să-l pornim manual:

    dockerd &

    Încă o neplăcere:

    a eșuat să pornească demonul: Eroare la inițializarea controlerului de rețea: eroare obținând instanța controlerului: nu a reușit 
    să creeze lanțul NAT DOCKER: Iptables nu au fost găsite

  4. Instalăm pachetele iptables și bash (în bash este mult mai plăcut să lucrezi decât în sh):

    apk add --no-cache iptables bash

  5. Lansăm bash. În sfârșit, suntem din nou în shell-ul obișnuit

  6. încercăm să lansăm Docker încă o dată:

    dockerd &

    Trebuie să vedem o lungă listă de jurnale care se termină cu:

    INFO[2019-11-25T19:51:19.448080400Z] Demonul a finalizat inițializarea          
    INFO[2019-11-25T19:51:19.474439300Z] API-ul ascultă pe /var/run/docker.sock

  7. Apăsăm Enter. Suntem din nou în bash.

Începând cu acest moment, putem încerca să lansăm alte containere în interiorul containerului nostru Docker, dar ce se întâmplă dacă dorim să ridicăm încă un container Docker în interiorul containerului nostru Docker sau ceva nu va merge bine și containerul „se va cufunda”? Începem din nou.

Containerul nostru propriu DinD și noi experimente

Cum am lansat Docker în Docker și ce a ieșit din asta
Pentru a nu repeta pașii descriși mai sus iar și iar, am creat propriul meu container DinD:

https://github.com/alekslitvinenk/dind

Soluția de lucru DinD mi-a permis să rulez Docker în interiorul Docker-ului în mod recursiv și să fac experimente mai îndrăznețe.
Un astfel de experiment (de succes) cu lansarea MySQL și Nodejs pe care mă pregătesc să-l descriu acum.
Cei mai nerăbdători pot vedea cum a fost aici

Redați video

Așadar, să începem:

  1. Lansăm DinD în modul interactiv. În această versiune DinD, trebuie să mapăm manual toate porturile care ar putea fi utilizate de containerele noastre fiice (lucrez deja la asta)

    docker run --privileged -it 
    -p 80:8080 
    -p 3306:3306 
    alekslitvinenk/dind

    Ajungem în Bash, de unde putem începe imediat să lansăm containerele secundare.

  2. Lansăm MySQL:

    docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql

  3. Ne conectăm la baza de date la fel cum ne-am conecta local. Ne asigurăm că totul funcționează.

  4. Lansăm al doilea container:

    docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server

    Rețineți că port mapping-ul aici va fi exact 8080:8080, deoarece am mapat deja portul 80 de pe host în containerul părinte pe portul 8080.

  5. Accesăm localhost în browser și ne asigurăm că serverul răspunde cu „Hello World!”.

În cazul meu, experimentul cu containere Docker înlănțuite s-a dovedit a fi destul de pozitiv și voi continua să dezvolt proiectul și să-l folosesc pentru staging. Mi se pare că aceasta este o soluție mult mai ușoară decât Kubernetes sau Jenkins X. Dar aceasta este părerea mea subiectivă.

Cred că pentru articolul de astăzi – asta e tot. În următorul articol, voi detalia mai multe experimente cu lansarea recursive a Docker-ului în Docker și montarea directorilor în adâncimea containerelor înlănțuite.

P.S. Dacă considerați că acest proiect este util, vă rog să-i dați o stea pe GitHub, să-l fork-uți și să povestiți prietenilor.

Edit1 Am corectat erorile, am pus accent pe 2 videoclipuri

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster