Nasveti za Docker: Počistite svoj stroj smeti

Nasveti za Docker: Počistite svoj stroj smeti

Hej Habr! Predstavljam vam prevod članka "Docker Nasveti: Očistite svoj lokalni stroj" avtor Luc Juggery.

Danes bomo govorili o tem, kako Docker uporablja prostor na disku gostiteljskega računalnika, in ugotovili bomo tudi, kako ta prostor osvoboditi ostankov neuporabljenih slik in vsebnikov.


Nasveti za Docker: Počistite svoj stroj smeti

Skupna poraba

Docker je kul zadeva, verjetno danes malokdo dvomi o tem. Samo nekaj let nazaj nam je ta izdelek dal popolnoma nov način za izdelavo, dostavo in izvajanje katerega koli okolja, kar nam je omogočilo znatno varčevanje z viri CPE in RAM. Poleg tega (in za nekatere bo to najpomembnejše) nam je Docker omogočil neverjetno poenostavitev in poenotenje upravljanja življenjskega cikla naših proizvodnih okolij.

Vse te slasti sodobnega življenja pa imajo svojo ceno. Ko izvajamo vsebnike, prenašamo ali ustvarjamo lastne slike in uvajamo kompleksne ekosisteme, moramo plačati. In plačujemo med drugim s prostorom na disku.

Če še nikoli niste razmišljali o tem, koliko prostora Docker dejansko zavzame na vašem računalniku, vas bo rezultat tega ukaza morda neprijetno presenetil:

$ docker system df

Nasveti za Docker: Počistite svoj stroj smeti

To prikazuje Dockerjevo uporabo diska v različnih kontekstih:

  • slike – skupna velikost slik, ki so bile prenesene iz repozitorijev slik in izdelane v vašem sistemu;
  • vsebniki – skupna količina prostora na disku, ki ga uporabljajo izvajajoči se vsebniki (kar pomeni skupno količino bralno-pisalnih slojev vseh vsebnikov);
  • lokalni volumni – prostornina lokalnega skladišča, nameščenega na zabojnike;
  • gradbeni predpomnilnik – začasne datoteke, ustvarjene s postopkom gradnje slike (z uporabo orodja BuildKit, ki je na voljo od različice Docker 18.09).

Stavim, da po tem preprostem prenosu nestrpno želite očistiti svoj disk smeti in oživiti dragocene gigabajte (opomba: še posebej, če vsak mesec plačujete najemnino za te gigabajte).

Poraba diska po vsebnikih

Vsakič, ko ustvarite vsebnik na gostiteljskem računalniku, se v imeniku /var/lib/docker ustvari več datotek in imenikov, med katerimi velja omeniti naslednje:

  • Imenik /var/lib/docker/containers/container_ID – pri uporabi standardnega gonilnika za beleženje se tukaj shranjujejo dnevniki dogodkov v formatu JSON. Preveč podrobni dnevniki, pa tudi dnevniki, ki jih nihče ne bere ali kako drugače obdeluje, pogosto povzročijo polnost diskov.
  • Imenik /var/lib/docker/overlay2 vsebuje plasti vsebnika za branje in pisanje (overlay2 je prednostni gonilnik v večini distribucij Linuxa). Če vsebnik hrani podatke v svojem datotečnem sistemu, potem bodo postavljeni v ta imenik.

Predstavljajmo si sistem, na katerem je nameščen nedotaknjen Docker, ki nikoli ni sodeloval pri zagonu vsebnikov ali gradnji slik. Njegovo poročilo o uporabi prostora na disku bo videti takole:

$ 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

Zaženimo vsebnik, na primer NGINX:

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

Kaj se zgodi z diskom:

  • slike zasedajo 126 MB, to je isti NGINX, ki smo ga zagnali v vsebniku;
  • vsebniki zavzamejo smešna 2 bajta.

$ 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

Po sklepu sodeč še nimamo prostora, ki bi ga lahko sprostili. Ker sta 2 bajta popolnoma neresna, si predstavljajmo, da je naš NGINX nepričakovano zapisal nekje 100 megabajtov podatkov in v sebi ustvaril točno tolikšno datoteko test.img.

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

Ponovno preučimo porabo prostora na disku na gostitelju. Videli bomo, da vsebnik (vsebniki) tam zaseda 100 megabajtov.

$ 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

Mislim, da se vaši vedoželjni možgani že sprašujejo, kje se nahaja naša datoteka test.img. Poiščimo ga:

$ 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

Ne da bi se spuščali v podrobnosti, lahko opazimo, da je datoteka test.img priročno nameščena na ravni branja in pisanja, ki jo nadzira gonilnik overlay2. Če zaustavimo naš vsebnik, nam bo gostitelj povedal, da se ta prostor načeloma lahko sprosti:

# 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

Kako lahko to storimo? Z brisanjem vsebnika, kar bo povzročilo čiščenje ustreznega prostora na ravni branja in pisanja.

Z naslednjim ukazom lahko z enim zamahom odstranite vse nameščene vsebnike in počistite disk vseh datotek za branje in pisanje, ki so jih ustvarili:

$ 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

Tako smo z brisanjem vsebnika sprostili 104,9 megabajtov. Ker pa prej prenesene slike ne uporabljamo več, postane tudi kandidatka za brisanje in sprostitev naših virov:

$ 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

Opomba: Dokler sliko uporablja vsaj en vsebnik, tega trika ne boste mogli uporabiti.

Podukaz prune, ki smo ga uporabili zgoraj, vpliva le na ustavljene vsebnike. Če želimo izbrisati ne le ustavljene, ampak tudi delujoče vsebnike, moramo uporabiti enega od teh ukazov:

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

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

Stranske opombe: če ob zagonu vsebnika uporabite parameter -rm, se bo, ko se ustavi, sprostil ves prostor na disku, ki ga je zasedel.

Uporaba slik diska

Pred nekaj leti je bila slika velikosti nekaj sto megabajtov povsem normalna: slika Ubuntuja je tehtala 600 megabajtov, slika Microsoft .Net pa več gigabajtov. V tistih kosmatih dneh bi lahko prenos samo ene slike močno obremenil vaš prosti prostor na disku, tudi če bi delili ravni med slikami. Danes - hvala velikim - slike tehtajo veliko manj, a kljub temu lahko hitro zapolnite razpoložljive vire, če ne upoštevate nekaterih previdnostnih ukrepov.

Obstaja več vrst slik, ki niso neposredno vidne končnemu uporabniku:

  • vmesne slike, na podlagi katerih se zbirajo druge slike - ni jih mogoče izbrisati, če uporabljate vsebnike, ki temeljijo na teh "drugih" slikah;
  • viseče slike so vmesne slike, na katere se ne sklicuje noben od tekočih vsebnikov - lahko jih izbrišete.
  • Z naslednjim ukazom lahko preverite viseče slike v vašem sistemu:

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

Odstranite jih lahko na naslednji način:

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

Uporabimo lahko tudi podukaz 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

Če nenadoma želimo z enim ukazom izbrisati vse slike skupaj (in ne samo viseče), potem lahko naredimo to:

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

Poraba diska po količinah

Zvezki se uporabljajo za shranjevanje podatkov zunaj datotečnega sistema vsebnika. Na primer, če želimo shraniti rezultate aplikacije, da bi jih uporabili na drug način. Pogost primer so baze podatkov.

Zaženimo vsebnik MongoDB, priklopimo nosilec, ki je zunaj vsebnika, in iz njega obnovimo varnostno kopijo baze podatkov (na voljo jo imamo v datoteki 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

Podatki se bodo nahajali na gostiteljskem računalniku v imeniku /var/lib/docker/volumes. Toda zakaj ne na nivoju branja in pisanja vsebnika? Ker je v datoteki Dockerfile slike MongoDB imenik /data/db (kjer MongoDB privzeto shranjuje svoje podatke) opredeljen kot nosilec.

Nasveti za Docker: Počistite svoj stroj smeti

Dodatna opomba: številne slike, ki morajo proizvesti podatke, uporabljajo količine za shranjevanje teh podatkov.

Ko se dovolj poigramo z MongoDB in ustavimo (ali morda celo izbrišemo) vsebnik, nosilec ne bo izbrisan. Še naprej bo zasedal naš dragoceni prostor na disku, dokler ga izrecno ne izbrišemo z ukazom, kot je ta:

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

No, lahko pa uporabimo podukaz prune, ki nam je že znan:

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

Uporaba diska za predpomnilnik gradnje slik

V Dockerju 18.09 je bil postopek ustvarjanja slike zaradi orodja BuildKit nekaj spremenjen. Ta stvar poveča hitrost procesa in optimizira shranjevanje podatkov in upravljanje varnosti. Tukaj ne bomo obravnavali vseh podrobnosti tega čudovitega orodja; osredotočili se bomo le na to, kako obravnava težave z uporabo prostora na disku.

Recimo, da imamo popolnoma preprosto aplikacijo Node.Js:

  • datoteka index.js zažene preprost strežnik HTTP, ki odgovori z vrstico na vsako prejeto zahtevo:
  • datoteka package.json definira odvisnosti, od katerih se samo expressjs uporablja za zagon strežnika HTTP:

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

Datoteka Docker za izdelavo slike je videti takole:

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

Zgradimo sliko na običajen način, brez uporabe BuildKita:

$ docker build -t app:1.0 .

Če preverimo porabo prostora na disku, lahko vidimo, da samo osnovna slika (node:13-alpine) in ciljna slika (app:1.0) zasedata prostor:

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

Zgradimo drugo različico naše aplikacije z uporabo BuildKita. Če želite to narediti, moramo le nastaviti spremenljivko DOCKER_BUILDKIT na 1:

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

Če zdaj preverimo uporabo diska, bomo videli, da je predpomnilnik gradnje (buid-cache) zdaj vključen tam:

$ 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

Če ga želite počistiti, uporabite naslednji ukaz:

$ 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

Počisti vse!

Torej smo preučili čiščenje prostora na disku, ki ga zasedajo vsebniki, slike in nosilci. Pri tem nam pomaga podukaz prune. Lahko pa se uporablja tudi na ravni docker sistema in počistil bo vse, kar lahko:

$ 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]

Če iz nekega razloga varčujete s prostorom na disku na računalniku, na katerem se izvaja Docker, bi moralo redno izvajanje tega ukaza postati navada.

Vir: www.habr.com

Dodaj komentar