Docker-tips: Tøm maskinen for søppel

Docker-tips: Tøm maskinen for søppel

Hei, Habr! Jeg presenterer for din oppmerksomhet en oversettelse av artikkelen "Docker-tips: Rydd opp i din lokale maskin" forfatter Luc Juggery.

I dag skal vi snakke om hvordan Docker bruker diskplassen til vertsmaskinen, og vi vil også finne ut hvordan vi kan frigjøre denne plassen fra utklipp av ubrukte bilder og beholdere.


Docker-tips: Tøm maskinen for søppel

Totalforbruk

Docker er en kul ting, det er nok få som tviler på det i dag. For bare noen få år siden ga dette produktet oss en helt ny måte å bygge, levere og kjøre ethvert miljø på, noe som gjorde at vi kunne spare CPU- og RAM-ressurser betydelig. I tillegg til dette (og for noen vil dette være det viktigste) har Docker tillatt oss å utrolig forenkle og forene livssyklusadministrasjonen til produksjonsmiljøene våre.

Imidlertid har alle disse herlighetene i det moderne livet en pris. Når vi kjører containere, laster ned eller lager våre egne bilder og distribuerer komplekse økosystemer, må vi betale. Og vi betaler blant annet med diskplass.

Hvis du aldri har tenkt på hvor mye plass Docker faktisk tar på maskinen din, kan du bli ubehagelig overrasket over resultatet av denne kommandoen:

$ docker system df

Docker-tips: Tøm maskinen for søppel

Dette viser Dockers diskbruk i forskjellige sammenhenger:

  • bilder – den totale størrelsen på bilder som ble lastet ned fra bildelager og bygget på systemet ditt;
  • containere – den totale mengden diskplass som brukes av å kjøre containere (som betyr det totale volumet av lese-skrive-lag for alle containere);
  • lokale volumer - volumet av lokal lagring montert på containere;
  • build cache – midlertidige filer generert av bildebyggingsprosessen (ved hjelp av BuildKit-verktøyet, tilgjengelig fra Docker versjon 18.09).

Jeg vedder på at du etter denne enkle overføringen er ivrig etter å rense disken for søppel og bringe dyrebare gigabyte til live igjen (merk: spesielt hvis du betaler leie for disse gigabytene hver måned).

Diskbruk av containere

Hver gang du oppretter en container på vertsmaskinen, opprettes flere filer og kataloger i /var/lib/docker-katalogen, blant annet er følgende verdt å merke seg:

  • Katalog /var/lib/docker/containers/container_ID – når du bruker standard loggingsdriver, er det her hendelseslogger lagres i JSON-format. For detaljerte logger, samt logger som ingen leser eller på annen måte behandler, fører ofte til at diskene blir fulle.
  • /var/lib/docker/overlay2-katalogen inneholder container-lese-skrive-lagene (overlay2 er den foretrukne driveren i de fleste Linux-distribusjoner). Hvis beholderen lagrer data i filsystemet, er det i denne katalogen den vil bli plassert.

La oss forestille oss et system der en uberørt Docker er installert, som aldri har vært involvert i oppskyting av containere eller bygging av bilder. Diskplassbruksrapporten vil se slik ut:

$ 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

La oss lansere en container, for eksempel NGINX:

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

Hva skjer med disken:

  • bilder opptar 126 MB, dette er den samme NGINX som vi lanserte i containeren;
  • containere tar opp latterlige 2 byte.

$ 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

Etter konklusjonen å dømme har vi foreløpig ingen plass vi kan frigjøre. Siden 2 byte er helt useriøst, la oss forestille oss at vår NGINX uventet skrev et sted 100 megabyte med data og opprettet en fil test.img av nøyaktig denne størrelsen i seg selv.

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

La oss undersøke diskplassbruken på verten igjen. Vi vil se at containeren (beholderne) opptar 100 megabyte der.

$ 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

Jeg tror din nysgjerrige hjerne allerede lurer på hvor test.img-filen vår ligger. La oss se etter det:

$ 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

Uten å gå inn på detaljer kan vi merke oss at test.img-filen er praktisk plassert på lese-skrivenivå, kontrollert av overlay2-driveren. Hvis vi stopper containeren vår, vil verten fortelle oss at denne plassen i prinsippet kan frigjøres:

# 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

Hvordan kan vi gjøre dette? Ved å slette beholderen, noe som vil innebære å tømme den tilsvarende plassen på lese-skrivenivå.

Med følgende kommando kan du fjerne alle installerte beholdere med ett slag og tømme disken for alle lese-skrive-filer som er opprettet av dem:

$ 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

Så vi frigjorde 104,9 megabyte ved å slette beholderen. Men siden vi ikke lenger bruker det tidligere nedlastede bildet, blir det også en kandidat for å slette og frigjøre ressursene våre:

$ 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

Merk: Så lenge bildet er i bruk av minst én beholder, vil du ikke kunne bruke dette trikset.

Sviske-underkommandoen vi brukte ovenfor har kun effekt på stoppede beholdere. Hvis vi ønsker å slette ikke bare stoppede, men også kjørende beholdere, bør vi bruke en av disse kommandoene:

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

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

Sidemerknader: Hvis du bruker parameteren -rm når du starter en beholder, vil all diskplass som den tok opp, frigjøres når den stopper.

Bruke diskbilder

For noen år siden var en bildestørrelse på flere hundre megabyte helt normal: Et Ubuntu-bilde veide 600 megabyte, og et Microsoft .Net-bilde veide flere gigabyte. I disse raggete dagene kunne nedlasting av bare ett bilde ta store belastninger på den ledige diskplassen din, selv om du delte nivåer mellom bilder. I dag – priset være de store – veier bilder mye mindre, men likevel kan du raskt fylle opp de tilgjengelige ressursene hvis du ikke tar noen forholdsregler.

Det finnes flere typer bilder som ikke er direkte synlige for sluttbrukeren:

  • mellombilder, på grunnlag av hvilke andre bilder samles inn - de kan ikke slettes hvis du bruker beholdere basert på disse "andre" bildene;
  • dinglende bilder er mellombilder som ikke refereres til av noen av de kjørende beholderne - de kan slettes.
  • Med følgende kommando kan du se etter hengende bilder på systemet ditt:

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

Du kan fjerne dem på følgende måte:

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

Vi kan også bruke underkommandoen prune:

$ 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

Hvis vi plutselig ønsker å slette alle bilder helt (og ikke bare dinglende) med én kommando, kan vi gjøre dette:

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

Diskbruk etter volumer

Volumer brukes til å lagre data utenfor containerens filsystem. For eksempel hvis vi ønsker å lagre resultatene av en applikasjon for å bruke dem på en annen måte. Et vanlig eksempel er databaser.

La oss starte en MongoDB-beholder, montere et volum utenfor beholderen og gjenopprette en databasesikkerhetskopi fra den (vi har den tilgjengelig i bck.json-filen):

# 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

Dataene vil bli plassert på vertsmaskinen i katalogen /var/lib/docker/volumes. Men hvorfor ikke på lese-skrivenivået til beholderen? Fordi i Dockerfilen til MongoDB-bildet, er /data/db-katalogen (der MongoDB lagrer data som standard) definert som et volum.

Docker-tips: Tøm maskinen for søppel

Sidenotat: mange bilder som må produsere data bruker volumer for å lagre disse dataene.

Når vi spiller nok med MongoDB og stopper (eller kanskje til og med sletter) beholderen, vil ikke volumet bli slettet. Den vil fortsette å ta opp vår dyrebare diskplass til vi eksplisitt sletter den med en kommando som denne:

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

Vel, eller vi kan bruke prune-underkommandoen som allerede er kjent for oss:

$ 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:~$

Bruker disk for image build cache

I Docker 18.09 har bildeopprettingsprosessen gjennomgått noen endringer takket være BuildKit-verktøyet. Denne tingen øker hastigheten på prosessen og optimerer datalagring og sikkerhetsstyring. Her vil vi ikke vurdere alle detaljene i dette fantastiske verktøyet; vi vil bare fokusere på hvordan det løser problemer med diskplassbruk.

La oss si at vi har en helt enkel Node.Js-applikasjon:

  • index.js-filen starter en enkel HTTP-server som svarer med en linje på hver forespørsel som mottas:
  • filen package.json definerer avhengighetene, hvorav kun expressjs brukes til å kjøre HTTP-serveren:

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

Dockerfilen for å bygge bildet ser slik ut:

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

La oss bygge bildet på vanlig måte, uten å bruke BuildKit:

$ docker build -t app:1.0 .

Hvis vi sjekker diskplassbruken, kan vi se at bare basisbildet (node:13-alpine) og destinasjonsbildet (app:1.0) tar opp plass:

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

La oss bygge den andre versjonen av applikasjonen vår ved å bruke BuildKit. For å gjøre dette trenger vi bare å sette DOCKER_BUILDKIT-variabelen til 1:

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

Hvis vi nå sjekker diskbruken, vil vi se at build-cachen (buid-cache) nå er involvert der:

$ 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

For å fjerne det, bruk følgende kommando:

$ 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

Rydd alt!

Så vi så på å rydde opp diskplass okkupert av containere, bilder og volumer. Sviske-underkommandoen hjelper oss med dette. Men den kan også brukes på docker-systemnivå, og den vil rydde opp i alt den 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]

Hvis du av en eller annen grunn sparer diskplass på Docker-maskinen, bør det bli en vane å kjøre denne kommandoen med jevne mellomrom.

Kilde: www.habr.com

Legg til en kommentar