Docker savjeti: Očistite svoju mašinu od smeća

Docker savjeti: Očistite svoju mašinu od smeća

Hej Habr! Predstavljam Vašoj pažnji prevod članka "Savjeti za Docker: očistite svoj lokalni stroj" autor Luc Juggery.

Danas ćemo pričati o tome kako Docker koristi prostor na disku host mašine, a takođe ćemo shvatiti kako da oslobodimo ovaj prostor od ostataka neiskorištenih slika i kontejnera.


Docker savjeti: Očistite svoju mašinu od smeća

Ukupna potrošnja

Docker je kul stvar, vjerovatno malo ljudi danas sumnja u to. Prije samo nekoliko godina, ovaj proizvod nam je dao potpuno nov način za izgradnju, isporuku i pokretanje bilo kojeg okruženja, omogućavajući nam da značajno uštedimo CPU i RAM resurse. Pored ovoga (a za neke će to biti najvažnije) Docker nam je omogućio da nevjerovatno pojednostavimo i objedinimo upravljanje životnim ciklusom naših proizvodnih okruženja.

Međutim, svi ovi užici modernog života imaju svoju cijenu. Kada pokrećemo kontejnere, preuzimamo ili kreiramo vlastite slike i postavljamo složene ekosisteme, moramo platiti. A plaćamo, između ostalog, i prostorom na disku.

Ako nikada niste razmišljali o tome koliko prostora Docker zapravo zauzima na vašoj mašini, možda ćete biti neprijatno iznenađeni izlazom ove naredbe:

$ docker system df

Docker savjeti: Očistite svoju mašinu od smeća

Ovo pokazuje upotrebu Docker diska u različitim kontekstima:

  • slike – ukupna veličina slika koje su preuzete iz skladišta slika i izgrađene na vašem sistemu;
  • kontejneri – ukupna količina prostora na disku koji se koristi za pokretanje kontejnera (što znači ukupan volumen slojeva čitanja i pisanja svih kontejnera);
  • lokalni volumeni – volumen lokalne memorije montirane na kontejnere;
  • build cache – privremene datoteke generirane procesom izgradnje slike (pomoću alata BuildKit, dostupnog počevši od Docker verzije 18.09).

Kladim se da ste nakon ovog jednostavnog prijenosa željni da očistite svoj disk od smeća i oživite dragocjene gigabajte (napomena: posebno ako plaćate kiriju za ove gigabajte svakog mjeseca).

Upotreba diska po kontejnerima

Svaki put kada kreirate kontejner na glavnom računaru, nekoliko fajlova i direktorijuma se kreira u /var/lib/docker direktorijumu, među kojima je vredno napomenuti sledeće:

  • Direktorij /var/lib/docker/containers/container_ID – kada se koristi standardni drajver za evidentiranje, ovo je mjesto gdje se zapisnici događaja čuvaju u JSON formatu. Previše detaljni logovi, kao i zapisi koje niko ne čita ili na drugi način obrađuje, često uzrokuju da se diskovi prepune.
  • Direktorij /var/lib/docker/overlay2 sadrži slojeve za čitanje i upisivanje spremnika (overlay2 je preferirani upravljački program u većini Linux distribucija). Ako kontejner pohranjuje podatke u svoj sistem datoteka, onda će se nalaziti u ovom direktoriju.

Zamislimo sistem na kojem je instaliran netaknuti Docker, koji nikada nije bio uključen u pokretanje kontejnera ili izgradnju slika. Njegov izvještaj o korištenju prostora na disku će izgledati ovako:

$ 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

Pokrenimo neki kontejner, na primjer, NGINX:

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

Šta se dešava sa diskom:

  • slike zauzimaju 126 MB, ovo je isti NGINX koji smo pokrenuli u kontejneru;
  • kontejneri zauzimaju smiješ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

Sudeći po zaključku, još nemamo prostor koji bismo mogli osloboditi. Pošto su 2 bajta potpuno neozbiljna, zamislimo da je naš NGINX neočekivano napisao negdje 100 megabajta podataka i kreirao datoteku test.img upravo ove veličine unutar sebe.

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

Hajde da ponovo ispitamo korišćenje prostora na disku na hostu. Vidjet ćemo da kontejner (kontejneri) tamo zauzima 100 megabajta.

$ 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š radoznali mozak već pita gdje se nalazi naš test.img fajl. Hajde da ga potražimo:

$ 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 ulazeći u detalje, možemo primetiti da je test.img fajl pogodno lociran na nivou čitanja i pisanja, koji kontroliše overlay2 drajver. Ako zaustavimo naš kontejner, domaćin će nam reći da se ovaj prostor u principu može osloboditi:

# 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 to možemo učiniti? Brisanjem kontejnera, što će podrazumijevati brisanje odgovarajućeg prostora na nivou čitanja-pisanja.

Sa sljedećom naredbom možete ukloniti sve instalirane kontejnere jednim potezom i očistiti disk od svih datoteka koje su kreirali za čitanje i upisivanje:

$ 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

Dakle, oslobodili smo 104,9 megabajta brisanjem kontejnera. Ali pošto više ne koristimo prethodno preuzetu sliku, ona također postaje kandidat za brisanje i oslobađanje naših resursa:

$ 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

Napomena: Sve dok sliku koristi barem jedan kontejner, nećete moći koristiti ovaj trik.

Podnaredba prune koju smo koristili iznad ima učinak samo na zaustavljene kontejnere. Ako želimo izbrisati ne samo zaustavljene već i pokrenute kontejnere, trebali bismo koristiti jednu od ovih naredbi:

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

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

Napomene: ako koristite parametar -rm prilikom pokretanja kontejnera, onda kada se zaustavi, sav prostor na disku koji je zauzimao bit će oslobođen.

Korištenje slika diska

Prije nekoliko godina, veličina slike od nekoliko stotina megabajta bila je sasvim normalna: Ubuntu slika je bila teška 600 megabajta, a Microsoft .Net slika nekoliko gigabajta. U tim mučnim danima, preuzimanje samo jedne slike moglo bi uzeti veliki danak na vašem slobodnom prostoru na disku, čak i ako dijelite nivoe između slika. Danas – svaka čast – slike teže mnogo manje, ali čak i tako, možete brzo napuniti raspoložive resurse ako ne preduzmete neke mjere opreza.

Postoji nekoliko vrsta slika koje nisu direktno vidljive krajnjem korisniku:

  • međuslike, na osnovu kojih se prikupljaju druge slike - one se ne mogu izbrisati ako koristite kontejnere na osnovu ovih „drugih“ slika;
  • viseće slike su posredne slike koje ne referencira nijedan od pokrenutih kontejnera - mogu se izbrisati.
  • Sa sljedećom naredbom možete provjeriti ima li visećih slika na vašem sistemu:

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

Možete ih ukloniti na sljedeći način:

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

Možemo koristiti i podnaredbu 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

Ako odjednom poželimo da obrišemo sve slike zajedno (a ne samo viseće) jednom komandom, onda možemo učiniti ovo:

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

Korištenje diska po volumenima

Volumi se koriste za skladištenje podataka izvan sistema datoteka kontejnera. Na primjer, ako želimo da sačuvamo rezultate aplikacije da bismo ih koristili na neki drugi način. Uobičajeni primjer su baze podataka.

Pokrenimo MongoDB kontejner, montiramo volumen izvan kontejnera i vratimo sigurnosnu kopiju baze podataka iz njega (imamo je dostupnu u datoteci 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

Podaci će se nalaziti na glavnom računaru u direktoriju /var/lib/docker/volumes. Ali zašto ne na nivou čitanja i pisanja kontejnera? Zato što je u Dockerfile-u slike MongoDB, direktorij /data/db (gdje MongoDB po defaultu pohranjuje svoje podatke) definiran kao volumen.

Docker savjeti: Očistite svoju mašinu od smeća

Napomena: mnoge slike koje moraju proizvesti podatke koriste volumene za pohranjivanje tih podataka.

Kada se dovoljno igramo sa MongoDB i zaustavimo (ili možda čak izbrišemo) kontejner, volumen neće biti obrisan. Nastavit će zauzimati naš dragocjeni prostor na disku sve dok ga eksplicitno ne izbrišemo naredbom poput ove:

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

Pa, ili možemo koristiti podnaredbu prune koja nam je već poznata:

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

Korištenje diska za keš za izgradnju slike

U Dockeru 18.09, proces kreiranja slike je prošao kroz neke promjene zahvaljujući alatu BuildKit. Ova stvar povećava brzinu procesa i optimizuje skladištenje podataka i upravljanje sigurnošću. Ovdje nećemo razmatrati sve detalje ovog divnog alata; samo ćemo se fokusirati na to kako rješava probleme korištenja prostora na disku.

Recimo da imamo potpuno jednostavnu Node.Js aplikaciju:

  • datoteka index.js pokreće jednostavan HTTP server koji odgovara linijom na svaki primljeni zahtjev:
  • datoteka package.json definira zavisnosti, od kojih se samo expressjs koristi za pokretanje HTTP servera:

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

Dockerfile za pravljenje slike izgleda ovako:

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

Napravimo sliku na uobičajen način, bez upotrebe BuildKit-a:

$ docker build -t app:1.0 .

Ako provjerimo korištenje prostora na disku, možemo vidjeti da samo osnovna slika (čvor:13-alpine) i odredišna slika (app:1.0) zauzimaju 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

Napravimo drugu verziju naše aplikacije, koristeći BuildKit. Da bismo to uradili, samo trebamo postaviti varijablu DOCKER_BUILDKIT na 1:

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

Ako sada provjerimo korištenje diska, vidjet ćemo da je keš za izgradnju (buid-cache) sada uključen tamo:

$ 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

Da ga obrišete, koristite sljedeću naredbu:

$ 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

Obriši sve!

Dakle, pogledali smo čišćenje prostora na disku koji zauzimaju kontejneri, slike i volumeni. U tome nam pomaže potkomanda prune. Ali može se koristiti i na nivou sistema docker, i očistit će sve što može:

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

Ako iz nekog razloga štedite prostor na disku na mašini na kojoj je pokrenut Docker, onda bi periodično izvršavanje ove naredbe trebalo postati navika.

izvor: www.habr.com

Dodajte komentar