Docker padomi: Notīriet savu mašīnu no liekā

Docker padomi: Notīriet savu mašīnu no liekā

Sveiki, Habr! Iepazīstinu ar tulkojumu raksta "Docker padomi: notīrīt jūsu vietējo mašīnu" autors Lūks Jaggeris.

Š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.


Docker padomi: Notīriet savu mašīnu no liekā

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

Docker padomi: Notīriet savu mašīnu no liekā

Š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         0B

Palaidīsim kādu konteineru, piemēram, NGINX:

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

Kas 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         0B

Spriež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         0B

Domā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.img

Neizsniegts 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         0B

Kā 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.9MB

Tā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         0B

Brī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.3MB

Jū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.9kB

Ja 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 
  --jsonArray

Dati 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).

Docker padomi: Notīriet savu mašīnu no liekā

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         0B

Tagad 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.949kB

Lai 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.949kB

Notī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

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster