Docker tippek: Tisztítsa meg a gépet a szeméttől

Docker tippek: Tisztítsa meg a gépet a szeméttől

Szia Habr! Figyelmébe ajánlom a cikk fordítását "Dokker tippek: tisztítsa meg a helyi gépet" szerző Luc Juggery.

Ma arról fogunk beszélni, hogy a Docker hogyan használja fel a gazdagép lemezterületét, és azt is kitaláljuk, hogyan szabadítsuk fel ezt a helyet a fel nem használt képek és konténerek maradékaitól.


Docker tippek: Tisztítsa meg a gépet a szeméttől

Teljes fogyasztás

A Docker klassz dolog, valószínűleg ma már kevesen kételkednek benne. Alig néhány évvel ezelőtt ez a termék teljesen új módot adott nekünk bármilyen környezet felépítésére, szállítására és futtatására, lehetővé téve számunkra, hogy jelentősen megtakarítsuk a CPU és a RAM erőforrásait. Ezen túlmenően (és egyesek számára ez lesz a legfontosabb) a Docker lehetővé tette számunkra, hogy hihetetlenül leegyszerűsítsük és egységesítsük termelési környezeteink életciklus-kezelését.

A modern élet minden örömének azonban ára van. Amikor konténereket futtatunk, letöltjük vagy létrehozzuk saját képeinket, és összetett ökoszisztémákat telepítünk, fizetnünk kell. És fizetünk többek között lemezterülettel.

Ha soha nem gondolt arra, hogy a Docker valójában mennyi helyet foglal el a gépén, akkor kellemetlen meglepetés lehet a parancs kimenete:

$ docker system df

Docker tippek: Tisztítsa meg a gépet a szeméttől

Ez a Docker lemezhasználatát mutatja különböző kontextusokban:

  • képek – a képtárakból letöltött és a rendszerre épített képek teljes mérete;
  • konténerek – a futó tárolók által felhasznált lemezterület teljes mennyisége (az összes tároló írás-olvasási rétegeinek teljes mennyisége);
  • helyi térfogatok – a konténerekre szerelt helyi tárolók térfogata;
  • build cache – a képalkotási folyamat által generált ideiglenes fájlok (a BuildKit eszközzel, amely a Docker 18.09-es verziójától elérhető).

Lefogadom, hogy ezen egyszerű átvitel után szívesen megtisztítja lemezét a szeméttől, és értékes gigabájtokat kelthet újra életre (megjegyzés: különösen, ha havonta bérleti díjat fizet ezekért a gigabájtokért).

Lemezhasználat tárolók szerint

Minden alkalommal, amikor létrehoz egy tárolót a gazdagépen, több fájl és könyvtár jön létre a /var/lib/docker könyvtárban, amelyek közül a következőket érdemes megjegyezni:

  • /var/lib/docker/containers/container_ID könyvtár – a szabványos naplózási illesztőprogram használatakor ez az a hely, ahol a rendszer az eseménynaplókat JSON formátumban menti. A túl részletes naplók, valamint a senki által nem olvasott vagy más módon nem feldolgozott naplók gyakran a lemezek megtelését okozzák.
  • A /var/lib/docker/overlay2 könyvtár tartalmazza a konténer olvasási-írási rétegeit (az overlay2 a preferált illesztőprogram a legtöbb Linux disztribúcióban). Ha a tároló adatokat tárol a fájlrendszerében, akkor ebbe a könyvtárba kerül.

Képzeljünk el egy olyan rendszert, amelyre egy érintetlen Docker van telepítve, amely soha nem vett részt konténerek kilövésében vagy képek készítésében. A lemezterület-használati jelentése így fog kinézni:

$ 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

Indítsunk el néhány tárolót, például az NGINX-et:

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

Mi történik a lemezzel:

  • a képek 126 MB-ot foglalnak el, ez ugyanaz az NGINX, amelyet a tárolóban indítottunk el;
  • a konténerek nevetséges 2 bájtot foglalnak el.

$ 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

A következtetésből ítélve még nincs szabad helyünk. Mivel a 2 bájt teljesen komolytalan, képzeljük el, hogy az NGINX-ünk váratlanul írt valahova 100 Megabájt adatot, és egy pontosan ekkora test.img fájlt hozott létre magában.

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

Vizsgáljuk meg újra a gép lemezterület-használatát. Látni fogjuk, hogy a konténer (konténerek) ott 100 megabájtot foglalnak el.

$ 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

Azt hiszem, a kíváncsi agyad már azon töpreng, hol található a test.img fájlunk. Keressük meg:

$ 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

Anélkül, hogy belemennénk a részletekbe, megjegyezhetjük, hogy a test.img fájl kényelmesen az olvasási-írási szinten található, az overlay2 illesztőprogram által vezérelve. Ha leállítjuk a konténerünket, a fogadó közli velünk, hogy ez a hely elvileg felszabadul:

# 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

Hogyan tudjuk ezt megtenni? A tároló törlésével, ami a megfelelő terület törlését vonja maga után olvasási-írási szinten.

A következő paranccsal egy csapásra eltávolíthatja az összes telepített tárolót, és megtisztíthatja a lemezt az általuk létrehozott írás-olvasási fájloktól:

$ 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

Tehát a tároló törlésével 104,9 megabájtot szabadítunk fel. De mivel már nem használjuk a korábban letöltött képet, ez is alkalmassá válik az erőforrásaink törlésére és felszabadítására:

$ 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

Megjegyzés: Amíg a képet legalább egy tároló használja, nem fogja tudni használni ezt a trükköt.

A fentebb használt prune alparancs csak a leállított tárolókra van hatással. Ha nem csak leállított, hanem futó konténereket is szeretnénk törölni, akkor az alábbi parancsok egyikét kell használnunk:

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

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

Mellékes megjegyzések: ha az -rm paramétert használja egy tároló indításakor, akkor amikor az leáll, az összes elfoglalt lemezterület felszabadul.

Lemezképek használata

Néhány éve még teljesen normálisnak számított a több száz megabájtos képméret: egy Ubuntu kép 600 megabájtot, egy Microsoft .Net kép több gigabájtot nyomott. Azokban a borongós napokban egyetlen kép letöltése nagy terhet róhat a szabad lemezterületre, még akkor is, ha megosztja a szinteket a képek között. Ma - dicséret a nagyoknak - a képek sokkal kisebb súlyúak, de még így is gyorsan feltöltheted a rendelkezésre álló forrásokat, ha nem teszel némi óvintézkedést.

Számos képtípus létezik, amelyek nem láthatók közvetlenül a végfelhasználó számára:

  • köztes képek, amelyek alapján más képeket gyűjtenek - nem törölhetők, ha ezeken az „egyéb” képeken alapuló tárolókat használ;
  • A lógó képek köztes képek, amelyekre egyik futó tároló sem hivatkozik – törölhetők.
  • A következő paranccsal ellenőrizheti, hogy nincsenek-e lelógó képek a rendszeren:

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

A következő módon távolíthatja el őket:

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

Használhatjuk a prune alparancsot is:

$ 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

Ha hirtelen egy paranccsal törölni akarjuk az összes képet (és nem csak a lógást), akkor ezt megtehetjük:

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

Lemezhasználat kötetenként

A kötetek a tároló fájlrendszerén kívüli adatok tárolására szolgálnak. Például, ha el akarjuk menteni egy alkalmazás eredményeit, hogy más módon használhassuk azokat. Gyakori példa az adatbázisok.

Indítsunk el egy MongoDB tárolót, csatlakoztassunk egy külső kötetet a tárolóhoz, és állítsunk vissza belőle egy adatbázis biztonsági másolatot (a bck.json fájlban elérhető):

# 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

Az adatok a gazdagépen a /var/lib/docker/volumes könyvtárban lesznek. De miért nem a tároló olvasási-írási szintjén? Mivel a MongoDB lemezkép Dockerfile-jában a /data/db könyvtár (ahol a MongoDB alapértelmezés szerint tárolja az adatait) kötetként van megadva.

Docker tippek: Tisztítsa meg a gépet a szeméttől

Mellékes megjegyzés: sok olyan kép, amelynek adatokat kell termelnie, köteteket használ az adatok tárolására.

Ha eleget játszunk a MongoDB-vel, és leállítjuk (vagy akár töröljük is) a tárolót, a kötet nem törlődik. Továbbra is elfoglalja értékes lemezterületünket, amíg kifejezetten ki nem töröljük egy ehhez hasonló paranccsal:

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

Nos, vagy használhatjuk a számunkra már jól ismert prune alparancsot:

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

Lemez használata képkészítési gyorsítótárhoz

A Docker 18.09-ben a képalkotási folyamat néhány változáson ment keresztül a BuildKit eszköznek köszönhetően. Ez növeli a folyamat sebességét, és optimalizálja az adattárolást és a biztonságkezelést. Itt nem vesszük figyelembe ennek a csodálatos eszköznek az összes részletét, csak arra összpontosítunk, hogyan kezeli a lemezterület-használat problémáit.

Tegyük fel, hogy van egy teljesen egyszerű Node.Js alkalmazásunk:

  • az index.js fájl elindít egy egyszerű HTTP-kiszolgálót, amely egy sorral válaszol minden fogadott kérésre:
  • a package.json fájl határozza meg a függőségeket, amelyek közül csak expressjs használható a HTTP-kiszolgáló futtatásához:

$ 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"
      }
    }

A kép elkészítéséhez használt Dockerfile így néz ki:

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

Építsük meg a képet a szokásos módon, BuildKit használata nélkül:

$ docker build -t app:1.0 .

Ha ellenőrizzük a lemezterület-használatot, láthatjuk, hogy csak az alapkép (node:13-alpine) és a célkép (app:1.0) foglal helyet:

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

Készítsük el az alkalmazásunk második verzióját a BuildKit segítségével. Ehhez csak a DOCKER_BUILDKIT változót 1-re kell állítanunk:

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

Ha most ellenőrizzük a lemezhasználatot, látni fogjuk, hogy a build gyorsítótár (buid-cache) most benne van:

$ 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

A törléséhez használja a következő parancsot:

$ 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

Mindent kitöröl!

Tehát megvizsgáltuk a konténerek, képek és kötetek által elfoglalt lemezterület megtisztítását. Ebben segít nekünk az aszalt szilva alparancs. De docker rendszerszinten is használható, és mindent megtisztít, amit csak tud:

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

Ha valamilyen okból lemezterületet takarít meg a Docker-gépen, akkor ennek a parancsnak a rendszeres futtatása szokássá válik.

Forrás: will.com

Hozzászólás