
Bok, Habr! Predstavljam vam prijevod članka autor .
Danas ćemo razgovarati o tome kako Docker koristi diskovni prostor domaćina, kao i kako osloboditi taj prostor od ostataka neiskorištenih slika i kontejnera.

Ukupna potrošnja
Docker je stvarno sjajna stvar, danas vjerojatno malo tko o tome sumnja. Prije nekoliko godina, ovaj proizvod nam je pružio potpuno novi način izgradnje, isporuke i pokretanja bilo kojeg okruženja, omogućujući nam da značajno uštedimo resurse procesora i radne memorije. Pored toga (a za neke će to biti čak i najvažnije), Docker nam je omogućio nevjerojatno pojednostavljenje i unifikaciju upravljanja životnim ciklom korištenih radnih okruženja.
Međutim, za sve te blagodati modernog života potrebno je platiti. Kada pokrećemo kontejnere, preuzimamo ili stvaramo vlastite slike, postavljamo složene ekosustave, moramo platiti. I plaćamo, između ostalog, diskovnim prostorom.
Ako nikada niste razmišljali o tome koliko prostora zapravo zauzima vaš Docker, moglo bi vas neugodno iznenaditi izlaz ove naredbe:
$ docker system df 
Ovdje se prikazuje korištenje diska Docker-a u različitim segmentima:
- slike (images) – ukupna veličina slika koje su preuzete iz spremišta slika i izgrađene u vašem sustavu;
- kontejneri (containers) – ukupni volumen diskovnog prostora koji koriste pokrenuti kontejneri (misli se na ukupni volumen slojeva za čitanje i pisanje svih kontejnera);
- lokalni volumeni (local volumes) – volumen lokalnih spremišta montiranih na kontejnere;
- keš izgradnje (build cache) – privremene datoteke generirane procesom izgradnje slika (prilikom korištenja alata BuildKit, dostupnog od Docker verzije 18.09).
Sigurno se kockam da se već nakon ovog jednostavnog nabrajanja palite željom da očistite disk od smeća i vratite u život dragocjene gigabajte (napomena: posebno, ako mjesečno plaćate najam za te gigabajte).
Korištenje diska od strane kontejnera
Svaki put kada se stvori kontejner na domaćem stroju, u direktoriju /var/lib/docker stvara se nekoliko datoteka i direktorija, među kojima vrijedi istaknuti sljedeće:
- Katalog /var/lib/docker/containers/ID_kontejnera – kada se koristi standardni driver za logiranje, upravo ovdje se pohranjuju dnevnici događaja u JSON formatu. Previše detaljni dnevnici, kao i dnevnici koje nitko ne čita i ne obrađuje na druge načine, često postaju uzrok preopterećenja diskova.
- Katalog /var/lib/docker/overlay2 – sadrži slojeve za čitanje i pisanje kontejnera (overlay2 je preferirani driver u većini Linux distribucija). Ako kontejner pohranjuje podatke u vlastitom datotečnom sustavu, oni će biti smješteni upravo u ovom katalogu.
Zamislimo sustav na kojem je instaliran netaknut Docker, koji nikada nije pokrenuo kontejner niti sastavio slike. Njegov izvještaj o korištenju diska izgledat će ovako:
$ docker system df
TIPA UKUPNO AKTIVNO VELIČINA OSLOBODIVO
Slike 0 0 0B 0B
Kontejneri 0 0 0B 0B
Lokalni volumeni 0 0 0B 0B
Predmemorija 0 0 0B 0BPokrenimo neki kontejner, na primjer, NGINX:
$ docker container run --name www -d -p 8000:80 nginx:1.16Što se događa s diskom:
- slike (images) zauzimaju 126 MB, to je onaj NGINX koji smo pokrenuli u kontejneru;
- kontejneri (containers) zauzimaju smiješnih 2 bajta.
$ docker system df
TIPA UKUPNO AKTIVNO VELIČINA OSLOBODIVO
Slike 1 1 126M 0B (0%)
Kontejneri 1 1 2B 0B (0%)
Lokalni volumeni 0 0 0B 0B
Predmemorija 0 0 0B 0BSudeći prema izlazu, još uvijek nemamo prostora koji bismo mogli osloboditi. Budući da je 2 bajta sasvim neozbiljno, zamislimo da je naš NGINX iznenada zapisao negdje 100 Megabajta podataka i stvorio unutar sebe datoteku test.img upravo te veličine.
$ docker exec -ti www
dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*100]Ponovno istražujemo korištenje diska na hostu. Vidjet ćemo da kontejner (containers) zauzima 100 Megabajta.
$ docker system df
TIPA UKUPNO AKTIVNO VELIČINA OSLOBODIVO
Slike 1 1 126M 0B (0%)
Kontejneri 1 1 104.9MB 0B (0%)
Lokalni volumeni 0 0 0B 0B
Predmemorija 0 0 0B 0BMislim da se vaš znatiželjni um već pita, gdje se nalazi naša datoteka test.img. Potražimo je:
$ 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.imgNe ulazeći u detalje, može se primijetiti da se datoteka test.img praktično smjestila na razini čitanja i pisanja, kojom upravlja overlay2 drajver. Ako zaustavimo naš kontejner, domaćin će nas obavijestiti da se to mjesto, u osnovi, 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 0BKako to možemo učiniti? Brisanjem kontejnera, što će uzrokovati čišćenje odgovarajućeg prostora na razini čitanja i pisanja.
Pomoću sljedeće komande možete odjednom ukloniti sve instalirane kontejnere i očistiti vaš disk od svih datoteka koje su stvorili na razini čitanja i pisanja:
$ docker container prune
WARNING! Ovo će ukloniti sve zaustavljene kontejnere.
Da li ste sigurni da želite nastaviti? [y/N] y
Uklonjeni kontejneri:
5e7f8e5097ace9ef5518ebf0c6fc2062ff024efb495f11ccc89df21ec9b4dcc2
Ukupno oslobođeni prostor: 104.9MBDakle, oslobodili smo 104,9 megabajta brisanjem kontejnera. No, budući da više ne koristimo ranije preuzetu sliku, ona također postaje kandidat za brisanje i oslobađanje naših resursa:
$ docker system df
TIP TOTAL ACTIVE SIZE RECLAIMABLE
Slike 1 0 126M 126M (100%)
Kontejneri 0 0 0B 0B
Lokalni volumeni 0 0 0B 0B
Cache gradnje 0 0 0B 0BPažnja: sve dok se slika koristi barem od jedne kontejnera, nećete moći koristiti ovu foru.
Podkomanda prune, koju smo koristili gore, daje učinak samo na zaustavljenim kontejnerima. Ako želimo ukloniti ne samo zaustavljene, već i pokrenute kontejnere, trebali bismo koristiti jednu od ovih komandi:
# Historical command
$ docker rm -f $(docker ps –aq)
# More recent command
$ docker container rm -f $(docker container ls -aq)Bilješke na margini: ako prilikom pokretanja kontejnera koristite parametar --rm, tada će pri njegovom zaustavljanju biti oslobođen sav prostor na disku koji je zauzimao.
Korištenje diska slikama
Prije nekoliko godina veličina slike od nekoliko stotina megabajta bila je sasvim normalna: slika Ubuntu-a je težila 600 megabajta, a slika Microsoft .Net nekoliko gigabajta. U to doba, preuzimanje jedne slike moglo je znatno naštetiti vašem slobodnom prostoru na disku, čak i ako ste dijelili nivoe između slika. Danas – hvala velikim – slike su mnogo manje, ali čak i tada može brzo doći do zasićenja raspoloživih resursa ako se ne poduzmu određene mjere opreza.
Postoji nekoliko tipova slika koje nisu izravno vidljive krajnjem korisniku:
- intermediate slike, na temelju kojih su prikupljene druge slike - ne mogu se izbrisati ako koristite kontejnere koji se temelje na tim drugim slikama;
- dangling slike - to su intermediate slike na koje se ne poziva nijedan pokrenuti kontejner - mogu se izbrisati.
- Pomoću sljedeće naredbe možete provjeriti postoje li dangling slike u vašem sustavu:
$ docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
none none 21e658fe5351 prije 12 minuta 71.3MBMožete ih izbrisati 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! Ovo će ukloniti sve dangling slike.
Jeste li sigurni da želite nastaviti? [y/N] y
Izbrisane slike:
izbrisano: sha256:143407a3cb7efa6e95761b8cd6cea25e3f41455be6d5e7cda
izbrisano: sha256:738010bda9dd34896bac9bbc77b2d60addd7738ad1a95e5cc
izbrisano: sha256:fa4f0194a1eb829523ecf3bad04b4a7bdce089c8361e2c347
izbrisano: sha256:c5041938bcb46f78bf2f2a7f0a0df0eea74c4555097cc9197
izbrisano: sha256:5945bb6e12888cf320828e0fd00728947104da82e3eb4452f
Ukupno povraćeno prostora: 12.9kBAko bismo željeli izbrisati sve slike (ne samo dangling) s jednom naredbom, možemo to učiniti na sljedeći način:
$ docker image rm $(docker image ls -q)Korištenje diska putem volumena
Volumeni se koriste za pohranu podataka izvan datotečnog sustava kontejnera. Na primjer, ako želimo sačuvati rezultate rada neke aplikacije kako bismo ih kasnije koristili. Čest primjer su baze podataka.
Pokrenimo MongoDB kontejner, povežimo mu vanjski volumen i obnovimo iz njega backup baze podataka (dostupan nam je 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
--jsonArrayPodaci će se nalaziti na domaćem stroju u katalogu /var/lib/docker/volumes. Zašto ne na razini čitanja-pisanja kontejnera? Zato što je u Dockerfile-u MongoDB slike katalog /data/db (gdje MongoDB po defaultu pohranjuje svoje podatke) definiran kao volumen.

Napomene: mnoge slike koje bi trebale generirati podatke koriste volumene za pohranu tih podataka.
Kada se zasitimo MongoDB-a i zaustavimo (ili čak obrišemo) kontejner, volumen se neće obrisati. Nastavit će zauzimati naš dragocjeni prostor na disku sve dok ga izričito ne obrišemo tom naredbom:
$ docker volume rm $(docker volume ls -q)Ili možemo koristiti već poznatu podnaredbu prune:
$ docker volume prune
UPOZORENJE! Ovo će ukloniti sve lokalne volumene koji nisu korišteni od strane barem jednog kontejnera.
Jeste li sigurni da želite nastaviti? [y/N] y
Izbrisani volumeni:
d50b6402eb75d09ec17a5f57df4ed7b520c448429f70725fc5707334e5ded4d5
8f7a16e1cf117cdfddb6a38d1f4f02b18d21a485b49037e2670753fa34d115fc
599c3dd48d529b2e105eec38537cd16dac1ae6f899a123e2a62ffac6168b2f5f
...
732e610e435c24f6acae827cd340a60ce4132387cfc512452994bc0728dd66df
9a3f39cc8bd0f9ce54dea3421193f752bda4b8846841b6d36f8ee24358a85bae
045a9b534259ec6c0318cb162b7b4fca75b553d4e86fc93faafd0e7c77c79799
c6283fe9f8d2ca105d30ecaad31868410e809aba0909b3e60d68a26e92a094da
Ukupno povraćeno prostora: 25.82GB
luc@saturn:~$Korištenje diska za keširanje gradnje slika
U Dockeru 18.09 proces stvaranja slika pretrpio je promjene zahvaljujući alatu BuildKit. Ovaj alat povećava brzinu procesa, optimizira upravljanje pohranom podataka i sigurnosti. Ovde se nećemo zadržavati na svim detaljima ovog sjajnog alata, već ćemo se fokusirati na to kako utječe na korištenje diska.
Pretpostavimo da imamo potpuno jednostavnu aplikaciju Node.Js:
- datoteka index.js pokreće jednostavni HTTP server koji odgovara na svaki primljeni zahtjev sa stringom:
- datoteka package.json definira ovisnosti, 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(), 'Primljen Zahtjev'));
});
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 izgradnju 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"]Hajde da izgradimo sliku na uobičajen način, bez korištenja BuildKit:
$ docker build -t app:1.0 .Ako proverimo korištenje diska, vidjet ćemo da samo osnovna slika (node:13-alpine) i finalna slika (app:1.0) zauzimaju prostor:
TIP UKUPNO AKTIVNO VELIČINA MOGUĆE POVRATITI
Slike 2 0 109.3MB 109.3MB (100%)
Kontejneri 0 0 0B 0B
Lokalni volumeni 0 0 0B 0B
Keš gradnje 0 0 0B 0BHajde da izgradimo drugu verziju naše aplikacije, već s korištenjem BuildKit-a. Sve što trebamo je da postavimo varijablu DOCKER_BUILDKIT na 1:
$ DOCKER_BUILDKIT=1 docker build -t app:2.0 .Ako sada proverimo korištenje diska, vidjet ćemo da sada sudjeluje keš gradnje (build-cache):
$ docker system df
TIP UKUPNO AKTIVNO VELIČINA OBNOVLJIVO
Slike 2 0 109.3MB 109.3MB (100%)
Kontejneri 0 0 0B 0B
Lokalni volumeni 0 0 0B 0B
Predmemorija 11 0 8.949kB 8.949kBZa njegovo čišćenje koristit ćemo sljedeću naredbu:
$ docker builder prune
UPOZORENJE! Ovo će ukloniti sve viseće predmemorije za gradnju.
Da li ste sigurni da želite nastaviti? [y/N] y
Objekti predmemorije za gradnju su obrisani:
rffq7b06h9t09xe584rn4f91e
ztexgsz949ci8mx8p5tzgdzhe
3z9jeoqbbmj3eftltawvkiayi
Ukupno obnovljen prostor: 8.949kBOčistiti sve!
Dakle, razmotrili smo čišćenje diskovnog prostora koji zauzimaju kontejneri, slike i volumeni. U tome nam pomaže podkomanda prune. Ali se može koristiti i na sistemskom nivou docker, i očistiti će sve što može:
$ docker system prune
UPOZORENJE! Ovo će ukloniti:
- sve zaustavljene kontejnere
- sve mreže koje nije koristio nijedan kontejner
- sve viseće slike
- sve viseće predmemorije za gradnju
Da li ste sigurni da želite nastaviti? [y/N]Ako iz nekog razloga štedite diskovni prostor na računaru sa Dockerom, povremeno pokretanje ove naredbe treba postati navika.
Izvor: habr.com
