Docker Tips: Rensa din maskin från skräp

Docker Tips: Rensa din maskin från skräp

Hej, Habr! Jag presenterar för din uppmärksamhet en översättning av artikeln "Docker Tips: Rensa upp din lokala maskin" författare Luc Juggery.

Idag kommer vi att prata om hur Docker använder diskutrymmet på värddatorn, och vi kommer också att ta reda på hur man frigör detta utrymme från rester av oanvända bilder och behållare.


Docker Tips: Rensa din maskin från skräp

Total förbrukning

Docker är en cool grej, förmodligen är det få som tvivlar på det idag. För bara några år sedan gav den här produkten oss ett helt nytt sätt att bygga, leverera och köra vilken miljö som helst, vilket gjorde att vi avsevärt kunde spara CPU- och RAM-resurser. Utöver detta (och för vissa kommer detta att vara det viktigaste) har Docker tillåtit oss att otroligt förenkla och förena livscykelhanteringen i våra produktionsmiljöer.

Men alla dessa nöjen i det moderna livet har ett pris. När vi kör containrar, laddar ner eller skapar våra egna bilder och distribuerar komplexa ekosystem måste vi betala. Och vi betalar bland annat med diskutrymme.

Om du aldrig har tänkt på hur mycket utrymme Docker faktiskt tar på din maskin, kan du bli obehagligt överraskad av resultatet av detta kommando:

$ docker system df

Docker Tips: Rensa din maskin från skräp

Detta visar Dockers diskanvändning i olika sammanhang:

  • bilder – den totala storleken på bilder som laddades ner från bildarkiv och byggdes på ditt system;
  • behållare – den totala mängden diskutrymme som används av att köra behållare (vilket betyder den totala volymen av läs-skrivlager för alla behållare);
  • lokala volymer – volymen lokal lagring monterad på containrar;
  • build cache – temporära filer som genereras av bildbyggnadsprocessen (med hjälp av BuildKit-verktyget, tillgängligt från Docker version 18.09).

Jag slår vad om att du efter denna enkla överföring är ivrig att rensa din disk från skräp och väcka värdefulla gigabyte till liv igen (obs: speciellt om du betalar hyra för dessa gigabyte varje månad).

Diskanvändning av behållare

Varje gång du skapar en behållare på värddatorn skapas flera filer och kataloger i katalogen /var/lib/docker, bland vilka följande är värda att notera:

  • Katalog /var/lib/docker/containers/container_ID – när du använder standardloggningsdrivrutinen är det här händelseloggarna sparas i JSON-format. För detaljerade loggar, liksom loggar som ingen läser eller på annat sätt bearbetar, gör ofta att diskarna blir fulla.
  • Katalogen /var/lib/docker/overlay2 innehåller behållarens läs-skrivskikt (overlay2 är den föredragna drivrutinen i de flesta Linux-distributioner). Om behållaren lagrar data i sitt filsystem, är det i denna katalog som den kommer att placeras.

Låt oss föreställa oss ett system där en orörd Docker är installerad, som aldrig har varit inblandad i att lansera containrar eller bygga bilder. Dess diskutrymmesanvändningsrapport kommer att se ut så här:

$ 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

Låt oss lansera en behållare, till exempel NGINX:

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

Vad händer med disken:

  • bilder upptar 126 MB, detta är samma NGINX som vi lanserade i behållaren;
  • behållare tar upp löjliga 2 byte.

$ 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

Av slutsatsen att döma har vi ännu inte något utrymme som vi skulle kunna frigöra. Eftersom 2 byte är helt oseriöst, låt oss föreställa oss att vår NGINX oväntat skrev någonstans 100 megabyte data och skapade en fil test.img av exakt denna storlek inuti sig själv.

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

Låt oss undersöka diskutrymmesanvändningen på värden igen. Vi kommer att se att behållaren (behållarna) upptar 100 megabyte där.

$ 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

Jag tror att din nyfikna hjärna redan undrar var vår test.img-fil finns. Låt oss leta efter det:

$ 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

Utan att gå in på detaljer kan vi notera att test.img-filen är bekvämt placerad på läs-skrivnivån, kontrollerad av overlay2-drivrutinen. Om vi ​​stoppar vår container kommer värden att berätta för oss att detta utrymme i princip kan frigöras:

# 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

Hur kan vi göra detta? Genom att ta bort behållaren, vilket kommer att innebära att motsvarande utrymme rensas på läs-skrivnivå.

Med följande kommando kan du ta bort alla installerade behållare i ett svep och rensa din disk från alla läs-skrivfiler som skapats av dem:

$ 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

Så vi frigjorde 104,9 megabyte genom att ta bort behållaren. Men eftersom vi inte längre använder den tidigare nedladdade bilden, blir den också en kandidat för att radera och frigöra våra resurser:

$ 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

Obs! Så länge bilden används av minst en behållare kommer du inte att kunna använda det här tricket.

Underkommandot för prune vi använde ovan har bara effekt på stoppade behållare. Om vi ​​vill ta bort inte bara stoppade utan även körande behållare bör vi använda ett av dessa kommandon:

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

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

Sidanteckningar: om du använder parametern -rm när du startar en behållare, och när den slutar, kommer allt diskutrymme som den upptog att frigöras.

Använda diskbilder

För några år sedan var en bildstorlek på flera hundra megabyte helt normal: en Ubuntu-bild vägde 600 megabyte och en Microsoft .Net-bild vägde flera gigabyte. Under dessa lurviga dagar kunde nedladdning av bara en bild ta en stor belastning på ditt lediga diskutrymme, även om du delade nivåer mellan bilder. Idag – beröm till de stora – väger bilder mycket mindre, men trots det kan du snabbt fylla på tillgängliga resurser om du inte vidtar några försiktighetsåtgärder.

Det finns flera typer av bilder som inte är direkt synliga för slutanvändaren:

  • mellanliggande bilder, på grundval av vilka andra bilder samlas in - de kan inte raderas om du använder behållare baserade på dessa "andra" bilder;
  • dinglande bilder är mellanliggande bilder som inte refereras av någon av de körande behållarna - de kan raderas.
  • Med följande kommando kan du leta efter hängande bilder på ditt system:

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

Du kan ta bort dem på följande sätt:

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

Vi kan också använda underkommandot 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

Om vi ​​plötsligt vill ta bort alla bilder helt och hållet (och inte bara dinglande) med ett kommando, så kan vi göra så här:

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

Diskanvändning efter volymer

Volymer används för att lagra data utanför containerns filsystem. Till exempel om vi vill spara resultaten av en applikation för att kunna använda dem på annat sätt. Ett vanligt exempel är databaser.

Låt oss starta en MongoDB-behållare, montera en volym utanför behållaren och återställa en databassäkerhetskopiering från den (vi har den tillgänglig i filen 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

Data kommer att finnas på värddatorn i katalogen /var/lib/docker/volumes. Men varför inte på containerns läs-skrivnivå? Eftersom i Dockerfilen för MongoDB-avbildningen, definieras /data/db-katalogen (där MongoDB lagrar sina data som standard) som en volym.

Docker Tips: Rensa din maskin från skräp

Sidanteckning: många bilder som måste producera data använder volymer för att lagra dessa data.

När vi spelar tillräckligt med MongoDB och stoppar (eller kanske till och med tar bort) behållaren kommer volymen inte att raderas. Det kommer att fortsätta att ta upp vårt värdefulla diskutrymme tills vi uttryckligen tar bort det med ett kommando som detta:

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

Tja, eller så kan vi använda underkommandot prune som redan är bekant för oss:

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

Använder disk för bildbyggande cache

I Docker 18.09 har bildskapandeprocessen genomgått vissa förändringar tack vare BuildKit-verktyget. Denna sak ökar hastigheten på processen och optimerar datalagring och säkerhetshantering. Här kommer vi inte att överväga alla detaljer i detta underbara verktyg; vi kommer bara att fokusera på hur det tar upp problem med diskutrymmesanvändning.

Låt oss säga att vi har en helt enkel Node.Js-applikation:

  • filen index.js startar en enkel HTTP-server som svarar med en rad på varje mottagen begäran:
  • filen package.json definierar beroenden, av vilka endast expressjs används för att köra HTTP-servern:

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

Dockerfilen för att bygga bilden ser ut så här:

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

Låt oss bygga bilden på vanligt sätt, utan att använda BuildKit:

$ docker build -t app:1.0 .

Om vi ​​kontrollerar diskutrymmesanvändningen kan vi se att endast basbilden (nod:13-alpin) och målbilden (app:1.0) tar upp utrymme:

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

Låt oss bygga den andra versionen av vår applikation med BuildKit. För att göra detta behöver vi bara ställa in variabeln DOCKER_BUILDKIT till 1:

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

Om vi ​​nu kontrollerar diskanvändningen kommer vi att se att build-cachen (buid-cache) nu är inblandad där:

$ 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

För att rensa det, använd följande kommando:

$ 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

Rensa alla!

Så vi tittade på att rensa upp diskutrymme som upptas av behållare, bilder och volymer. Underkommandot prune hjälper oss med detta. Men det kan också användas på dockar-systemnivå, och det kommer att rensa upp allt det kan:

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

Om du av någon anledning sparar diskutrymme på en dator som kör Docker, bör det bli en vana att köra detta kommando med jämna mellanrum.

Källa: will.com

Lägg en kommentar