Docker vanuit de grond omhoog afbeeldingen begrijpen

Dockercontainers zijn in opkomst als best practice voor het implementeren en beheren van cloud-native gedistribueerde systemen. Containers zijn exemplaren van Docker-afbeeldingen. Het blijkt dat er veel te weten en te begrijpen is over afbeeldingen. 

In deze tweedelige handleiding behandel ik de Docker-afbeeldingen in de diepte. In dit deel zal ik beginnen met de basisprincipes, en dan ga ik verder met het ontwerpen van overwegingen en het inspecteren van interne afbeeldingen van afbeeldingen. In deel twee behandel ik uw eigen afbeeldingen, het oplossen van problemen en het werken met beeldopslagplaatsen. 

Wanneer u aan de andere kant uitkomt, heeft u een goed begrip van wat Docker-afbeeldingen precies zijn en hoe u ze effectief kunt gebruiken in uw eigen toepassingen en systemen.

Lagen begrijpen

Docker beheert afbeeldingen met behulp van een back-end opslagstuurprogramma. Er zijn verschillende ondersteunde stuurprogramma's, zoals AUFS, BTRFS en overlays. Afbeeldingen zijn gemaakt van geordende lagen. U kunt een laag zien als een reeks wijzigingen in het bestandssysteem. Wanneer u alle lagen neemt en ze samen stapelt, krijgt u een nieuwe afbeelding die alle geaccumuleerde wijzigingen bevat. 

Het bestelde onderdeel is belangrijk. Als u een bestand in één laag toevoegt en het in een andere laag verwijdert, kunt u het beter in de juiste volgorde doen. Docker houdt elke laag bij. Een afbeelding kan zijn samengesteld uit tientallen lagen (de huidige limiet is 127). Elke laag is erg licht van gewicht. Het voordeel van lagen is dat afbeeldingen lagen kunnen delen. 

Als u veel afbeeldingen hebt op basis van vergelijkbare lagen, zoals basis-OS of algemene pakketten, worden al deze algemene lagen slechts één keer opgeslagen en is de overhead per afbeelding alleen de unieke lagen van die afbeelding.

Kopiëren op schrijven

Wanneer een nieuwe container wordt gemaakt op basis van een afbeelding, zijn alle afbeeldingslagen alleen-lezen en wordt er een dunne laag voor lezen en schrijven aan toegevoegd. Alle wijzigingen die in de specifieke container zijn aangebracht, worden in die laag opgeslagen. 

Dit betekent niet dat de container geen bestanden van de afbeeldingslaag kan wijzigen. Het kan zeker. Maar het maakt een kopie in de bovenste laag en vanaf dat moment krijgt iedereen die probeert toegang te krijgen tot het bestand de kopie op de bovenste laag. Wanneer bestanden of mappen uit lagere lagen worden verwijderd, worden ze verborgen. De originele afbeeldingslagen worden geïdentificeerd door een op cryptografische inhoud gebaseerde hash. De lees- en schrijflaag van de container wordt geïdentificeerd door een UUID.

Dit maakt een copy-on-write-strategie mogelijk voor zowel afbeeldingen als containers. Docker gebruikt dezelfde items zoveel mogelijk opnieuw. Alleen wanneer een item is gewijzigd, maakt Docker een nieuwe kopie.

Ontwerpoverwegingen voor Docker-afbeeldingen

De unieke organisatie in lagen en de copy-on-write-strategie bevorderen enkele praktische tips voor het maken en compositeren van Docker-afbeeldingen.

Minimale afbeeldingen: minder is meer

Docker-afbeeldingen hebben enorme voordelen vanuit het oogpunt van stabiliteit, veiligheid en laadtijd, hoe kleiner ze zijn. U kunt hele kleine afbeeldingen maken voor productiedoeleinden. Als u problemen wilt oplossen, kunt u altijd hulpprogramma's in een container installeren. 

Als u uw gegevens, logboeken en al het andere alleen naar gekoppelde volumes schrijft, kunt u uw hele arsenaal aan hulpprogramma's voor foutopsporing en probleemoplossing van de host gebruiken. We zullen snel zien hoe u heel nauwkeurig kunt bepalen welke bestanden in uw Docker-afbeelding terechtkomen.

Combineer lagen

Lagen zijn geweldig, maar er is een limiet en er is overhead verbonden aan lagen. Te veel lagen kunnen de toegang tot het bestandssysteem binnen de container beschadigen (omdat elke laag een bestand of map kan hebben toegevoegd of verwijderd) en ze maken je eigen bestandssysteem rommelig.

Als u bijvoorbeeld een aantal pakketten installeert, kunt u een laag voor elk pakket hebben door elk pakket in een afzonderlijk RUN-commando in uw Dockerfile te installeren:

RUN apt-get update RUN apt-get -y install package_1 RUN apt-get -y install package_2 RUN apt-get -y install package_3

Of u kunt ze combineren in één laag met een enkele RUN-opdracht.

RUN apt-get update && \ apt-get -y installeren package_1 && apt-get -y installeren package_2 && apt-get -y installeren package_3 

Een basisafbeelding kiezen

Je basisbeeld (vrijwel niemand maakt de beelden helemaal opnieuw) is vaak een belangrijke beslissing. Het kan veel lagen bevatten en veel mogelijkheden toevoegen, maar ook veel gewicht. De kwaliteit van de afbeelding en de auteur zijn ook van cruciaal belang. Je wilt je afbeeldingen niet baseren op een vlokkig beeld waarvan je niet zeker weet wat erin zit en of je de auteur kunt vertrouwen.

Er zijn officiële afbeeldingen voor veel distributies, programmeertalen, databases en runtime-omgevingen. Soms zijn de opties overweldigend. Neem de tijd en maak een verstandige keuze.

Beelden inspecteren

Laten we naar enkele afbeeldingen kijken. Hier is een lijst met de afbeeldingen die momenteel beschikbaar zijn op mijn computer:

REPOSITORY TAG IMAGE ID CREATED SIZE python laatste 775dae9b960e 12 dagen geleden 687 MB d4w / nsenter laatste 9e4f13a0901e 4 maanden geleden 83.8 kB ubuntu-with-ssh nieuwste 87391dca396d 4 maanden geleden 221 MB ubuntu laatste bd3d4369aebc 5 maanden geleden 127 MB hello-world laatste c54a2cc56cbb 7 maanden geleden 1.85 kB alpine laatste 4e38e38c8ce0 7 maanden geleden 4.8 MB nsqio / nsq laatste 2a82c70fe5e3 8 maanden geleden 70,7 MB

De repository en de tag identificeren het beeld voor mensen. Als u alleen probeert te rennen of te trekken met een repository-naam zonder de tag op te geven, wordt standaard de tag "latest" gebruikt. De afbeeldings-ID is een unieke ID.

Laten we duiken in en het imago van de hellowereld bekijken:

> havenarbeider inspecteer hello-world ["Id": "sha256: c54a2cc56cbb2f ... e7e2720f70976c4b75237dc", "RepoTags": ["hallo-wereld: nieuwste"], "RepoDigests": ["hallo-world @ sha256: 0256e8a3 ... 411de4cdcf9431a1feb60fd9" ], "Parent": "", "Reactie": "", "Gemaakt": "2016-07-01T19: 39: 27.532838486Z", "Container": "562cadb4d17bbf30b58a ... bf637f1d2d7f8afbef666", "ContainerConfig": "Hostnaam ":" c65bc554a4b7 "," Domainname ":" "," User ":" "," AttachStdin ": false," AttachStdout ": false," AttachStderr ": false," Tty ": false," OpenStdin ": false, "StdinOnce": false, "Env": ["PATH = / usr / bin: / usr / sbin: / usr / bin: / sbin: / bin"], "Cmd": ["/ bin / sh", " -c "," # (nop) CMD [\ "/ hallo \"] "]," Afbeelding ":" sha256: 0f9bb7da10de694 ... 5ab0fe537ce1cd831e "," Volumes ": null," WorkingDir ":" "," Entrypoint ": null, "OnBuild": null, "Labels": , "DockerVersion": "1.10.3", "Auteur": "", "Config": "Hostname": "c65bc554a4b7", "Domeinnaam": "", "Gebruiker": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": false, "Open Stdin ": false," StdinOnce ": false," Env ": [" PATH = / usr / sbin: / usr / bin: / sbin: / bin "]," Cmd ": [" / hallo "]," Afbeelding ":" sha256: 0f9bb7da10de694b ... b0fe537ce1cd831e "," Volumes ": null," WorkingDir ":" "," Entrypoint ": null," OnBuild ": null," Labels ": ," Architecture ":" amd64 " , "Os": "linux", "Grootte": 1848, "VirtualSize": 1848, "GraphDriver": "Name": "aufs", "Data": null, "RootFS": "Type": "layers", "Layers": ["sha256: a02596fdd012f22b03a ... 079c3e8cebceb4262d7"]]

Het is interessant om te zien hoeveel informatie aan elke afbeelding is gekoppeld. Ik ga niet over elk item heen. Ik noem alleen een interessant feitje dat de "container" - en "containerConfig" -items voor een tijdelijke container zijn die door Docker wordt gemaakt wanneer deze de afbeelding bouwt. Hier wil ik me concentreren op het laatste deel van "RootFS". Je kunt alleen dit onderdeel krijgen met de Go-sjabloonondersteuning van de opdracht inspecteren:

> docker inspect -f '.RootFS' hello-world layers [sha256: a02596fdd012f22b03af6a ... 8357b079c3e8cebceb4262d7]

Het werkt, maar we zijn de mooie opmaak kwijtgeraakt. Ik gebruik liever jq:

> havenarbeider inspecteert hello-world | jq. [0] .RootFS "Type": "layers", "Layers": ["sha256: a02596fdd012f22b03af6a ... 7507558357b079c3e8cebceb4262d7"] 

U kunt zien dat het type "Lagen" is en dat er slechts één laag is. 

Laten we de lagen van de Python-afbeelding inspecteren:

> havenarbeider inspecteert python | jq. [0] .RootFS "Type": "layers", "Layers": ["sha256: a2ae92ffcd29f7ede ... e681696874932db7aee2c", "sha256: 0eb22bfb707db44a8 ... 8f04be511aba313bdc090", "sha256: 30339f20ced009fc3 ... 6b2a44b0d39098e2e2c40", "sha256: f55f65539fab084d4 ... 52932c7d4924c9bfa6c9e "," sha256: 311f330fa783aef35 ... e8283e06fc1975a47002d "," sha256: f250d46b2c81bf76c ... 365f67bdb014e98698823 "," sha256: 1d3d54954c0941a8f ... 8992c3363197536aa291a "]

Wauw. Zeven lagen. Maar wat zijn die lagen? We kunnen de opdracht history gebruiken om dat te achterhalen:

BEELD GECREËERD GECREËERD OP GROOTTE 775dae9b960e 12 dagen geleden / bin / sh -c # (nop) CMD ["python3"] 0 B  12 dagen geleden / bin / sh -c cd / usr / local / bin && ... 48 B  12 dagen geleden / bin / sh -c set -ex && buildDeps = '... 66.9 MB  12 dagen geleden / bin / sh -c # (nop) ENV PYTHON_PIP_V ... 0 B  12 dagen geleden / bin / sh -c # (nop) ENV PYTHON_VERSI ... 0 B  12 dagen geleden / bin / sh -c # (nop) ENV GPG_KEY = 0D96 ... 0 B  12 dagen geleden / bin / sh -c apt-get update && apt-ge ... 7.75 MB  12 dagen geleden / bin / sh -c # (nop) ENV LANG = C.UTF-8 0 B  12 dagen geleden / bin / sh -c # (nop) ENV PATH = / usr / lo ... 0 B  13 dagen geleden / bin / sh -c apt-get update && apt-ge ... 323 MB  13 dagen geleden / bin / sh -c apt-get update && apt-ge ... 123 MB  13 dagen geleden / bin / sh -c apt-get update && apt-ge ... 44.3 MB  13 dagen geleden / bin / sh -c # (nop) CMD ["/ bin / bash" ... 0 B  13 dagen geleden / bin / sh -c # (nop) ADD-bestand: 89ecb642 ... 123 MB

OK. Wees niet gealarmeerd. Niets ontbreekt. Dit is gewoon een vreselijke gebruikersinterface. De lagen hadden eerder een afbeelding-ID voor Docker 1.10, maar niet meer. De ID van de bovenste laag is niet echt de ID van die laag. Het is de ID van de Python-afbeelding. De "CREATED BY" is afgekapt, maar u kunt de volledige opdracht zien als u slaagt --no-trunc. Ik zal je hier van de uitvoer redden vanwege de beperkingen van de paginabreedte waarvoor extreme lijninwikkeling vereist is.

Hoe krijg je afbeeldingen? Er zijn drie manieren:

  • Trek / Run
  • Laden
  • Bouwen

Wanneer u een container uitvoert, geeft u de afbeelding op. Als de afbeelding niet op uw systeem bestaat, wordt deze uit een Docker-register gehaald (standaard DockerHub). Je kunt ook direct trekken zonder de container te gebruiken.

U kunt ook een afbeelding laden die iemand u heeft gestuurd als een tar-bestand. Docker ondersteunt het native.

Ten slotte, en het is interessant om te weten, kun je je eigen afbeeldingen maken, wat het onderwerp is van deel twee.

Conclusie

Docker-images zijn gebaseerd op een gelaagd bestandssysteem dat vele voordelen en voordelen biedt voor de use cases waarvoor containers zijn ontworpen, zoals lichtgewicht zijn en gemeenschappelijke delen delen, zodat veel containers op dezelfde machine economisch kunnen worden ingezet en uitgevoerd.. 

.