Sfaturi Docker: Ștergeți mașina de nedorit

Sfaturi Docker: Ștergeți mașina de nedorit

Bună, Habr! Vă prezint atenției o traducere a articolului „Sfaturi Docker: Curățați-vă mașina locală” autor Luc Juggery.

Astăzi vom vorbi despre modul în care Docker utilizează spațiul pe disc al mașinii gazdă și, de asemenea, vom descoperi cum să eliberăm acest spațiu de resturile de imagini și containere neutilizate.


Sfaturi Docker: Ștergeți mașina de nedorit

Consum total

Docker este un lucru grozav, probabil puțini oameni se îndoiesc de asta astăzi. Cu doar câțiva ani în urmă, acest produs ne-a oferit o modalitate complet nouă de a construi, livra și rula orice mediu, permițându-ne să economisim în mod semnificativ resursele CPU și RAM. Pe lângă aceasta (și pentru unii acesta va fi cel mai important lucru), Docker ne-a permis să simplificăm și să unificăm incredibil de managementul ciclului de viață al mediilor noastre de producție.

Cu toate acestea, toate aceste delicii ale vieții moderne au un preț. Când rulăm containere, descarcăm sau creăm propriile noastre imagini și implementăm ecosisteme complexe, trebuie să plătim. Și plătim, printre altele, cu spațiu pe disc.

Dacă nu v-ați gândit niciodată cât spațiu ocupă de fapt Docker pe mașina dvs., ați putea fi surprins neplăcut de rezultatul acestei comenzi:

$ docker system df

Sfaturi Docker: Ștergeți mașina de nedorit

Aceasta arată utilizarea discului de către Docker în diferite contexte:

  • imagini – dimensiunea totală a imaginilor care au fost descărcate din depozitele de imagini și construite pe sistemul dumneavoastră;
  • containere – cantitatea totală de spațiu pe disc utilizată de rularea containerelor (adică volumul total de straturi de citire-scriere ale tuturor containerelor);
  • volume locale – volumul de depozitare locală montat pe containere;
  • build cache – fișiere temporare generate de procesul de construire a imaginii (folosind instrumentul BuildKit, disponibil începând cu versiunea Docker 18.09).

Pun pariu că după acest transfer simplu sunteți dornic să vă curățați discul de gunoi și să readuceți la viață gigaocteți prețioși (notă: mai ales dacă plătiți chirie pentru acești gigaocteți în fiecare lună).

Utilizarea discului de către containere

De fiecare dată când creați un container pe mașina gazdă, în directorul /var/lib/docker sunt create mai multe fișiere și directoare, printre care sunt de remarcat următoarele:

  • Director/var/lib/Docker/Containers/Container_id - Când utilizați driverul de înregistrare standard, acesta este locul în care jurnalele de evenimente sunt salvate în format JSON. Jurnalele prea detaliate, precum și jurnalele pe care nimeni nu le citește sau altfel procesează, adesea determină ca discurile să devină pline.
  • Directorul /var/lib/docker/overlay2 conține straturile de citire-scriere a containerului (overlay2 este driverul preferat în majoritatea distribuțiilor Linux). Dacă containerul stochează date în sistemul său de fișiere, atunci acesta va fi plasat în acest director.

Să ne imaginăm un sistem pe care este instalat un Docker impecabil, care nu a fost niciodată implicat în lansarea containerelor sau construirea de imagini. Raportul său de utilizare a spațiului pe disc va arăta astfel:

$ 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

Să lansăm un container, de exemplu, NGINX:

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

Ce se întâmplă cu discul:

  • imaginile ocupă 126 MB, acesta este același NGINX pe care l-am lansat în container;
  • containerele ocupă 2 octeți ridicoli.

$ 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

Judecând după concluzie, nu avem încă niciun spațiu pe care să-l eliberăm. Deoarece 2 octeți este complet frivol, să ne imaginăm că NGINX-ul nostru a scris în mod neașteptat undeva 100 de megaocteți de date și a creat un fișier test.img de exact această dimensiune în interiorul său.

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

Să examinăm din nou utilizarea spațiului de disc pe gazdă. Vom vedea că containerul (containerele) ocupă acolo 100 Megaocteți.

$ 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

Cred că creierul tău curios se întreabă deja unde se află fișierul nostru test.img. Să-l căutăm:

$ 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

Fără a intra în detalii, putem observa că fișierul test.img este situat convenabil la nivel de citire-scriere, controlat de driverul overlay2. Dacă ne oprim containerul, gazda ne va spune că acest spațiu, în principiu, poate fi eliberat:

# 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

Cum putem face asta? Prin ștergerea containerului, ceea ce va presupune ștergerea spațiului corespunzător la nivel de citire-scriere.

Cu următoarea comandă, puteți elimina toate containerele instalate dintr-o singură lovitură și puteți șterge discul de toate fișierele de citire-scriere create de aceștia:

$ 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

Deci, am eliberat 104,9 Megaocteți prin ștergerea containerului. Dar, din moment ce nu mai folosim imaginea descărcată anterior, aceasta devine și candidată pentru ștergerea și eliberarea resurselor noastre:

$ 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

Notă: atâta timp cât imaginea este utilizată de cel puțin un container, nu veți putea folosi acest truc.

Subcomanda prune pe care am folosit-o mai sus are efect numai asupra containerelor oprite. Dacă vrem să ștergem nu numai containerele oprite, ci și care rulează, ar trebui să folosim una dintre aceste comenzi:

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

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

Note secundare: dacă utilizați parametrul -rm la pornirea unui container, atunci când acesta se oprește, tot spațiul pe disc pe care l-a ocupat va fi eliberat.

Utilizarea imaginilor de disc

În urmă cu câțiva ani, o dimensiune a imaginii de câteva sute de megaocteți era complet normală: o imagine Ubuntu cântărea 600 de megaocteți, iar o imagine Microsoft .Net cântărea câțiva gigabytes. În acele zile pline, descărcarea unei singure imagini ar putea avea o taxă mare asupra spațiului liber pe disc, chiar dacă partajați niveluri între imagini. Astăzi - lăudați să fie mari - imaginile cântăresc mult mai puțin, dar chiar și așa, puteți completa rapid resursele disponibile dacă nu vă luați unele măsuri de precauție.

Există mai multe tipuri de imagini care nu sunt direct vizibile pentru utilizatorul final:

  • imagini intermediare, pe baza cărora sunt colectate alte imagini - nu pot fi șterse dacă utilizați containere bazate pe aceste „alte” imagini;
  • imaginile suspendate sunt imagini intermediare la care niciunul dintre containerele care rulează nu face referire - pot fi șterse.
  • Cu următoarea comandă puteți verifica dacă există imagini suspendate pe sistemul dvs.:

$ docker image ls -f dangling=true
REPOSITORY  TAG      IMAGE ID         CREATED             SIZE
none      none   21e658fe5351     12 minutes ago      71.3MB

Le puteți elimina în felul următor:

$ docker image rm $(docker image ls -f dangling=true -q)

De asemenea, putem folosi subcomanda 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

Dacă vrem brusc să ștergem toate imaginile cu totul (și nu doar atârnând) cu o singură comandă, atunci putem face asta:

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

Utilizarea discului în funcție de volume

Volumele sunt folosite pentru a stoca date în afara sistemului de fișiere al containerului. De exemplu, dacă vrem să salvăm rezultatele unei aplicații pentru a le folosi în alt mod. Un exemplu comun sunt bazele de date.

Să lansăm un container MongoDB, să montăm un volum extern containerului și să restabilim o copie de rezervă a bazei de date din acesta (o avem disponibilă în fișierul 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

Datele vor fi localizate pe mașina gazdă în directorul /var/lib/docker/volumes. Dar de ce nu la nivelul de citire-scriere al containerului? Deoarece în Dockerfile al imaginii MongoDB, directorul /data/db (unde MongoDB își stochează datele în mod implicit) este definit ca volum.

Sfaturi Docker: Ștergeți mașina de nedorit

Notă secundară: multe imagini care trebuie să producă date folosesc volume pentru a stoca acele date.

Când ne jucăm suficient cu MongoDB și oprim (sau poate chiar ștergem) containerul, volumul nu va fi șters. Va continua să ocupe spațiul nostru prețios pe disc până când îl ștergem în mod explicit cu o comandă ca aceasta:

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

Ei bine, sau putem folosi subcomanda prune care ne este deja familiară:

$ 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:~$

Utilizarea discului pentru cache-ul de construire a imaginii

În Docker 18.09, procesul de creare a imaginii a suferit unele modificări datorită instrumentului BuildKit. Acest lucru mărește viteza procesului și optimizează stocarea datelor și gestionarea securității. Aici nu vom lua în considerare toate detaliile acestui instrument minunat; ne vom concentra doar asupra modului în care abordează problemele de utilizare a spațiului pe disc.

Să presupunem că avem o aplicație Node.Js complet simplă:

  • fișierul index.js pornește un server HTTP simplu care răspunde cu o linie la fiecare solicitare primită:
  • fișierul package.json definește dependențele, dintre care numai expressjs este folosit pentru a rula serverul 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(), '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"
      }
    }

Fișierul Docker pentru construirea imaginii arată astfel:

FROM node:13-alpine
COPY package.json /app/package.json
RUN cd /app && npm install
COPY . /app/
WORKDIR /app
EXPOSE 80
CMD ["npm", "start"]

Să construim imaginea în modul obișnuit, fără a folosi BuildKit:

$ docker build -t app:1.0 .

Dacă verificăm utilizarea spațiului pe disc, putem vedea că doar imaginea de bază (nodul:13-alpine) și imaginea țintă (app:1.0) ocupă spațiu:

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

Să construim a doua versiune a aplicației noastre, folosind BuildKit. Pentru a face acest lucru, trebuie doar să setăm variabila DOCKER_BUILDKIT la 1:

$ DOCKER_BUILDKIT=1 docker build -t app:2.0 .

Dacă verificăm acum utilizarea discului, vom vedea că memoria cache de compilare (buid-cache) este acum implicată acolo:

$ 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

Pentru a o șterge, utilizați următoarea comandă:

$ 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

Curata tot!

Deci, ne-am uitat la curățarea spațiului pe disc ocupat de containere, imagini și volume. Subcomanda prune ne ajută în acest sens. Dar poate fi folosit și la nivel de sistem docker și va curăța tot ce poate:

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

Dacă dintr-un motiv oarecare economisiți spațiu pe disc pe o mașină care rulează Docker, atunci rularea periodică a acestei comenzi ar trebui să devină un obicei.

Sursa: www.habr.com

Adauga un comentariu