
Helló, Habr! Örömmel mutatom be az írás fordítását. szerző .
Ma arról beszélünk, hogy a Docker hogyan használja a gazdagép lemezterületét, és megnézzük, hogyan lehet ezt a teret felszabadítani a nem használt képek és konténerek maradványaitól.

Összes fogyasztás
A Docker nagyszerű dolog, szerintem ma már senki nem kételkedik ebben. Csak néhány évvel ezelőtt ez a termék egy teljesen új módot kínált bármely környezet felépítésére, szállítására és futtatására, lehetővé téve, hogy jelentősen megtakarítsuk a CPU és a RAM erőforrásait. Ezen kívül (és valakinek ez valószínűleg a legfontosabb) a Docker hihetetlenül egyszerűvé és egységessé tette a felhasznált munkakörnyezetek életciklusának kezelését.
Azonban mindezekért a modern élet szépségeiért fizetni kell. Amikor konténereket indítunk, képeket töltünk le vagy hozunk létre, összetett ökoszisztémákat indítunk el, akkor fizetünk. És fizetünk többek között lemezterülettel.
Ha még soha nem gondolt arra, hogy valójában mennyi helyet foglal el a Docker a gépén, akkor kellemetlenül meglepődhet ennek a parancsnak az outputján:
$ docker system df 
Itt látható a Docker lemezhasználata több szempontból:
- képek (images) – az összes letöltött és a rendszerében létrehozott képek teljes mérete;
- konténerek (containers) – a futó konténerek által használt lemezterület összértéke (a konténerek összes írás-olvasási rétegének összterjedelme);
- helyi kötetek (local volumes) – a konténerekhez csatolt helyi tárolók volumene;
- build cache – ideiglenes fájlok, amelyeket a képek építése során generál a BuildKit eszköz (amely a Docker 18.09-es verziójától érhető el).
Fogadok, hogy már a fenti egyszerű lista után türelmetlenül vágyik arra, hogy megtisztítsa a lemezt a szeméttől és visszahozza a értékes gigabájtokat (megjegyzés: különösen, ha ezekért a gigabájtokért havonta bérel, akkor kevesen örülnek).
Díjhasználat a konténerektől
Minden egyes konténer létrehozásakor a gazdagépen a /var/lib/docker könyvtárban több fájl és könyvtár jön létre, amelyek közül a következőket érdemes kiemelni:
- A katalog /var/lib/docker/containers/ID_konténer – a standard naplózó meghajtó használata esetén pont ide kerülnek az eseménynaplók JSON-formátumban. A túl részletes naplók, valamint azok a naplók, amelyeket senki nem olvas, és más módon nem dolgoznak fel, gyakran a lemezek túltöltésének okai.
- A katalog /var/lib/docker/overlay2 – a konténerek írás-olvasás rétegeit tartalmazza (az overlay2 a legtöbb Linux disztribúcióban preferált meghajtó). Ha a konténer adatokat tárol a fájlrendszerében, akkor azok itt lesznek elhelyezve.
Képzeljünk el egy rendszert, amelyen egy tiszta Docker van telepítve, soha nem indítottak el konténereket és nem készítettek képeket. A lemezhasználati jelentése így néz ki:
$ 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 0BIndítsunk el egy konténert, például NGINX-et:
$ docker container run --name www -d -p 8000:80 nginx:1.16Mi történik a lemezzel:
- a képek (images) 126 MB-ot foglalnak el, ez az a NGINX, amelyet a konténerben elindítottunk;
- a konténerek (containers) vicces 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 0BA kimenet alapján nem áll rendelkezésünkre olyan hely, amelyet felszabadíthatnánk. Mivel a 2 bájt teljesen vicc, képzeljük el, hogy NGINX-ünk senki által nem várt módon írt valahová 100 Megabájtot és létrehozott egy test.img nevű fájlt éppen ennyi méretben.
$ docker exec -ti www
dd if=/dev/zero of=test.img bs=1024 count=0 seek=$[1024*100]Ismét vizsgáljuk meg a lemezhasználatot a gazdagépen. Látni fogjuk, hogy a konténer (containers) ott 100 Megabájtot foglal 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 0BGondolom, hogy agyad már azon töri a fejét, hol van a test.img fájlunk. Nézzü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.imgAnélkül, hogy részletekbe bocsátkoznánk, megemlíthetjük, hogy a test.img fájl kényelmesen elhelyezkedik az overlay2 által kezelt olvasási-írási szinten. Ha azonban leállítjuk a konténert, a gazda jelezni fogja nekünk, hogy ezt a helyet elvileg felszabadíthatjuk:
# 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 0BHogyan tehetjük ezt meg? A konténer eltávolításával, ami felszabadítja a megfelelő helyet az olvasási-írási szinten.
A következő paranccsal egyszerre eltávolíthatja az összes telepített konténert, és megtisztíthatja a lemezt az általuk létrehozott összes fájltól az olvasási-írási szinten:
$ docker container prune
FIGYELEM! Ez eltávolítja az összes leállított konténert.
Biztosan folytatni szeretné? [y/N] y
Eltávolított konténerek:
5e7f8e5097ace9ef5518ebf0c6fc2062ff024efb495f11ccc89df21ec9b4dcc2
Összesen visszanyert terület: 104.9 MBTehát 104,9 Megabájtot szabadítottunk fel a konténer eltávolításával. Mivel azonban már nem használjuk a korábban letöltött képet, az is jelölt a törlésre, ezzel felszabadítva erőforrásainkat:
$ docker system df
TÍPUS ÖSSZES AKTÍV MÉRET VISSZANYERHETŐ
Képek 1 0 126M 126M (100%)
Konténerek 0 0 0B 0B
Helyi kötetek 0 0 0B 0B
Build Cache 0 0 0B 0BFigyelem: mindaddig, amíg a kép legalább egy konténer által használatban van, nem tudja használni ezt a trükköt.
A prune almód, amit fentebb használtunk, csak a leállított konténerekre hat. Ha szeretnénk eltávolítani nemcsak a leállított, hanem a futó konténereket is, érdemes az alábbi parancsok egyikét használni:
# Historical command
$ docker rm -f $(docker ps –aq)
# More recent command
$ docker container rm -f $(docker container ls -aq)Megjegyzések: ha a konténer indításakor a —rm paramétert használja, akkor annak leállításakor felszabadul minden lemezhely, amelyet elfoglalt.
A lemezhasználat képek által
Néhány évvel ezelőtt a néhány száz megabájtos kép teljesen normálisnak számított: az Ubuntu kép 600 Megabájt, míg a Microsoft .Net kép néhány Gigabájt. Azokban a homályos időkben egyedül egy kép letöltése is nagy kárt tehetett a szabad lemezterületében, még akkor is, ha megosztotta a szinteket a képek között. Ma - hála Istennek - a képek sokkal kisebbek, de még ebben az esetben is gyorsan megtölthetjük a meglévő erőforrásokat, ha nem fogadunk el néhány óvintézkedést.
Számos olyan képtípus létezik, amelyek a végfelhasználó számára közvetlenül nem láthatók:
- intermediate képek, amelyek alapján más képek készülnek – nem lehetnek törölve, ha ilyen „más” képek alapjául szolgáló tartályokat használunk;
- dangling képek – olyan intermediate képek, amelyekre nincs hivatkozás a futó tárolók közül – ezek törölhetők.
- A következő parancs segítségével ellenőrizheti a rendszerében a dangling képeket:
$ docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
none none 21e658fe5351 12 minutes ago 71.3MBEzeket a következő módon lehet törölni:
$ docker image rm $(docker image ls -f dangling=true -q)A prune alparancsot is használhatjuk:
$ docker image prune
WARNING! Ez törli az összes dangling képet.
Biztosan folytatni akarja? [y/N] y
Törölt képek:
törölt: sha256:143407a3cb7efa6e95761b8cd6cea25e3f41455be6d5e7cda
törölt: sha256:738010bda9dd34896bac9bbc77b2d60addd7738ad1a95e5cc
törölt: sha256:fa4f0194a1eb829523ecf3bad04b4a7bdce089c8361e2c347
törölt: sha256:c5041938bcb46f78bf2f2a7f0a0df0eea74c4555097cc9197
törölt: sha256:5945bb6e12888cf320828e0fd00728947104da82e3eb4452f
Összesen visszaszerezhető hely: 12.9kBHa mégis úgy döntenénk, hogy minden képet (nem csak a dangling képeket) egyszerre törlünk, akkor ezt tehetjük:
$ docker image rm $(docker image ls -q)Lemez használat a kötetekkel
A kötetek (volumes) az adatok tárolására szolgálnak a tartály fájlrendszerén kívül. Például, ha meg akarjuk őrizni egy alkalmazás működési eredményeit, hogy később valamilyen módon felhasználhassuk őket. Gyakori példa az adatbázisok.
Indítsuk el a MongoDB tárolót, csatlakoztassunk hozzá egy külső kötetet, és állítsuk vissza az adatbázis mentését (ez 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
--jsonArrayAz adatok a gazdagépen a /var/lib/docker/volumes könyvtárban fognak található lenni. De miért nem a konténer olvasási-írási szintjén? Mert a MongoDB Dockerfile képében a /data/db könyvtár (ahol a MongoDB alapértelmezés szerint tárolja az adatait) kötetként van definiálva.

Megjegyzések a margón: sok olyan kép, amelynek működése során adatokat kell létrehozni, köteteket (volumes) használ az adatok megőrzésére.
Amikor elegünk van a MongoDB-ből és leállítjuk (vagy akár töröljük) a tárolót, a kötet nem fog törlődni. Továbbra is elfoglalja a drága lemezterületünket, amíg kifejezetten nem töröljük ezzel a paranccsal:
$ docker volume rm $(docker volume ls -q)Vagy használhatjuk már megszokott alparancsunkat is, a prune-t:
$ docker volume prune
FIGYELMEZTETÉS! Ez eltávolítja az összes olyan helyi tárolót, amelyet legalább egy konténer sem használ.
Biztosan folytatni akarja? [y/N] y
Eltávolított tárolók:
d50b6402eb75d09ec17a5f57df4ed7b520c448429f70725fc5707334e5ded4d5
8f7a16e1cf117cdfddb6a38d1f4f02b18d21a485b49037e2670753fa34d115fc
599c3dd48d529b2e105eec38537cd16dac1ae6f899a123e2a62ffac6168b2f5f
...
732e610e435c24f6acae827cd340a60ce4132387cfc512452994bc0728dd66df
9a3f39cc8bd0f9ce54dea3421193f752bda4b8846841b6d36f8ee24358a85bae
045a9b534259ec6c0318cb162b7b4fca75b553d4e86fc93faafd0e7c77c79799
c6283fe9f8d2ca105d30ecaad31868410e809aba0909b3e60d68a26e92a094da
Összesen visszaállított terület: 25.82GB
luc@saturn:~$Lemezhasználat az image build cache-hez
A Docker 18.09 verziójában az image-ek létrehozása során néhány változás történt a BuildKit eszköz köszönhetően. Ezen eszköz révén javul a folyamat sebessége, és optimalizálódik az adatok tárolásának és biztonságának kezelése. Ebben a szövegben nem tárgyaljuk az összes részletét ennek a nagyszerű eszköznek, csak azt, hogy miként befolyásolja a lemezhasználatot.
Tegyük fel, hogy van egy nagyon egyszerű Node.js alkalmazásunk:
- a index.js fájl elindít egy egyszerű HTTP szervert, amely egy üzenettel válaszol minden érkező kérésre:
- a package.json fájl defines dependencies, of which only expressjs is used to run the HTTP server:
$ 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 Dockerfile az image építéséhez í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"]Most építsük meg az image-t a szokásos módon, BuildKit használata nélkül:
$ docker build -t app:1.0 .Ha ellenőrizzük a lemezhasználatot, láthatjuk, hogy csak az alap image (node:13-alpine) és a végleges image (app:1.0) foglal helyet:
TIPUS ÖSSZES AKTÍV MÉRET VISSZANYERHETŐ
Képek 2 0 109.3MB 109.3MB (100%)
Konténerek 0 0 0B 0B
Helyi tárolók 0 0 0B 0B
Build Cache 0 0 0B 0BMost építsük meg a második verzióját az alkalmazásunknak, már a BuildKit használatával. Ehhez csupán annyira van szükség, hogy a DOCKER_BUILDKIT változót 1-re állítsuk:
$ DOCKER_BUILDKIT=1 docker build -t app:2.0 .Ha most ellenőrizzük a lemezhasználatot, láthatjuk, hogy most már a build cache is részt vesz (build-cache):
$ docker system df
TIPUS ÖSSZES AKTÍV MÉRET VISSZANYERHETŐ
Képek 2 0 109,3MB 109,3MB (100%)
Konténerek 0 0 0B 0B
Helyi kötetek 0 0 0B 0B
Build Cache 11 0 8,949kB 8,949kBA tisztításhoz használjuk a következő parancsot:
$ docker builder prune
FIGYELMEZTETÉS! Ez eltávolítja az összes lógó build cache-t.
Biztos benne, hogy folytatni szeretné? [y/N] y
Törölt build cache objektumok:
rffq7b06h9t09xe584rn4f91e
ztexgsz949ci8mx8p5tzgdzhe
3z9jeoqbbmj3eftltawvkiayi
Összesen visszanyert hely: 8,949kBTisztíts meg mindent!
Tehát áttekintettük a disk space megtisztítását, amelyet a konténerek, képek és kötetek foglalnak el. Ebben segít nekünk a prune almuk. De ezt a Docker rendszer szintjén is felhasználhatjuk, és minden eltávolításra kerül, amit csak lehet:
$ docker system prune
FIGYELMEZTETÉS! Ez eltávolítja:
- minden leállított konténert
- minden hálózatot, amelyet legalább egy konténer sem használ
- minden lógó képet
- minden lógó build cache-t
Biztos benne, hogy folytatni szeretné? [y/N]Ha bármilyen okból megtakarítja a lemezterületet a Docker-t futtató gépen, akkor érdemes időnként ezt a parancsot futtatni.
Forrás: habr.com
