
Përshëndetje, Habr! Po ju prezantoj një përkthim të artikullit autori .
Sot do flasim për mënyrën se si Docker përdor hapësirën diskore të makinës pritëse, si dhe do të shqyrtojmë se si ta çlironi atë hapësirë nga mbetjet e imazheve dhe kontejnerëve të papërdorur.

Konsum total
Docker është një gjë e shkëlqyer, ndoshta sot pak kush e dyshon këtë. Vetëm disa vite më parë, ky produkt na ofroi një mënyrë krejtësisht të re për të ndërtuar, shpërndarë dhe përgatitur çdo ambient, duke i lejuar të kursenim ndjeshëm burimet e procesorit dhe memorizimit. Përveç kësaj (dhe për disa do të jetë edhe më e rëndësishme), Docker na lehtësoi në mënyrë të jashtëzakonshme dhe standardizoi menaxhimin e ciklit të jetës së ambientet e punës që përdorim.
Megjithatë, për të gjitha këto komoditete të jetës moderne, na duhet të paguajmë. Kur aktivizojmë kontejnerë, shkarkojmë ose krijojmë imazhe tona, ndërtojmë ekosistema të komplikuara, na duhet të paguajmë. Dhe paguajmë me hapësirë diskore.
Nëse keni ndonjëherë menduar se sa hapësirë është realisht e zënë në makinën tuaj nga Docker, mund të jeni të papërshtatshëm kur të shihni rezultatin e kësaj komande:
$ docker system df 
Këtu shfaqet përdorimi i diskut nga Docker në dimensione të ndryshme:
- imazhet (images) – madhësia totale e imazheve që janë shkarkuar nga depozitat dhe ndërtuar në sistemin tuaj;
- kontejnerët (containers) – vëllimi total i hapësirës diskore të përdorur nga kontejnerët e aktivizuar (kuptohet si vëllimi total i shtresave të leximit-shkrimit të të gjithë kontejnerëve);
- tumat lokale (local volumes) – vëllimi i depozitave lokale të lidhura me kontejnerët;
- këshilla e ndërtimit (build cache) – skedarë temporarë të krijuar nga procesi i ndërtimit të imazheve (në përdorimin e mjetit BuildKit, i disponueshëm që nga Docker versioni 18.09).
Jam gati të betohem se pas këtij përshkrimi të thjeshtë ju ndiheni të etur për të pastruar diskun nga mbeturinat dhe për të rikthyer në jetë gigabajtët tuaj të çmuar (shënim: sidomos nëse për këto gigabajtë ju paguani çdo muaj një qira).
Përdorimi i diskut nga kontejnerët
Çdo herë që krijohet një kontejner në makinën pritëse, në katalogun /var/lib/docker krijohen disa skedarë dhe katalogë, ndër të cilët vlen të përmenden këta:
- Katalogu /var/lib/docker/containers/ID_kontejnerit – kur përdoret drejtori standard i regjistrimit, pikërisht këtu ruhen regjistrat e ngjarjeve në formatin JSON. Regjistrat shumë të detajuar, si dhe regjistrat që askush nuk i lexon dhe nuk i përpunon në mënyra të tjera, shpesh janë shkak për mbushjen e disqeve.
- Katalogu /var/lib/docker/overlay2 – përmban shtresa leximi-shkruese të konteinerëve (overlay2 – drejtori më i preferuar në shumicën e shpërndarjeve të Linux). Nëse një kontejner ruan të dhëna në sistemin e tij të skedarëve, atëherë pikërisht në këtë katalog do të vendosen ato.
Le të imagjinojmë një sistem në të cilin është instaluar një Docker tërësisht i pastër, që nuk ka marrë pjesë ndonjëherë në ekzekutimin e konteinerëve dhe ndërtimin e imazheve. Raporti i tij për përdorimin e hapësirës në disk do të duket kështu:
$ docker system df
TIPI TOTAL AKTIV TË DHËNA RIKHET
Imazhet 0 0 0B 0B
Konteinerët 0 0 0B 0B
Vëllimet Lokale 0 0 0B 0B
Kosh Ndërtimi 0 0 0B 0BLe të nisëm një kontejner, për shembull, NGINX:
$ docker container run --name www -d -p 8000:80 nginx:1.16Çfarë ndodh me diskun:
- imazhet (images) zënë 126 MB, ky është NGINX-i që ne filluam në kontejner;
- konteinerët (containers) zënë vetëm 2 byte.
$ docker system df
TIPI TOTAL AKTIV TË DHËNA RIKHET
Imazhet 1 1 126M 0B (0%)
Konteinerët 1 1 2B 0B (0%)
Vëllimet Lokale 0 0 0B 0B
Kosh Ndërtimi 0 0 0B 0BDuke parë rezultatin, ne ende nuk kemi hapësirë për ta liruar. Pasiqë 2 byte janë krejtësisht të papranueshëm, le të imagjinojmë se NGINX-i ynë papritur shkroi diku 100 Megabajt të dhënash dhe krijoi në brendësi të tij një skedar test.img me atë madhësi.
$ docker exec -ti www
dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*100]Përsëri, le të shqyrtojmë përdorimin e hapësirës në disk në host. Do të shohim se kontejneri (containers) zë atje 100 Megabajt.
$ docker system df
TIPI TOTAL AKTIV TË DHËNA RIKHET
Imazhet 1 1 126M 0B (0%)
Konteinerët 1 1 104.9MB 0B (0%)
Vëllimet Lokale 0 0 0B 0B
Kosh Ndërtimi 0 0 0B 0BMendoj se truri juaj i kureshtshëm tashmë po bën pyetje për vendndodhjen e skedarit tonë test.img. Le të shohim se ku ndodhet:
$ 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.imgPa përmendur shkurt, mund të theksohet se skedari test.img është pozicionuar lehtë në nivelin e leximit-shkrimit, të menaxhuar nga drejtuesi overlay2. Nëse e ndalim kontejnerin tonë, hosti do të na tregojë se ky vend mund të lirohet, në thelb.
# 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 0BSi mund ta bëjmë këtë? Duke eliminuar kontejnerin, i cili do të sjellë pastrimin e hapësirës përkatëse në nivelin e leximit-shkrimit.
Me komandën në vijim, mund të eliminoni të gjithë kontejnerët e instaluar njëherësh dhe të pastroni diskun tuaj nga të gjitha skedarët që ata krijuan në nivelin e leximit-shkrimit:
$ docker container prune
KËSHILLË! Kjo do të heqë të gjithë kontejnerët e ndaluar.
A jeni të sigurt që dëshironi të vazhdoni? [y/N] y
Kontejnerët e Fshirë:
5e7f8e5097ace9ef5518ebf0c6fc2062ff024efb495f11ccc89df21ec9b4dcc2
Hapësira totale e rikuperuar: 104.9MBKështu, ne kemi liruar 104,9 Megabajt duke eliminuar kontejnerin. Por pasi që nuk po e përdorim më imazhin e shkarkuar më parë, ai gjithashtu bëhet një kandidat për eliminim dhe lirimin e burimeve tona:
$ docker system df
LLOJI TOTAL AKTIV MDFAR RIKUPERUESHËM
Imazhe 1 0 126M 126M (100%)
Kontejnerë 0 0 0B 0B
Volume Lokal 0 0 0B 0B
Cache të Ndërtimit 0 0 0B 0BVëmendje: derisa imazhi të përdoret nga të paktën një kontejner, nuk do të jeni në gjendje ta përdorni këtë truk.
Subkomanda prune, e cila u përdor më sipër, ka efekt vetëm në kontejnerë të ndaluar. Nëse dëshirojmë të eliminojmë jo vetëm kontejnerët e ndaluar, por edhe ata të aktivizuar, duhet të përdorim një nga këto komanda:
# Historical command
$ docker rm -f $(docker ps –aq)
# More recent command
$ docker container rm -f $(docker container ls -aq)Shënime në margjinë: nëse gjatë fillimit të kontejnerit përdorni parametrin —rm, atëherë kur ai ndalet, do të lirohet të gjithë hapësira disk që ai zinte.
Përdorimi i diskut nga imazhet
Para disa vitesh, madhësia e një imazhi prej disa qindra megabajtësh ishte krejt normale: imazhi Ubuntu peshohej 600 Megabajt, ndërsa imazhi Microsoft .Net peshohej disa Gigabajt. Në ato ditë, shkarkimi i vetëm një imazhi mund të shkaktonte një dëm të madh në hapësirën tuaj të lirë në disk, edhe nëse ndaheshit nivelet midis imazheve. Sot – falë Zotit – imazhet peshojnë shumë më pak, por edhe kështu, mund të mbushen shpejt burimet ekzistuese, nëse nuk merren disa masa paraprake.
Ka disa lloje imazhesh që nuk duken drejtpërdrejt për përdoruesin përfundimtar:
- imazhet ndërmjetëse, mbi bazën e të cilave janë grumbulluar imazhe të tjera – ato nuk mund të fshihen nëse po përdorni kontejnerë të bazuar në këto "imazhe të tjera";
- imazhe të varura – janë ato imazhe ndërmjetëse, të cilat nuk referohen nga asnjë nga kontejnerët e nisur – ato mund të fshihen.
- Me komandën e mëposhtme mund të kontrolloni praninë e imazheve të varura në sistemin tuaj:
$ docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
none none 21e658fe5351 12 minutes ago 71.3MBAto mund të fshihen në këtë mënyrë:
$ docker image rm $(docker image ls -f dangling=true -q)Mund të përdorim gjithashtu nënkomandën prune:
$ docker image prune
WARNING! Kjo do të fshijë të gjitha imazhet e varura.
A jeni i sigurt që dëshironi të vazhdoni? [y/N] y
Imazhet e fshira:
deleted: sha256:143407a3cb7efa6e95761b8cd6cea25e3f41455be6d5e7cda
deleted: sha256:738010bda9dd34896bac9bbc77b2d60addd7738ad1a95e5cc
deleted: sha256:fa4f0194a1eb829523ecf3bad04b4a7bdce089c8361e2c347
deleted: sha256:c5041938bcb46f78bf2f2a7f0a0df0eea74c4555097cc9197
deleted: sha256:5945bb6e12888cf320828e0fd00728947104da82e3eb4452f
Hapsira totale e rikuperuar: 12.9kBNëse ndonjëherë dëshirojmë të fshijmë të gjitha imazhet (dhe jo vetëm imazhet e varura) me një komandë, mund ta bëjmë kështu:
$ docker image rm $(docker image ls -q)Përdorimi i diskut me volume
Volume-t (të dhënat) përdoren për të ruajtur të dhëna jashtë sistemit të skedarëve të kontejnerit. Për shembull, nëse duam të ruajmë rezultatet e funksionimit të ndonjë aplikacioni për t'i përdorur ndryshe. Një shembull i zakonshëm janë baze të dhënash.
Le të nisëm një kontejner MongoDB, të bashkëlidhim një volume të jashtëm të kontejnerit, dhe të rikuperojmë nga një backup të bazës të dhënash (e kemi të disponueshme në skedarin 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
--jsonArrayTë dhënat do të jenë në makinë pritëse në katalogun /var/lib/docker/volumes. Por pse jo në nivelin e leximit-shkrimit të kontejnerit? Sepse në Dockerfile-in e imazhit MongoDB katalogu /data/db (në të cilin MongoDB në mënyrë të paracaktuar ruan të dhënat e tij) është përcaktuar si volume.

Shënime në anë: shumë imazhe, si rezultat i të cilave duhet të krijohen të dhëna, përdorin volume (të dhënat) për të ruajtur këto të dhëna.
Kur të përfundojmë me MongoDB dhe të ndalim (ndoshta madje të fshijmë) kontejnerin, volumi nuk do të fshihet. Ai do të vazhdojë të marrë hapësirën tonë të çmuar diskore derisa ne ta fshijmë atë qartë me këtë komandë:
$ docker volume rm $(docker volume ls -q)Ose mund të përdorim nënkomandën tonë të njohur prune:
$ docker volume prune
WARNING! Kjo do të heqë të gjitha volumet lokale që nuk përdoren nga të paktën një kontejner.
A jeni të sigurt se dëshironit të vazhdoni? [y/N] y
Të fshirë Volumet:
d50b6402eb75d09ec17a5f57df4ed7b520c448429f70725fc5707334e5ded4d5
8f7a16e1cf117cdfddb6a38d1f4f02b18d21a485b49037e2670753fa34d115fc
599c3dd48d529b2e105eec38537cd16dac1ae6f899a123e2a62ffac6168b2f5f
...
732e610e435c24f6acae827cd340a60ce4132387cfc512452994bc0728dd66df
9a3f39cc8bd0f9ce54dea3421193f752bda4b8846841b6d36f8ee24358a85bae
045a9b534259ec6c0318cb162b7b4fca75b553d4e86fc93faafd0e7c77c79799
c6283fe9f8d2ca105d30ecaad31868410e809aba0909b3e60d68a26e92a094da
Hapësira totale e rikuperuar: 25.82GB
luc@saturn:~$Përdorimi i diskut për cache të ndërtimit të imazheve
Në Docker 18.09, procesi i krijimit të imazheve kaloi disa ndryshime falë mjetit BuildKit. Me këtë mjet, rritet shpejtësia e procesit, optimizohet menaxhimi i ruajtjes së të dhënave dhe sigurisë. Nuk do të shqyrtojmë të gjitha detajet e këtij mjeti të mrekullueshëm, do të ndalemi vetëm te mënyra se si ai ndikon në çështjet e përdorimit të hapësirës disk.
Le të supozojmë se kemi një aplikacion shumë të thjeshtë Node.Js:
- Skedari index.js nis një server HTTP të thjeshtë që përgjigjet me një varg për çdo kërkesë të marrë:
- Skedari package.json përcakton varësitë, nga të cilat vetëm expressjs përdoret për të nisur serverin 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(), 'Kërkesa e Marrë'));
});
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 për ndërtimin e imazhit duket kështu:
FROM node:13-alpine
COPY package.json /app/package.json
RUN cd /app && npm install
COPY . /app/
WORKDIR /app
EXPOSE 80
CMD ["npm", "start"]Le të ndërtoshim imazhin në mënyrë të zakonshme, pa përdorur BuildKit:
$ docker build -t app:1.0 .Nëse kontrollojmë përdorimin e hapësirës disk, do të shohim se hapësira zë vetëm imazhi bazë (node:13-alpine) dhe imazhi përfundimtar (app:1.0):
TIPI TOTAL AKTIV SIZE RIKUPERUESHËM
Imazhet 2 0 109.3MB 109.3MB (100%)
Kontejnerët 0 0 0B 0B
Volumet Lokale 0 0 0B 0B
Cache e Ndërtimit 0 0 0B 0BLe të ndërtoshim versionin e dytë të aplikacionit tonë, tani me përdorimin e BuildKit. Për këtë, na duhet vetëm të vendosim variablen DOCKER_BUILDKIT në vlerën 1:
$ DOCKER_BUILDKIT=1 docker build -t app:2.0 .Nëse tani kontrollojmë përdorimin e diskut, do të shohim se tani është përfshirë cache e ndërtimit (buid-cache):
$ 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.949kBPër ta pastruar atë, përdorim komandën në vijim:
$ docker builder prune
WARNING! Kjo do të heqë të gjithë ndihmësit e ndërtimit që s'kanë asnjë përdorim.
A jeni të sigurt që dëshironi të vazhdoni? [y/N] y
Objektet e pastruar të ndihmësit të ndërtimit:
rffq7b06h9t09xe584rn4f91e
ztexgsz949ci8mx8p5tzgdzhe
3z9jeoqbbmj3eftltawvkiayi
Hapësira totale e rikuperuar: 8.949kBPastroni gjithçka!
Pra, ne shqyrtuam pastrimin e hapësirës së diskut të zënë nga kontejnerët, imazhet dhe volumet. Kjo na ndihmon subkomanda prune. Por mund të përdoret edhe në nivelin sistemor docker, dhe do të pastruar gjithçka që mundet:
$ docker system prune
WARNING! Kjo do të heqë:
- të gjithë kontejnerët e ndalur
- të gjithë rrjetet që nuk përdoren nga të paktën një kontejner
- të gjitha imazhet që s'kanë asnjë përdorim
- të gjitha ndihmësit e ndërtimit që s'kanë asnjë përdorim
A jeni të sigurt që dëshironi të vazhdoni? [y/N]Nëse për ndonjë arsye po kurseni hapësirë në disk në makinën tuaj me Docker, atëherë ekzekutimi periodic i kësaj komande është një zakon i mirë.
Burimi: habr.com
