Containerele Docker sunt în creștere ca o bună practică pentru implementarea și gestionarea sistemelor distribuite în nori cloud. Containerele sunt exemple de imagini Docker. Se pare că există multe de știut și de înțeles despre imagini.
În acest tutorial în două părți voi acoperi în profunzime imaginile Docker. În această parte, voi începe cu principiile de bază și apoi voi continua să proiectez examinarea și inspectarea imaginilor interne. În partea a doua, voi acoperi construirea propriilor imagini, depanare și lucrul cu arhivele de imagini.
Când ieșiți pe cealaltă parte, veți avea o înțelegere solidă a ceea ce sunt exact imaginile Docker și cum să le utilizați eficient în propriile aplicații și sisteme.
Docker gestionează imaginile utilizând un driver de stocare din spate. Există mai multe drivere acceptate, cum ar fi AUFS, BTRFS și suprapuneri. Imaginile sunt realizate din straturi comandate. Vă puteți gândi la un strat ca la un set de modificări ale sistemului de fișiere. Când luați toate straturile și le strângeți împreună, veți obține o nouă imagine care conține toate modificările acumulate.
Partea comandată este importantă. Dacă adăugați un fișier într-un singur strat și îl eliminați într-un alt strat, ar fi bine să îl faceți în ordinea corectă. Docker urmărește fiecare strat. O imagine poate fi compusă din zeci de straturi (limita actuală este de 127). Fiecare strat este foarte ușor. Beneficiul straturilor este că imaginile pot partaja straturi.
Dacă aveți o mulțime de imagini bazate pe straturi similare, cum ar fi OS de bază sau pachete comune, atunci toate aceste straturi comune vor fi stocate doar o singură dată, iar suprafata pe imagine va fi doar straturile unice ale acelei imagini.
Atunci când un nou container este creat dintr-o imagine, toate straturile de imagini sunt doar pentru citire și un strat subțire de citire și scriere este adăugat în partea superioară. Toate modificările aduse containerului specific sunt stocate în acel strat.
Acum, aceasta nu înseamnă că containerul nu poate modifica fișiere din stratul său de imagine. Cu siguranta poate. Dar va crea o copie în stratul său superior și, din acel punct, oricine care încearcă să acceseze fișierul va primi copia de nivel superior. Când fișierele sau directoarele sunt eliminate din straturile inferioare, acestea se ascund. Straturile originale ale imaginii sunt identificate de un hash bazat pe conținut criptografic. Stratul de citire-scriere al containerului este identificat de un UUID.
Aceasta permite o strategie de scriere pe ambele imagini și containere. Docker reutilizează aceleași elemente cât mai mult posibil. Doar atunci când un element este modificat, Docker va crea o copie nouă.
Organizația unică în straturi și strategia copy-on-write promovează câteva bune practici pentru crearea și compunerea imaginilor Docker.
Imaginile Docker beneficiază de avantaje enorme din punct de vedere al stabilității, securității și timpului de încărcare, cu cât sunt mai mici. Puteți crea imagini minuscule în scopuri de producție. Dacă aveți nevoie de depanare, puteți instala întotdeauna instrumente într-un container.
Dacă vă scrieți datele, jurnalele și orice altceva numai pentru volume montate, atunci puteți utiliza întregul arsenal de instrumente de depanare și depanare la gazdă. Vom vedea în curând cum să controlați foarte atent ce fișiere intră în imaginea dvs. Docker.
Straturile sunt minunate, însă există o limită și există straturi asociate aeriene. Prea multe straturi ar putea afecta accesul la sistemul de fișiere din interiorul containerului (deoarece fiecare strat poate fi adăugat sau eliminat un fișier sau un director), și ei doar dezordinează propriul sistem de fișiere.
De exemplu, dacă instalați o grămadă de pachete, puteți avea un strat pentru fiecare pachet, instalând fiecare pachet într-o comandă RUN separată în fișierul Docker:
RUN apt-get actualizare RUN apt-get -y instalare pachet_1 RUN apt-get -y instalare pachet_2 RUN apt-get -y instalare pachet_3
Sau le puteți combina într-un singur strat cu o singură comandă RUN.
RUN apt-get update && \ apt-get -y instala pachetul_1 && \ apt-get -y instala pachetul_2 && \ apt-get -y instala pachetul_3
Imaginea de bază (practic nimeni nu construiește imagini de la zero) este adesea o decizie majoră. Poate conține mai multe straturi și poate adăuga o mulțime de capabilități, dar și o mulțime de greutate. Calitatea imaginii și a autorului sunt, de asemenea, critice. Nu doriți să vă bazați imaginile pe o imagine subțire în care nu sunteți sigur exact ce este acolo și dacă aveți încredere în autor.
Există imagini oficiale pentru multe distribuții, limbi de programare, baze de date și medii de rulare. Uneori opțiunile sunt copleșitoare. Luați-vă timp și faceți o alegere înțeleaptă.
Să ne uităm la niște imagini. Iată o listă a imaginilor disponibile în prezent pe mașina mea:
REPOSITORY TAG ID IMAGINI CREATED SIZE python cel mai recent 775dae9b960e 12 zile în urmă 687 MB d4w / nsenter Ultimele 9e4f13a0901e 4 luni în urmă 83.8 kB ubuntu-with-ssh Ultimele 87391dca396d 4 luni în urmă 221 MB ubuntu latest bd3d4369aebc 5 luni în urmă 127 MB hello-world latest c54a2cc56cbb 7 luni in urma 1.85 kB alpine cele mai recente 4e38e38c8ce0 7 luni în urmă 4.8 MB nsqio / nsq ultimele 2a82c70fe5e3 8 luni în urmă 70.7 MB
Depozitarul și eticheta identifică imaginea pentru oameni. Dacă încercați doar să executați sau să trageți folosind un nume de depozit fără a specifica eticheta, atunci eticheta "ultim" este utilizată în mod implicit. ID-ul de imagine este un identificator unic.
Să ne scufundăm și să inspectăm imaginea salio-lumii:
> docker inspecta salo-lume ["id": "sha256: c54a2cc56cbb2f ... e7e2720f70976c4b75237dc", "RepoTags": ["hello-world: latest"], "RepoDigests" , "Parent": "", "Comment": "", "Creat": "2016-07-01T19: 39: 27.532838486Z", "Container" ":" c65bc554a4b7 "," Utilizator ":" "," AttachStdin ": false," AttachStdout ": false," AttachStderr " "StdinOnce": false, "Env": ["PATH = / usr / bin: / usr / sbin: / usr / bin: -c "," # (nop) CMD [\ "/ hello \"] "]," Imagine ":" sha256: 0f9bb7da10de694 ... 5ab0fe537ce1cd831e "," Volumes ": null, WorkingDir:" Entrypoint: null, "OnBuild": null, "Etichete": , "DockerVersion": "1.10.3", "Autor": "", "Config": nume_apartament: c65bc554a4b7; "", "Utilizator": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty" Stdin ": false," StdinOnce ": false," Env ": [" PATH = / usr / sbin: / usr / bin: ":" sha256: 0f9bb7da10de694b ... b0fe537ce1cd831e "," Volumele ": null," WorkDir ":" "," Entrypoint ": null," OnBuild " , "Os": "linux", "Dimensiune": 1848, "VirtualSize": 1848, "GraphDriver": "Name": "aufs", "Data": null "straturi", "straturi": ["sha256: a02596fdd012f22b03a ... 079c3e8cebceb4262d7"]
Este interesant de văzut cât de multe informații sunt asociate cu fiecare imagine. Nu voi trece peste fiecare articol. Voi menționa un interesant lucru pe care contactele "container" și "containerConfig" sunt pentru un container temporar pe care Docker îl creează atunci când construiește imaginea. Aici, vreau să mă concentrez asupra ultimei secțiuni a "RootFS". Puteți obține doar această parte utilizând funcția Go templating a comenzii inspect:
> docker inspecta -f '.RootFS "hello-world straturi [sha256: a02596fdd012f22b03af6a ... 8357b079c3e8cebceb4262d7]
Funcționează, dar am pierdut formatul frumos. Prefer sa folosesc jq:
> docker inspecta lumea salutului jq. [0] .RootFS "Tip": "straturi", "Straturi": ["sha256: a02596fdd012f22b03af6a ... 7507558357b079c3e8cebceb4262d7"]]
Puteți vedea că tipul este "Straturi" și există doar un singur strat.
Să inspectăm straturile imaginii Python:
> docterul inspectă Python | jq [0] .RootFS "Type":. "straturi", "straturi": [ "SHA256: a2ae92ffcd29f7ede ... e681696874932db7aee2c", "SHA256: 0eb22bfb707db44a8 ... 8f04be511aba313bdc090", "SHA256: 30339f20ced009fc3 ... 6b2a44b0d39098e2e2c40", „SHA256: f55f65539fab084d4 ... 52932c7d4924c9bfa6c9e "," sha256: 311f330fa783aef35 ... e8283e06fc1975a47002d "," sha256: f250d46b2c81bf76c ... 365f67bdb014e98698823 "," sha256: 1d3d54954c0941a8f ... 8992c3363197536aa291a "]]
Wow. Șapte straturi. Dar care sunt aceste straturi? Putem folosi comanda de istorie pentru a ne da seama:
IMAGE CREATED CREATED BY SIZE 775dae9b960e 12 zile în urmă / bin / sh -c # (nop) CMD ["python3"] 0 BAcum 12 zile / bin / sh -c cd / usr / local / bin && ... 48 B 12 zile în urmă / bin / sh -c set -ex && buildDeps = '... 66.9 MB Acum 12 zile / bin / sh -c # (nop) ENV PYTHON_PIP_V ... 0 B Acum 12 zile / bin / sh -c # (nop) ENV PYTHON_VERSI ... 0 B Acum 12 zile / bin / sh -c # (nop) ENV GPG_KEY = 0D96 ... 0 B 12 zile în urmă / bin / sh -c apt-get update && apt-ge ... 7.75 MB Acum 12 zile / bin / sh -c # (nop) ENV LANG = C.UTF-8 0 B Acum 12 zile / bin / sh -c # (nop) ENV PATH = / usr / lo ... 0 B Acum 13 zile / bin / sh -c apt-get update && apt-ge ... 323 MB Acum 13 zile / bin / sh -c apt-get update && apt-ge ... 123 MB Acum 13 zile / bin / sh -c apt-get update && apt-ge ... 44.3 MB Acum 13 zile / bin / sh -c # (nop) CMD ["/ bin / bash" ... 0 B Acum 13 zile / bin / sh -c # (nop) Fișier ADD: 89ecb642 ... 123 MB
O.K. Nu fi alarmat. Nimic nu lipsește. Aceasta este doar o interfață teribilă de utilizator. Straturile utilizate pentru a avea un ID de imagine înainte de Docker 1.10, dar nu mai. ID-ul stratului superior nu este într-adevăr ID-ul acelui strat. Este ID-ul imaginii Python. "CREATED BY" este trunchiat, dar puteți vedea comanda completă dacă treceți --no-TRUNC
. Vă voi salva de la ieșire aici din cauza limitelor de lățime a paginii care vor necesita înfășurarea liniei extreme.
Cum obții imagini? Există trei moduri:
Când rulați un container, specificați imaginea acestuia. Dacă imaginea nu există în sistemul dvs., acesta este tras dintr-un registru Docker (implicit DockerHub). Alternativ, puteți trage direct fără a rula containerul.
De asemenea, puteți încărca o imagine pe care cineva v-a trimis-o ca fișier tar. Docker îl susține nativ.
În cele din urmă, și cel mai interesant, vă puteți construi propriile imagini, care este subiectul părții a doua.
Imaginile Docker se bazează pe un sistem de fișiere cu straturi, care oferă numeroase avantaje și beneficii pentru cazurile de utilizare pentru care sunt proiectate containerele, cum ar fi distribuirea ușoară și partajarea unor părți comune, astfel încât multe containere pot fi instalate și pot funcționa pe aceeași mașină economic.
.