
Sveiki, Habr! Iepazīstinu ar tulkojumu raksta autors .
Šodien mēs runāsim par to, kā Docker izmanto viesmašīnas diskus, kā arī aplūkosim, kā atbrīvot šo vietu no nevajadzīgajiem attēliem un konteineriem.

Kopējais patēriņš
Docker ir forša lieta, šodien, iespējams, to vairs neapšauba neviens. Pirms dažiem gadiem šis produkts mums sniedza pilnīgi jaunu veidu, kā būvēt, piegādāt un palaist jebkuru vidi, ļaujot ievērojami ietaupīt procesora un operatīvās atmiņas resursus. Papildus tam (un kādam tas var būt pat vissvarīgākais) Docker ir ļāvis mums neticami atvieglot un vienkāršot izmantoto darba vidi dzīves cikla pārvaldību.
Tomēr par visām šīm modernās dzīves ērtībām ir jāmaksā. Kad mēs palaidām konteinerus, lejupielādējām vai izveidojām savus attēlus, izvēršot sarežģītas ekosistēmas, mums jāmeklē maksāt. Un mēs to darām, tostarp ar diskos pieejamo vietu.
Ja jūs nekad neesat domājuši par to, cik daudz vietas patiesībā tiek aizņemta jūsu Docker mašīnā, tad jūs varat būt nepatīkami pārsteigts par šīs komandas rezultātiem:
$ docker system df 
Šeit tiek attēlota Docker diska izmantošana dažādos griezumos:
- attēli (images) – kopējais attēlu lielums, kas tika lejupielādēti no attēlu krātuvēm un izveidoti jūsu sistēmā;
- konteineri (containers) – kopējais diska vietas apjoms, ko izmanto palaistie konteineri (domājot par lasīšanas-ierakstīšanas slāņu kopējo apjomu visu konteineru);
- lokālie apjomi (local volumes) – lokālo krātuvju apjoms, kas pievienots konteineriem;
- būvēšanas kešatmiņa (build cache) – pagaidu faili, kas ģenerēti attēlu būvēšanas procesā (izmantojot BuildKit instrumentu, kas pieejams kopš Docker versijas 18.09).
Es derētu, ka jau pēc šī vienkāršā uzskaitījuma jums ir vēlme notīrīt disku no atkritumiem un atgūt dārgos gigabaitus (piezīme: īpaši, ja par šiem gigabaitiem katru mēnesi maksājat īres maksu).
Disku izmantošana ar konteineriem
Katru reizi, kad tiek izveidots konteiners viesmašīnā, katalogā /var/lib/docker tiek izveidoti vairāki faili un katalogi, starp kuriem jāizceļ sekojošie:
- Katalogs /var/lib/docker/containers/ID_konteinera – izmantojot standarta žurnālfailu sistēmu, šeit tiek glabāti notikumu žurnāli JSON formātā. Pārāk detalizēti žurnāli, kā arī žurnāli, kurus neviens nelasa un neapstrādā citos veidos, bieži izraisa disku pārslogošanu.
- Katalogs /var/lib/docker/overlay2 – satur konteineru rakstīšanas un lasīšanas slāņus (overlay2 – ieteicamā sistēma lielākajā daļā Linux izplatījumu). Ja konteiners saglabā datus savā failu sistēmā, tad tie tiks glabāti tieši šajā katalogā.
Iedomāsimies sistēmu, kurā ir uzstādīts pilnīgi nevainīgs Docker, kas nekad nav piedalījies konteineru palaišanā vai attēlu būvēšanā. Tā pārskats par diskā izmantoto telpu izskatīsies šādi:
$ docker system df
TIPA KOPĀ AKTĪVS IZMĒRS ATBRĪVOJAMS
Attēli 0 0 0B 0B
Konteineri 0 0 0B 0B
Vietējie apjomi 0 0 0B 0B
Būvēšanas kešatmiņa 0 0 0B 0BPalaidīsim kādu konteineru, piemēram, NGINX:
$ docker container run --name www -d -p 8000:80 nginx:1.16Kas notiek ar disku:
- attēli (images) aizņem 126 MB, tas ir NGINX, kuru mēs palaidām konteinerā;
- konteineri (containers) aizņem smieklīgus 2 baitus.
$ docker system df
TIPA KOPĀ AKTĪVS IZMĒRS ATBRĪVOJAMS
Attēli 1 1 126M 0B (0%)
Konteineri 1 1 2B 0B (0%)
Vietējie apjomi 0 0 0B 0B
Būvēšanas kešatmiņa 0 0 0B 0BSpriežot pēc rezultātiem, mums vēl nav brīvās vietas, ko varētu atbrīvot. Tā kā 2 baiti ir pilnīgi nenozīmīgi, iedomāsimies, ka mūsu NGINX negaidīti uzrakstīja 100 megabaitus datu un izveidoja sevī failu test.img tieši šā izmēra.
$ docker exec -ti www
dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*100]Atkal izpētīsim diska telpas izmantošanu uz hosta. Mēs redzēsim, ka konteiners (containers) tur aizņem 100 megabaitus.
$ docker system df
TIPA KOPĀ AKTĪVS IZMĒRS ATBRĪVOJAMS
Attēli 1 1 126M 0B (0%)
Konteineri 1 1 104.9MB 0B (0%)
Vietējie apjomi 0 0 0B 0B
Būvēšanas kešatmiņa 0 0 0B 0BDomāju, ka jūsu ziņkārīgais prāts jau uzdod jautājumu, kur tad atrodas mūsu fails test.img. Meklēsim to:
$ 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.imgNeizsniegts pārāk dziļi, varam atzīmēt, ka fails test.img ērti novietots lasīšanas-ierakstīšanas līmenī, ko pārvalda pārklājošs draiveris overlay2. Ja mēs apturēsim savu konteinerv, hostējs norādīs, ka šo vietu, principā, var atbrīvot:
# 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 0BKā mēs to varam izdarīt? Ar konteineru dzēšanu, kas radīs attiecīgā lasīšanas-ierakstīšanas līmeņa vietas attīrīšanu.
Izmantojot šo komandu, jūs varat vienlaicīgi dzēst visus uzstādītos konteinerus un attīrīt savu disku no visiem tiem radītajiem lasīšanas-ierakstīšanas failiem:
$ docker container prune
WARNING! Tas izdzēš visus apstādinātos konteinerus.
Vai tiešām vēlaties turpināt? [y/N] y
Izdzēstie konteineri:
5e7f8e5097ace9ef5518ebf0c6fc2062ff024efb495f11ccc89df21ec9b4dcc2
Kopējā atgūstamā telpa: 104.9MBTātad, mēs atbrīvojām 104,9 megabaitus, izdzēšot konteineru. Bet, ņemot vērā, ka mēs vairs neizmantojam iepriekš lejupielādēto attēlu, tas arī kļūst par kandidātu dzēšanai un mūsu resursu atbrīvošanai:
$ docker system df
TIPA KOPĀ AKTĪVS IZMĒRS ATGŪSTAMS
Attēli 1 0 126M 126M (100%)
Konteineri 0 0 0B 0B
Vietējie apjomi 0 0 0B 0B
Būves kešs 0 0 0B 0BBrīdinājums: kamēr attēls tiek izmantots vismaz ar vienu konteineru, jūs nevarēsit izmantot šo triku.
Subkomanda prune, ko mēs izmantojām iepriekš, sniedz efektu tikai apstādinātiem konteineriem. Ja vēlamies dzēst ne tikai apstādinātos, bet arī darbojošos konteinerus, jādarbina viena no šīm komandām:
# Historical command
$ docker rm -f $(docker ps –aq)
# More recent command
$ docker container rm -f $(docker container ls -aq)Piezīmes uz malas: ja palaižot konteineru izmantojat parametru —rm, tad tā apstāšanās laikā tiks atbrīvota visa diska vieta, ko tas aizņēma.
Disku izmantošana ar attēliem
Pirms dažiem gadiem attēla izmērs pāris simtu megabaitu apmērā bija pilnīgi normāls: Ubuntu attēls sver 600 megabaitus, bet Microsoft .Net attēls – vairākus gigabaitus. Tajos senajos laikos viena tikai attēla lejupielāde varēja nodarīt milzīgu kaitējumu jūsu brīvajai vietai uz diska, pat ja jūs dalījāt līmeņus starp attēliem. Šodien – slava lielajiem – attēli sver daudz mazāk, bet pat šādā gadījumā, ja netiek pieņemti daži piesardzības pasākumi, resursi var ātri tikt aizpildīti.
Ir vairāki attēlu tipi, kas tieši nav redzami galalietotājam:
- starpējo attēlu, uz kuriem balstās citi attēli, – tos nevar dzēst, ja izmantojat traukus, kas izveidoti, pamatojoties uz šiem «citiem» attēliem;
- nepieejamie attēli – tie ir tādi starpējo attēlu, uz kuriem neatsaucas neviens no palaistajiem traukiem – tos var dzēst.
- Ar nākamo komandu jūs varat pārbaudīt, vai jūsu sistēmā ir nepieejami attēli:
$ docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
none none 21e658fe5351 12 minutes ago 71.3MBJūs varat tos dzēst šādā veidā:
$ docker image rm $(docker image ls -f dangling=true -q)Mēs varam izmantot arī apakškomandu 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.9kBJa pēkšņi mēs vēlētos dzēst visus attēlus (ne tikai nepieejamos) ar vienu komandu, to var izdarīt šādi:
$ docker image rm $(docker image ls -q)Disku izmantošana ar apjomiem
Apjomi (volumes) tiek izmantoti datu glabāšanai ārpus trauka failu sistēmas. Piemēram, ja mēs vēlamies saglabāt kāda lietojumprogrammas rezultātus, lai tos izmantotu kaut kā citādi. Bieža piemēra ir datu bāzes.
Sāksim MongoDB trauku, pievienosim tam ārēju apjomu un atjaunosim no tā datu bāzes rezervkopiju (mums tā ir pieejama failā 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
--jsonArrayDati atradīsies hosta mašīnā mapē /var/lib/docker/volumes. Bet kāpēc ne trauka lasīšanas-ierakstīšanas līmenī? Tāpēc, ka MongoDB attēla Dockerfile katalogs /data/db (kur MongoDB pēc noklusējuma glabā savus datus) ir noteikts kā apjoms (volume).

Piezīmes malās: daudzi attēli, kuru darbības rezultātā ir jāizveido dati, izmanto apjomus (volumes) šo datu saglabāšanai.
Kad mēs beigsim spēlēties ar MongoDB un apstāsim (varbūt pat izdzēsīsim) trauku, apjoms netiks izdzēsts. Tas turpinās aizņemt mūsu dārgo diskā vietu līdz brīdim, kad mēs to skaidri izdzēsīsim, izmantojot šādu komandu:
$ docker volume rm $(docker volume ls -q)Vai arī mēs varam izmantot jau pazīstamo apakškomandu prune:
$ docker volume prune
WARNING! Tas noņems visus vietējos apjomus, kas nav izmantoti vismaz vienā konteinerā.
Vai esat pārliecināts, ka vēlaties turpināt? [y/N] y
Dzēsti apjomi:
d50b6402eb75d09ec17a5f57df4ed7b520c448429f70725fc5707334e5ded4d5
8f7a16e1cf117cdfddb6a38d1f4f02b18d21a485b49037e2670753fa34d115fc
599c3dd48d529b2e105eec38537cd16dac1ae6f899a123e2a62ffac6168b2f5f
...
732e610e435c24f6acae827cd340a60ce4132387cfc512452994bc0728dd66df
9a3f39cc8bd0f9ce54dea3421193f752bda4b8846841b6d36f8ee24358a85bae
045a9b534259ec6c0318cb162b7b4fca75b553d4e86fc93faafd0e7c77c79799
c6283fe9f8d2ca105d30ecaad31868410e809aba0909b3e60d68a26e92a094da
Kopējā atbrīvotā vieta: 25.82GB
luc@saturn:~$Disku izmantošana attēlu būvēšanas kešatmiņai
Docker 18.09 attēlu veidošanas procesa ietvaros ir notikušas dažas izmaiņas, pateicoties instrumentam BuildKit. Šī lieta paātrina procesu, optimizē datu uzglabāšanas un drošības pārvaldību. Šeit mēs neskatīsimies uz visām šī brīnišķīgā rīka detaļām, bet pievērsīsimies tam, kā tas ietekmē diskā pieejamās vietas izmantošanu.
Pieņemsim, ka mums ir pavisam vienkārša Node.Js lietotne:
- fails index.js palaidīs vienkāršu HTTP serveri, kas atbildēs ar virkni uz katru saņemto pieprasījumu:
- fails package.json nosaka atkarības, no kurām tiek izmantots tikai expressjs HTTP servera palaišanai:
$ 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(), 'Saņemts pieprasījums'));
});
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, lai izveidotu attēlu, izskatās šādi:
FROM node:13-alpine
COPY package.json /app/package.json
RUN cd /app && npm install
COPY . /app/
WORKDIR /app
EXPOSE 80
CMD ["npm", "start"]Apskatīsim attēla veidošanu parastajā veidā, neizmantojot BuildKit:
$ docker build -t app:1.0 .Ja mēs pārbaudīsim diska izmantošanu, mēs redzēsim, ka vietu aizņem tikai pamata attēls (node:13-alpine) un gala attēls (app:1.0):
TIPA KOPĀ AKTĪVS IZMANTOJAMĀ VAIETA
Attēli 2 0 109.3MB 109.3MB (100%)
Konteineri 0 0 0B 0B
Vietējie apjomi 0 0 0B 0B
Būvēšanas kešatmiņa 0 0 0B 0BTagad mēs apvienosim otro versiju mūsu lietotnei, jau izmantojot BuildKit. Lai to izdarītu, mums vienkārši jādod DOCKER_BUILDKIT mainīgajam vērtību 1:
$ DOCKER_BUILDKIT=1 docker build -t app:2.0 .Ja mēs tagad pārbaudīsim diska izmantošanu, mēs redzēsim, ka šoreiz tajā tiek iekļauta būvēšanas kešatmiņa (build-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.949kBLai to notīrītu, izmantojiet šo komandu:
$ docker builder prune
WARNING! Šī komanda noņems visus neskartos būvēšanas kešus.
Vai tiešām vēlaties turpināt? [y/N] y
Izdzēsti būvēšanas keša objekti:
rffq7b06h9t09xe584rn4f91e
ztexgsz949ci8mx8p5tzgdzhe
3z9jeoqbbmj3eftltawvkiayi
Kopējā atbrīvotā vieta: 8.949kBNotīrīt visu!
Tātad, mēs apskatījām diska vietas notīrīšanu, ko ieņem konteineri, attēli un apjomi. Šajā procesā mums palīdz subkomanda prune. Bet to var izmantot arī sistemātiskā līmenī docker, un tā notīrīs visu, ko vien var:
$ docker system prune
WARNING! Šī komanda noņems:
- visus apstādinātos konteinerus
- visas tīklus, kas netiek lietoti vismaz vienā konteinerā
- visus nesakārtotos attēlus
- visus nesakārtotos būvēšanas kešus
Vai tiešām vēlaties turpināt? [y/N]Ja jūs kādu iemeslu dēļ ekonomējat vietu diskā uz mašīnas ar Docker, tad periodiska šīs komandas palaišana ir jāievieš kā ieradums.
Avots: habr.com
