Docker savjeti: Očistite svoj stroj od smeća

Docker savjeti: Očistite svoj stroj od smeća

Hej Habr! Vašoj pozornosti predstavljam prijevod članka "Docker savjeti: Očistite svoj lokalni stroj" Autor Luc Juggery.

Danas ćemo govoriti o tome kako Docker koristi prostor na disku glavnog računala, a također ćemo smisliti kako osloboditi ovaj prostor od ostataka neiskorištenih slika i spremnika.


Docker savjeti: Očistite svoj stroj od smeća

Ukupna potrošnja

Docker je cool stvar, vjerojatno danas malo tko sumnja u to. Prije samo nekoliko godina, ovaj proizvod nam je dao potpuno novi način za izgradnju, isporuku i pokretanje bilo kojeg okruženja, omogućujući nam da značajno uštedimo CPU i RAM resurse. Uz to (a za neke će to biti najvažnija stvar) Docker nam je omogućio da nevjerojatno pojednostavimo i unificiramo upravljanje životnim ciklusom naših proizvodnih okruženja.

Međutim, sve te užitke modernog života imaju svoju cijenu. Kada pokrećemo spremnike, preuzimamo ili stvaramo vlastite slike i implementiramo složene ekosustave, 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šem računalu, mogli biste se neugodno iznenaditi rezultatom ove naredbe:

$ docker system df

Docker savjeti: Očistite svoj stroj od smeća

Ovo pokazuje Dockerovu upotrebu diska u različitim kontekstima:

  • slike – ukupna veličina slika koje su preuzete iz repozitorija slika i izgrađene na vašem sustavu;
  • spremnici – ukupna količina diskovnog prostora koju koriste spremnici (što znači ukupnu količinu slojeva za čitanje i pisanje svih spremnika);
  • lokalni volumeni – volumen lokalnog skladišta montiranog na kontejnere;
  • predmemorija izgradnje – privremene datoteke generirane procesom izrade slike (pomoću alata BuildKit, dostupnog počevši od Docker verzije 18.09).

Kladim se da ste nakon ovog jednostavnog prijenosa željni očistiti svoj disk od smeća i vratiti dragocjene gigabajte u život (napomena: pogotovo ako plaćate najam za te gigabajte svaki mjesec).

Upotreba diska po spremnicima

Svaki put kada stvorite spremnik na glavnom računalu, nekoliko datoteka i direktorija se stvara u direktoriju /var/lib/docker, među kojima je vrijedno pažnje sljedeće:

  • Direktorij /var/lib/docker/containers/container_ID – kada koristite standardni upravljački program za bilježenje, ovdje se spremaju zapisnici događaja u JSON formatu. Pretjerano detaljni zapisnici, kao i zapisnici koje nitko ne čita ili na neki drugi način ne obrađuje, često uzrokuju da se diskovi popune.
  • Direktorij /var/lib/docker/overlay2 sadrži slojeve spremnika za čitanje i pisanje (overlay2 je preferirani pokretački program u većini distribucija Linuxa). Ako spremnik pohranjuje podatke u svom datotečnom sustavu, tada će biti smješteni u ovaj direktorij.

Zamislimo sustav na kojem je instaliran netaknuti Docker, koji nikada nije bio uključen u pokretanje spremnika ili izgradnju slika. Izvješće o korištenju prostora na disku izgledat će 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 spremnik, na primjer, NGINX:

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

Što se događa s diskom:

  • slike zauzimaju 126 MB, ovo je isti NGINX koji smo pokrenuli u spremniku;
  • spremnici 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 prema zaključku, još nemamo prostora koji bismo mogli osloboditi. Budući da su 2 bajta potpuno neozbiljna, zamislimo da je naš NGINX neočekivano upisao negdje 100 megabajta podataka i unutar sebe napravio datoteku test.img točno te veličine.

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

Ponovno ispitajmo korištenje diskovnog prostora na hostu. Vidjet ćemo da spremnik (spremnici) 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ša datoteka test.img. Potraž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 ulazeći u detalje, možemo primijetiti da je datoteka test.img prikladno smještena na razini čitanja i pisanja, kojom upravlja upravljački program overlay2. Ako zaustavimo naš kontejner, domaćin će nam reći da se taj 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 spremnika, što će podrazumijevati brisanje odgovarajućeg prostora na razini čitanja i pisanja.

Sljedećom naredbom možete jednim potezom ukloniti sve instalirane spremnike i očistiti svoj disk od svih datoteka za čitanje i pisanje koje su kreirali:

$ 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 spremnika. Ali budući da 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 spremnik, nećete moći koristiti ovaj trik.

Podnaredba prune koju smo koristili gore ima učinak samo na zaustavljene spremnike. Ako želimo obrisati ne samo zaustavljene već i pokrenute spremnike, trebali bismo upotrijebiti jednu od ovih naredbi:

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

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

Sporedne napomene: ako koristite parametar -rm prilikom pokretanja spremnika, onda kada se zaustavi, sav prostor na disku koji je zauzeo bit će oslobođen.

Korištenje slika diska

Prije nekoliko godina veličina slike od nekoliko stotina megabajta bila je sasvim normalna: Ubuntu slika bila je teška 600 megabajta, a Microsoft .Net slika nekoliko gigabajta. U tim mračnim danima, preuzimanje samo jedne slike moglo je uzeti veliki danak u vašem slobodnom prostoru na disku, čak i ako ste dijelili razine između slika. Danas - svaka čast velikima - slike teže mnogo manje, ali unatoč tome možete brzo popuniti dostupne resurse ako ne poduzmete neke mjere opreza.

Postoji nekoliko vrsta slika koje nisu izravno vidljive krajnjem korisniku:

  • srednje slike, na temelju kojih se prikupljaju druge slike - ne mogu se izbrisati ako koristite spremnike temeljene na tim "drugim" slikama;
  • viseće slike su međuslike na koje ne upućuje niti jedan spremnik koji se izvodi - mogu se izbrisati.
  • Sljedećom naredbom možete provjeriti viseće slike na vašem sustavu:

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

Također možemo koristiti 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 iznenada poželimo izbrisati sve slike (a ne samo one koje vise) jednom naredbom, možemo učiniti ovo:

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

Upotreba diska prema volumenima

Volumeni se koriste za pohranu podataka izvan datotečnog sustava spremnika. Na primjer, ako želimo spremiti rezultate aplikacije kako bismo ih upotrijebili na neki drugi način. Čest primjer su baze podataka.

Pokrenimo MongoDB spremnik, montirajmo volumen izvan spremnika 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čunalu u direktoriju /var/lib/docker/volumes. Ali zašto ne na razini čitanja i pisanja spremnika? Budući da je u Docker datoteci MongoDB slike direktorij /data/db (gdje MongoDB pohranjuje svoje podatke prema zadanim postavkama) definiran kao volumen.

Docker savjeti: Očistite svoj stroj od smeća

Dodatna napomena: mnoge slike koje moraju proizvesti podatke koriste količine za pohranjivanje tih podataka.

Kada se dovoljno poigramo s MongoDB-om i zaustavimo (ili možda čak izbrišemo) spremnik, volumen neće biti izbrisan. 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 predmemoriju izrade slike

U Dockeru 18.09 proces stvaranja slike je doživio neke promjene zahvaljujući alatu BuildKit. Ova stvar povećava brzinu procesa i optimizira pohranu podataka i upravljanje sigurnošću. Ovdje nećemo razmatrati sve pojedinosti ovog prekrasnog alata; samo ćemo se usredotočiti 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 poslužitelj koji odgovara linijom na svaki primljeni zahtjev:
  • datoteka package.json definira ovisnosti, od kojih se samo expressjs koristi za pokretanje HTTP poslužitelja:

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

Izgradimo sliku na uobičajeni način, bez korištenja BuildKita:

$ docker build -t app:1.0 .

Ako provjerimo iskorištenost prostora na disku, možemo vidjeti da samo osnovna slika (node: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

Izradimo drugu verziju naše aplikacije koristeći BuildKit. Da bismo to učinili, 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 predmemorija izgradnje (buid-cache) sada uključena:

$ 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

Za brisanje upotrijebite 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

Očistiti sve!

Dakle, pogledali smo čišćenje prostora na disku koji zauzimaju spremnici, slike i volumeni. U tome nam pomaže podnaredba prune. Ali također se može koristiti na razini docker sustava 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 računalu koje pokreće Docker, povremeno pokretanje ove naredbe trebalo bi postati navika.

Izvor: www.habr.com

Dodajte komentar