Docker Tips: Maak je machine vrij van rommel

Docker Tips: Maak je machine vrij van rommel

Hallo, Habr! Ik presenteer u de vertaling van het artikel "Docker Tips: Maak Uw Lokale Machine Schoon" auteur Luc Juggery.

Vandaag bespreken we hoe Docker de schijfruimte van de hostmachine gebruikt en hoe we deze ruimte kunnen vrijmaken van overblijfselen van ongebruikte images en containers.


Docker Tips: Maak je machine vrij van rommel

Totaal verbruik

Docker is een fantastisch hulpmiddel, tegenwoordig twijfelt bijna niemand daar meer aan. Slechts enkele jaren geleden heeft dit product ons een geheel nieuwe manier gegeven om omgevingen te bouwen, te leveren en uit te voeren, waarmee we aanzienlijk CPU- en RAM-bronnen konden besparen. Bovendien heeft Docker (en voor sommigen is dit misschien wel het belangrijkste) ons in staat gesteld om het beheer van de levenscyclus van gebruikte werkomgevingen ongelooflijk te vereenvoudigen en te uniformeren.

Echter, voor al deze voordelen van het moderne leven moeten we betalen. Wanneer we containers starten, eigen images downloaden of creƫren, of complexe ecosystemen implementeren, komt daar een prijs aan vast. En we betalen, onder andere, met schijfruimte.

Als je nooit hebt nagedacht over hoeveel ruimte daadwerkelijk door Docker op jouw machine in beslag wordt genomen, kun je onaangenaam verrast worden door de output van dit commando:

$ docker system df

Docker Tips: Maak je machine vrij van rommel

Hier wordt het schijfgebruik door Docker in verschillende categorieƫn weergegeven:

  • images – de totale grootte van images die zijn gedownload uit image repositories en in jouw systeem zijn opgebouwd;
  • containers – de totale hoeveelheid schijfruimte die wordt gebruikt door actieve containers (dit verwijst naar het totale volume van de lees- en schrijf- layers van alle containers);
  • local volumes – de hoeveelheid lokale opslag die aan containers is gekoppeld;
  • build cache – tijdelijke bestanden die zijn gegenereerd door het buildproces van images (met behulp van de BuildKit-tool, beschikbaar vanaf Docker versie 18.09).

Ik wed dat je al na deze eenvoudige opsomming verlangen hebt om de schijf op te ruimen en waardevolle gigabytes terug te winnen (opmerking van de vertaler: vooral als je maandelijks huur betaalt voor die gigabytes).

Schijfgebruik door containers

Elke keer als er een container op de hostmachine wordt aangemaakt, worden er verschillende bestanden en mappen in de directory /var/lib/docker aangemaakt, waaronder de volgende te vermelden:

  • Catalogus /var/lib/docker/containers/ID_container – bij het gebruik van de standaard loggingdriver worden hier de gebeurtenislogboeken in JSON-formaat opgeslagen. Te gedetailleerde logs, evenals logs die niemand leest of op andere manieren verwerkt, zijn vaak de oorzaak van schijfontoegang.
  • Catalogus /var/lib/docker/overlay2 – bevat de lees- en schrijflagen van de containers (overlay2 is de voorkeursdriver in de meeste Linux-distributies). Als een container gegevens in zijn bestandssysteem opslaat, worden deze in deze catalogus geplaatst.

Laten we ons een systeem voorstellen met een spiksplinternieuwe Docker, die nog nooit containers heeft uitgevoerd of afbeeldingen heeft opgebouwd. Het rapport over het schijgebruik zal er als volgt uitzien:

$ docker system df
TYPE           TOTAAL      ACTIEF     GROOTTE    HERSTELBAAR
Afbeeldingen    0          0          0B         0B
Containers      0          0          0B         0B
Lokale Volumes  0          0          0B         0B
Build Cache     0          0          0B         0B

Laten we een container starten, bijvoorbeeld NGINX:

$ docker container run --name www -d -p 8000:80 nginx:1.16

Wat gebeurt er met de schijf:

  • afbeeldingen (images) nemen 126 MB in beslag, dat is diezelfde NGINX die we in de container hebben gestart;
  • containers (containers) nemen belachelijke 2 bytes in beslag.

$ docker system df
TYPE           TOTAAL      ACTIEF     GROOTTE    HERSTELBAAR
Afbeeldingen    1          1          126M       0B (0%)
Containers      1          1          2B         0B (0%)
Lokale Volumes  0          0          0B         0B
Build Cache     0          0          0B         0B

Afgaand op de uitvoer hebben we nog geen ruimte die we kunnen vrijgeven. Aangezien 2 bytes totaal onbeduidend zijn, laten we ons voorstellen dat onze NGINX onverwacht 100 megabyte aan gegevens heeft geschreven en daarin een bestand test.img van precies die grootte heeft aangemaakt.

$ docker exec -ti www 
  dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*100]

Laten we opnieuw het schijgebruik op de host onderzoeken. We zullen zien dat de container (containers) daar 100 megabyte in beslag neemt.

$ docker system df
TYPE           TOTAAL      ACTIEF     GROOTTE    HERSTELBAAR
Afbeeldingen    1          1          126M       0B (0%)
Containers      1          1          104.9MB    0B (0%)
Lokale Volumes  0          0          0B         0B
Build Cache     0          0          0B         0B

Ik denk dat je nieuwsgierige geest zich al afvraagt waar ons bestand test.img is. Laten we het gaan zoeken:

$ find /var/lib/docker -type f -name test.img
/var/lib/docker/overlay2/83f177...630078/merged/test.img
/var/lib/docker/overlay2/83f177...630078/diff/test.img

Zonder in detail te treden, kunnen we opmerken dat het bestand test.img handig is geplaatst op het lees-schrijf niveau, beheerd door de overlay2 driver. Als we onze container echter stoppen, zal de host ons vertellen dat deze ruimte in principe kan worden vrijgegeven:

# Stopping the www container
$ docker stop www

# Visualizing the impact on the disk usage
$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         1          1          126M       0B (0%)
Containers     1          0          104.9MB    104.9MB (100%)
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Hoe kunnen we dit doen? Door de container te verwijderen, wat de opruiming van de bijbehorende ruimte op het lees-schrijf niveau met zich meebrengt.

Met de volgende opdracht kunt u alle geïnstalleerde containers in één keer verwijderen en uw schijf schoonmaken van alle door hen op het lees-schrijf niveau aangemaakte bestanden:

$ docker container prune
WAARSCHUWING! Dit zal alle gestopte containers verwijderen.
Weet u zeker dat u wilt doorgaan? [y/N] y
Verwijderde Containers:
5e7f8e5097ace9ef5518ebf0c6fc2062ff024efb495f11ccc89df21ec9b4dcc2

Totaal herwonnen ruimte: 104,9MB

Dus hebben we 104,9 Megabyte vrijgegeven door de container te verwijderen. Maar omdat we de eerder gedownloade afbeelding niet meer gebruiken, wordt deze ook een kandidaat voor verwijdering en kunnen we onze middelen vrijgeven:

$ docker system df
TYPE           TOTAAL     ACTIEF     GROOTTE    HERWONNEN
Afbeeldingen    1          0          126M       126M (100%)
Containers     0          0          0B         0B
Lokale Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Let op: zolang de afbeelding door minstens ƩƩn container wordt gebruikt, kunt u deze truc niet toepassen.

De subopdracht prune, die we hierboven hebben gebruikt, heeft alleen effect op gestopte containers. Als we niet alleen gestopte, maar ook actieve containers willen verwijderen, moeten we een van deze opdrachten gebruiken:

# Historical command
$ docker rm -f $(docker ps –aq)

# More recent command
$ docker container rm -f $(docker container ls -aq)

Opmerkingen aan de zijlijn: als u de parameter —rm gebruikt bij het starten van de container, zal alle schijfruimte die deze in beslag nam, worden vrijgegeven wanneer deze wordt gestopt.

Schijfruimtegebruik door afbeeldingen

Enkele jaren geleden was een afbeeldingsgrootte van enkele honderden megabytes volkomen normaal: de Ubuntu afbeelding weegde 600 Megabyte en de Microsoft .Net afbeelding enkele Gigabytes. In die oude tijden kon het downloaden van slechts ƩƩn afbeelding aanzienlijke schade toebrengen aan uw vrije schijfruimte, zelfs als u lagen tussen afbeeldingen deelde. Tegenwoordig, laten we de grootheden prijzen, wegen afbeeldingen veel minder, maar zelfs dan kunt u snel de beschikbare middelen opvullen als u geen voorzorgsmaatregelen neemt.

Er zijn verschillende soorten afbeeldingen die niet direct zichtbaar zijn voor de eindgebruiker:

  • intermediate afbeeldingen, waarop andere afbeeldingen zijn gebaseerd – deze kunnen niet worden verwijderd als je containers gebruikt die op deze 'andere' afbeeldingen zijn gebaseerd;
  • dangling afbeeldingen – dit zijn intermediate afbeeldingen die niet door een actieve container worden aangeroepen – deze kunnen verwijderd worden.
  • Met de volgende opdracht kun je controleren of er dangling afbeeldingen in je systeem aanwezig zijn:

$ docker image ls -f dangling=true
REPOSITORY  TAG      IMAGE ID         CREATED             SIZE
none      none   21e658fe5351     12 minuten geleden      71.3MB

Je kunt ze als volgt verwijderen:

$ docker image rm $(docker image ls -f dangling=true -q)

We kunnen ook de subopdracht prune gebruiken:

$ docker image prune
WARNING! Dit verwijdert alle dangling afbeeldingen.
Weet je zeker dat je wilt doorgaan? [y/N] y
Verwijderde afbeeldingen:
deleted: sha256:143407a3cb7efa6e95761b8cd6cea25e3f41455be6d5e7cda
deleted: sha256:738010bda9dd34896bac9bbc77b2d60addd7738ad1a95e5cc
deleted: sha256:fa4f0194a1eb829523ecf3bad04b4a7bdce089c8361e2c347
deleted: sha256:c5041938bcb46f78bf2f2a7f0a0df0eea74c4555097cc9197
deleted: sha256:5945bb6e12888cf320828e0fd00728947104da82e3eb4452f

Totaal teruggewonnen ruimte: 12.9kB

Als we alles willen verwijderen (en niet alleen dangling) met ƩƩn opdracht, kunnen we het als volgt doen:

$ docker image rm $(docker image ls -q)

Gebruik van schijf met volumes

Volumes worden gebruikt voor het opslaan van gegevens buiten de container's bestandssysteem. Bijvoorbeeld, als we de resultaten van een applicatie willen opslaan om ze later opnieuw te gebruiken. Een veelvoorkomend voorbeeld zijn databases.

Laten we een MongoDB-container starten, een externe volume aan koppelen, en deze opnieuw opbouwen vanuit een back-upbestand van de database (dat beschikbaar is in het bestand bck.json):

# Running a mongo container
$ docker run --name db -v $PWD:/tmp -p 27017:27017 -d mongo:4.0

# Importing an existing backup (from a huge bck.json file)
$ docker exec -ti db mongoimport 
  --db 'test' 
  --collection 'demo' 
  --file /tmp/bck.json 
  --jsonArray

De gegevens bevinden zich op de hostmachine in de map /var/lib/docker/volumes. Maar waarom niet op het niveau van lezen/schrijven van de container? Omdat in de Dockerfile van de MongoDB-afbeelding de map /data/db (waar MongoDB standaard zijn gegevens opslaat) als volume is gedefinieerd.

Docker Tips: Maak je machine vrij van rommel

Opmerkingen aan de zijlijn: veel afbeeldingen die gegevens creƫren, gebruiken volumes om deze gegevens op te slaan.

Wanneer we klaar zijn met MongoDB en de container stoppen (of misschien zelfs verwijderen), zal het volume niet worden verwijderd. Het blijft onze waardevolle schijfruimte innemen totdat we het expliciet verwijderen met de volgende opdracht:

$ docker volume rm $(docker volume ls -q)

Of we kunnen de al bekende subopdracht prune gebruiken:

$ docker volume prune
WAARSCHUWING! Dit verwijdert alle lokale volumes die door ten minste ƩƩn container niet worden gebruikt.
Weet je zeker dat je door wilt gaan? [y/N] y
Verwijderde Volumes:
d50b6402eb75d09ec17a5f57df4ed7b520c448429f70725fc5707334e5ded4d5
8f7a16e1cf117cdfddb6a38d1f4f02b18d21a485b49037e2670753fa34d115fc
599c3dd48d529b2e105eec38537cd16dac1ae6f899a123e2a62ffac6168b2f5f
...
732e610e435c24f6acae827cd340a60ce4132387cfc512452994bc0728dd66df
9a3f39cc8bd0f9ce54dea3421193f752bda4b8846841b6d36f8ee24358a85bae
045a9b534259ec6c0318cb162b7b4fca75b553d4e86fc93faafd0e7c77c79799
c6283fe9f8d2ca105d30ecaad31868410e809aba0909b3e60d68a26e92a094da

Totaal herwonnen ruimte: 25.82GB
luc@saturn:~$

Schijfruimte voor de build-cache gebruiken

In Docker 18.09 heeft het proces voor het maken van afbeeldingen enkele wijzigingen ondergaan dankzij de BuildKit-tool. Met deze tool wordt de snelheid van het proces verhoogd, worden gegevensopslag en -beveiliging geoptimaliseerd. We zullen hier niet alle details van deze geweldige tool bekijken, maar ons beperken tot hoe het de schijfruimte beĆÆnvloedt.

Stel dat we een heel eenvoudige Node.js-applicatie hebben:

  • het bestand index.js start een eenvoudige HTTP-server die met een regel op elk ontvangen verzoek reageert:
  • het bestand package.json definieert de afhankelijkheden, waarvan alleen expressjs wordt gebruikt om de HTTP-server te draaien:

$ cat index.js
var express = require('express');
var util    = require('util');
var app = express();
app.get('/', function(req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.end(util.format("%s - %s", new Date(), 'Got Request'));
});
app.listen(process.env.PORT || 80);

$ cat package.json
    {
      "name": "testnode",
      "version": "0.0.1",
      "main": "index.js",
      "scripts": {
        "start": "node index.js"
      },
      "dependencies": {
        "express": "^4.14.0"
      }
    }

De Dockerfile voor het bouwen van de afbeelding ziet er als volgt uit:

FROM node:13-alpine
COPY package.json /app/package.json
RUN cd /app && npm install
COPY . /app/
WORKDIR /app
EXPOSE 80
CMD ["npm", "start"]

Laten we de afbeelding op de gebruikelijke manier bouwen, zonder gebruik te maken van BuildKit:

$ docker build -t app:1.0 .

Als we het gebruik van schijfruimte controleren, zullen we zien dat alleen de basisafbeelding (node:13-alpine) en de eindafbeelding (app:1.0) ruimte in beslag nemen:

TYPE           TOTAAL      ACTIEF     GROOTTE    HERSTELBAAR
Afbeeldingen    2          0          109.3MB    109.3MB (100%)
Containers      0          0          0B         0B
Lokale Volumes  0          0          0B         0B
Build Cache     0          0          0B         0B

Laten we de tweede versie van onze applicatie bouwen, deze keer met gebruik van BuildKit. Hiervoor hoeven we alleen maar de variabele DOCKER_BUILDKIT op 1 in te stellen:

$ DOCKER_BUILDKIT=1 docker build -t app:2.0 .

Als we nu het schijfgebruik controleren, zullen we zien dat er nu ook build-cache (build-cache) bij betrokken is:

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         2          0          109.3MB    109.3MB (100%)
Containers     0          0          0B         0B
Local Volumes  0          0          0B         0B
Build Cache    11         0          8.949kB    8.949kB

Gebruik de volgende opdracht om dit op te schonen:

$ docker builder prune
WAARSCHUWING! Dit verwijdert alle dangling build cache.
Weet je zeker dat je door wilt gaan? [y/N] y
Verwijderde build cache-objecten:
rffq7b06h9t09xe584rn4f91e
ztexgsz949ci8mx8p5tzgdzhe
3z9jeoqbbmj3eftltawvkiayi

Totaal herstelde ruimte: 8.949kB

Maak alles schoon!

Dus, we hebben gekeken naar het opruimen van schijfruimte die door containers, images en volumes wordt ingenomen. Dit wordt geholpen door de subopdracht prune. Maar deze kan ook op systeemniveau voor docker worden gebruikt en zal alles opruimen wat het maar kan:

$ docker system prune
WAARSCHUWING! Dit verwijdert:
  - alle gestopte containers
  - alle netwerken die door ten minste ƩƩn container niet worden gebruikt
  - alle dangling images
  - alle dangling build cache

Weet je zeker dat je door wilt gaan? [y/N]

Als je om welke reden dan ook schijfruimte op een machine met Docker bespaart, is het aan te raden om deze opdracht regelmatig uit te voeren.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers šŸ”„ Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster