Docker-tips: verwijder rommel van uw machine

Docker-tips: verwijder rommel van uw machine

Hallo, Habr! Ik presenteer onder uw aandacht een vertaling van het artikel "Docker-tips: ruim uw lokale machine op" auteur Luc Juggery.

Vandaag zullen we het hebben over hoe Docker de schijfruimte van de hostmachine gebruikt, en we zullen ook uitzoeken hoe we deze ruimte kunnen vrijmaken van de restjes ongebruikte afbeeldingen en containers.


Docker-tips: verwijder rommel van uw machine

Totaal verbruik

Docker is een cool ding, waarschijnlijk twijfelen maar weinig mensen er vandaag de dag aan. Nog maar een paar jaar geleden gaf dit product ons een geheel nieuwe manier om elke omgeving te bouwen, te leveren en te beheren, waardoor we CPU- en RAM-bronnen aanzienlijk konden besparen. Daarnaast (en voor sommigen zal dit het belangrijkste zijn) heeft Docker ons in staat gesteld om het levenscyclusbeheer van onze productieomgevingen ongelooflijk te vereenvoudigen en te verenigen.

Al deze geneugten van het moderne leven hebben echter een prijs. Als we containers draaien, onze eigen images downloaden of creëren, en complexe ecosystemen inzetten, moeten we betalen. En we betalen onder andere met schijfruimte.

Als je er nog nooit over hebt nagedacht hoeveel ruimte Docker daadwerkelijk in beslag neemt op je machine, zul je misschien onaangenaam verrast zijn door de uitvoer van deze opdracht:

$ docker system df

Docker-tips: verwijder rommel van uw machine

Dit toont het schijfgebruik van Docker in verschillende contexten:

  • afbeeldingen – de totale grootte van afbeeldingen die zijn gedownload van afbeeldingsopslagplaatsen en op uw systeem zijn gebouwd;
  • containers – de totale hoeveelheid schijfruimte die wordt gebruikt door het uitvoeren van containers (dat wil zeggen het totale volume aan lees-schrijflagen van alle containers);
  • lokale volumes – het volume van lokale opslag gemonteerd op containers;
  • build cache – tijdelijke bestanden gegenereerd door het image-bouwproces (bij gebruik van de BuildKit-tool, beschikbaar sinds Docker versie 18.09).

Ik wed dat je na deze eenvoudige overdracht graag je schijf wilt opruimen en kostbare gigabytes weer tot leven wilt wekken (let op: vooral als je elke maand huur voor deze gigabytes betaalt).

Schijfgebruik door containers

Elke keer dat u een container op de hostmachine aanmaakt, worden er verschillende bestanden en mappen aangemaakt in de map /var/lib/docker, waarvan de volgende het vermelden waard zijn:

  • Directory /var/lib/docker/containers/container_ID – bij gebruik van het standaard logboekstuurprogramma worden hier gebeurtenislogboeken opgeslagen in JSON-indeling. Te gedetailleerde logs, maar ook logs die niemand leest of anderszins verwerkt, zorgen er vaak voor dat schijven vol raken.
  • De map /var/lib/docker/overlay2 bevat de container-lees-schrijflagen (overlay2 is het voorkeursstuurprogramma in de meeste Linux-distributies). Als de container gegevens in zijn bestandssysteem opslaat, wordt deze in deze map geplaatst.

Laten we ons een systeem voorstellen waarop een onberispelijke Docker is geïnstalleerd, die nooit betrokken is geweest bij het lanceren van containers of het bouwen van images. Het rapport over schijfruimtegebruik ziet er als volgt uit:

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         0          0          0B         0B
Containers     0          0          0B         0B
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Laten we een container lanceren, bijvoorbeeld NGINX:

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

Wat gebeurt er met de schijf:

  • afbeeldingen nemen 126 MB in beslag, dit is dezelfde NGINX die we in de container hebben gelanceerd;
  • containers nemen een belachelijke 2 bytes in beslag.

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         1          1          126M       0B (0%)
Containers     1          1          2B         0B (0%)
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Afgaande op de conclusie hebben we nog geen ruimte die we kunnen vrijmaken. Omdat 2 bytes volkomen frivool is, laten we ons voorstellen dat onze NGINX onverwacht ergens 100 Megabytes aan gegevens schreef en een bestand test.img van precies deze grootte in zichzelf creëerde.

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

Laten we het schijfruimtegebruik op de host opnieuw bekijken. We zullen zien dat de container (containers) daar 100 Megabytes in beslag neemt.

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         1          1          126M       0B (0%)
Containers     1          1          104.9MB    0B (0%)
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Ik denk dat je nieuwsgierige brein zich al afvraagt ​​waar ons test.img-bestand zich bevindt. Laten we ernaar 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 details te treden, kunnen we opmerken dat het bestand test.img zich handig op het lees-schrijfniveau bevindt en wordt bestuurd door het overlay2-stuurprogramma. Als wij onze container tegenhouden, zal de host ons vertellen dat deze ruimte in principe vrijgemaakt kan worden:

# 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 inhoudt dat de overeenkomstige ruimte op lees-schrijfniveau wordt vrijgemaakt.

Met de volgende opdracht kunt u in één klap alle geïnstalleerde containers verwijderen en uw schijf wissen van alle lees- en schrijfbestanden die door deze containers zijn gemaakt:

$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
5e7f8e5097ace9ef5518ebf0c6fc2062ff024efb495f11ccc89df21ec9b4dcc2

Total reclaimed space: 104.9MB

We hebben dus 104,9 Megabytes vrijgemaakt door de container te verwijderen. Maar aangezien we de eerder gedownloade afbeelding niet langer gebruiken, komt deze ook in aanmerking voor het verwijderen en vrijmaken van onze bronnen:

$ docker system df
TYPE           TOTAL      ACTIVE     SIZE       RECLAIMABLE
Images         1          0          126M       126M (100%)
Containers     0          0          0B         0B
Local Volumes  0          0          0B         0B
Build Cache    0          0          0B         0B

Opmerking: Zolang de afbeelding door ten minste één container wordt gebruikt, kun je deze truc niet gebruiken.

Het pruimen-subcommando dat 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)

Kanttekeningen: als u de parameter -rm gebruikt bij het starten van een container, wordt alle schijfruimte die deze in beslag nam, vrijgegeven als deze stopt.

Schijfimages gebruiken

Een paar jaar geleden was een afbeeldingsgrootte van enkele honderden megabytes volkomen normaal: een Ubuntu-image woog 600 megabytes en een Microsoft .Net-image woog enkele gigabytes. In die ruige dagen kon het downloaden van slechts één afbeelding een grote tol eisen van uw vrije schijfruimte, zelfs als u niveaus tussen afbeeldingen deelde. Tegenwoordig wegen afbeeldingen veel minder, maar toch kun je de beschikbare bronnen snel aanvullen als je niet de nodige voorzorgsmaatregelen neemt.

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

  • tussenliggende afbeeldingen, op basis waarvan andere afbeeldingen worden verzameld - deze kunnen niet worden verwijderd als u containers gebruikt op basis van deze “andere” afbeeldingen;
  • bungelende afbeeldingen zijn tussenliggende afbeeldingen waarnaar niet wordt verwezen door een van de actieve containers - ze kunnen worden verwijderd.
  • Met de volgende opdracht kunt u controleren op bungelende afbeeldingen op uw systeem:

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

Je kunt ze op de volgende manier verwijderen:

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

We kunnen ook het subcommando snoeien gebruiken:

$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
Deleted Images:
deleted: sha256:143407a3cb7efa6e95761b8cd6cea25e3f41455be6d5e7cda
deleted: sha256:738010bda9dd34896bac9bbc77b2d60addd7738ad1a95e5cc
deleted: sha256:fa4f0194a1eb829523ecf3bad04b4a7bdce089c8361e2c347
deleted: sha256:c5041938bcb46f78bf2f2a7f0a0df0eea74c4555097cc9197
deleted: sha256:5945bb6e12888cf320828e0fd00728947104da82e3eb4452f

Total reclaimed space: 12.9kB

Als we plotseling alle afbeeldingen helemaal willen verwijderen (en niet alleen maar bungelen) met één commando, dan kunnen we dit doen:

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

Schijfgebruik per volume

Volumes worden gebruikt om gegevens buiten het bestandssysteem van de container op te slaan. Bijvoorbeeld als we de resultaten van een applicatie willen bewaren om ze op een andere manier te gebruiken. Een bekend voorbeeld zijn databases.

Laten we een MongoDB-container starten, een volume extern aan de container koppelen en er een databaseback-up van herstellen (we hebben deze beschikbaar 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 lees-schrijfniveau van de container? Omdat in het Dockerfile van de MongoDB-image de map /data/db (waar MongoDB standaard zijn gegevens opslaat) wordt gedefinieerd als een volume.

Docker-tips: verwijder rommel van uw machine

Kanttekening: veel afbeeldingen die gegevens moeten produceren, gebruiken volumes om die gegevens op te slaan.

Als we genoeg met MongoDB spelen en de container stoppen (of misschien zelfs verwijderen), wordt het volume niet verwijderd. Het zal onze kostbare schijfruimte blijven innemen totdat we het expliciet verwijderen met een opdracht als deze:

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

Nou ja, of we kunnen het snoei-subcommando gebruiken dat ons al bekend is:

$ docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
d50b6402eb75d09ec17a5f57df4ed7b520c448429f70725fc5707334e5ded4d5
8f7a16e1cf117cdfddb6a38d1f4f02b18d21a485b49037e2670753fa34d115fc
599c3dd48d529b2e105eec38537cd16dac1ae6f899a123e2a62ffac6168b2f5f
...
732e610e435c24f6acae827cd340a60ce4132387cfc512452994bc0728dd66df
9a3f39cc8bd0f9ce54dea3421193f752bda4b8846841b6d36f8ee24358a85bae
045a9b534259ec6c0318cb162b7b4fca75b553d4e86fc93faafd0e7c77c79799
c6283fe9f8d2ca105d30ecaad31868410e809aba0909b3e60d68a26e92a094da

Total reclaimed space: 25.82GB
luc@saturn:~$

Schijf gebruiken voor cache voor het maken van afbeeldingen

In Docker 18.09 heeft het proces voor het maken van afbeeldingen enkele wijzigingen ondergaan dankzij de BuildKit-tool. Dit ding verhoogt de snelheid van het proces en optimaliseert gegevensopslag en beveiligingsbeheer. Hier zullen we niet alle details van dit prachtige hulpmiddel bespreken; we zullen ons alleen concentreren op de manier waarop het problemen met het gebruik van schijfruimte aanpakt.

Laten we zeggen dat we een volledig eenvoudige Node.Js-applicatie hebben:

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

$ 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"
      }
    }

Het Dockerbestand 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 BuildKit te gebruiken:

$ docker build -t app:1.0 .

Als we het schijfruimtegebruik controleren, kunnen we zien dat alleen de basisimage (node:13-alpine) en de doelimage (app:1.0) ruimte in beslag nemen:

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    0          0          0B         0B

Laten we de tweede versie van onze applicatie bouwen met behulp van BuildKit. Om dit te doen, hoeven we alleen maar de DOCKER_BUILDKIT variabele in te stellen op 1:

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

Als we nu het schijfgebruik controleren, zullen we zien dat de build-cache (buid-cache) daar nu 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

Om het te wissen, gebruikt u de volgende opdracht:

$ docker builder prune
WARNING! This will remove all dangling build cache.
Are you sure you want to continue? [y/N] y
Deleted build cache objects:
rffq7b06h9t09xe584rn4f91e
ztexgsz949ci8mx8p5tzgdzhe
3z9jeoqbbmj3eftltawvkiayi

Total reclaimed space: 8.949kB

Wis alles!

We hebben dus gekeken naar het opruimen van schijfruimte die wordt ingenomen door containers, afbeeldingen en volumes. Het subcommando snoeien helpt ons hierbij. Maar het kan ook op docker-systeemniveau worden gebruikt en het zal alles opruimen wat het kan:

$ docker system prune
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N]

Als u om de een of andere reden schijfruimte bespaart op een machine waarop Docker draait, dan zou het periodiek uitvoeren van deze opdracht een gewoonte moeten worden.

Bron: www.habr.com

Voeg een reactie