Docker-Konsiloj: Forigu vian maŝinon de rubaĵo

Docker-Konsiloj: Forigu vian maŝinon de rubaĵo

Hej Habr! Mi prezentas al via atento la tradukon de la artikolo "Docker-Konsiloj: Purigu Vian Lokan Maŝinon" la verkisto Luc Juggery.

Hodiaŭ ni parolos pri kiel Docker uzas la diskspacon de la gastiga maŝino, kaj ni ankaŭ ekscios kiel liberigi ĉi tiun spacon de la pecetoj de neuzataj bildoj kaj ujoj.


Docker-Konsiloj: Forigu vian maŝinon de rubaĵo

Totala konsumo

Docker estas bonega afero, verŝajne malmultaj homoj dubas pri ĝi hodiaŭ. Antaŭ nur kelkaj jaroj, ĉi tiu produkto donis al ni tute novan manieron konstrui, liveri kaj funkciigi ajnan medion, permesante al ni grave ŝpari CPU- kaj RAM-resursojn. Krom ĉi tio (kaj por iuj ĉi tio estos la plej grava afero) Docker permesis al ni nekredeble simpligi kaj unuigi la vivciklan administradon de niaj produktadmedioj.

Tamen, ĉiuj ĉi tiuj ĝojoj de la moderna vivo havas prezon. Kiam ni prizorgas ujojn, elŝutas aŭ kreas niajn proprajn bildojn kaj disfaldis kompleksajn ekosistemojn, ni devas pagi. Kaj ni pagas, interalie, per diskospaco.

Se vi neniam pensis pri kiom da spaco Docker efektive okupas sur via maŝino, vi eble estos malagrable surprizita de la eligo de ĉi tiu komando:

$ docker system df

Docker-Konsiloj: Forigu vian maŝinon de rubaĵo

Ĉi tio montras la uzadon de disko de Docker en malsamaj kuntekstoj:

  • bildoj - la totala grandeco de bildoj, kiuj estis elŝutitaj el bilddeponejoj kaj konstruitaj sur via sistemo;
  • ujoj - la totala kvanto de diskspaco uzata per rulado de ujoj (signifas la totalan volumon de lego-skribaj tavoloj de ĉiuj ujoj);
  • local volumes - la volumeno de loka stokado muntita al ujoj;
  • konstrui kaŝmemoron - provizoraj dosieroj generitaj de la bilda konstruprocezo (uzante la ilon BuildKit, disponebla ekde Docker-versio 18.09).

Mi vetas, ke post ĉi tiu simpla translokigo vi deziras purigi vian diskon de rubo kaj revivigi altvalorajn gigabajtojn (notu: precipe se vi pagas lupagon por ĉi tiuj gigabajtoj ĉiumonate).

Disko-uzado per ujoj

Ĉiufoje kiam vi kreas ujon sur la gastiga maŝino, pluraj dosieroj kaj dosierujoj estas kreitaj en la dosierujo /var/lib/docker, inter kiuj estas rimarkindaj la jenaj:

  • Dosierujo /var/lib/docker/containers/container_ID - kiam vi uzas la norman protokolan pelilon, ĉi tie estas konservitaj evento-protokoloj en JSON-formato. Tro detalaj protokoloj, same kiel protokoloj, kiujn neniu legas aŭ alie prilaboras, ofte igas diskojn pleniĝi.
  • La dosierujo /var/lib/docker/overlay2 enhavas la ujajn lego-skribajn tavolojn (overlay2 estas la preferata pelilo en plej multaj Linuksaj distribuoj). Se la ujo stokas datumojn en sia dosiersistemo, tiam ĝi estas en ĉi tiu dosierujo, ke ĝi estos metita.

Ni imagu sistemon, sur kiu estas instalita netuŝita Docker, kiu neniam okupiĝis pri lanĉo de ujoj aŭ konstruado de bildoj. Ĝia raporto pri uzado de diskospaco aspektos jene:

$ 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

Ni lanĉu iun ujon, ekzemple NGINX:

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

Kio okazas al la disko:

  • bildoj okupas 126 MB, ĉi tiu estas la sama NGINX, kiun ni lanĉis en la ujo;
  • ujoj okupas ridindajn 2 bajtojn.

$ 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

Juĝante laŭ la konkludo, ni ankoraŭ ne havas iun spacon, kiun ni povus liberigi. Ĉar 2 bajtoj estas tute frivolaj, ni imagu, ke nia NGINX neatendite skribis ie 100 Megabajtojn da datumoj kaj kreis dosieron test.img de ĝuste ĉi tiu grandeco ene de si.

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

Ni ekzamenu denove la uzadon de diskospaco sur la gastiganto. Ni vidos, ke la ujo (ujoj) tie okupas 100 Megabajtojn.

$ 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

Mi pensas, ke via esplorema cerbo jam demandas, kie troviĝas nia test.img-dosiero. Ni serĉu ĝin:

$ 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

Sen eniri detalojn, ni povas rimarki, ke la test.img-dosiero estas oportune lokita ĉe la lego-skriba nivelo, kontrolita de la overlay2-ŝoforo. Se ni haltigas nian ujon, la gastiganto diros al ni, ke ĉi tiu spaco principe povas esti liberigita:

# 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

Kiel ni povas fari ĉi tion? Forigante la ujon, kio implicos malplenigi la respondan spacon ĉe la nivelo de legado-skriba.

Per la sekva komando, vi povas forigi ĉiujn instalitajn ujojn per unu paŝo kaj forigi vian diskon de ĉiuj legi-skribaj dosieroj kreitaj de ili:

$ 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

Do, ni liberigis 104,9 Megabajtojn forigante la ujon. Sed ĉar ni ne plu uzas la antaŭe elŝutitan bildon, ĝi ankaŭ fariĝas kandidato por forigi kaj liberigi niajn rimedojn:

$ 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

Noto: Dum la bildo estas uzata de almenaŭ unu ujo, vi ne povos uzi ĉi tiun lertaĵon.

La prune-subkomando, kiun ni uzis supre, nur efikas sur haltigitaj ujoj. Se ni volas forigi ne nur haltigitajn sed ankaŭ kurantajn ujojn, ni devus uzi unu el ĉi tiuj komandoj:

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

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

Flankaj notoj: se vi uzas la parametron -rm kiam vi ekfunkciigas ujon, tiam kiam ĝi ĉesas, la tuta diskospaco, kiun ĝi okupis, estos liberigita.

Uzante diskobildojn

Antaŭ kelkaj jaroj, bildgrandeco de kelkcent megabajtoj estis tute normala: bildo de Ubuntu pezis 600 megabajtojn, kaj bildo de Microsoft .Net pezis plurajn gigabajtojn. En tiuj vilaj tagoj, elŝuti nur unu bildon povus preni grandan koston sur via libera diskospaco, eĉ se vi kunhavis nivelojn inter bildoj. Hodiaŭ - laŭdo estu al la bonegaj - bildoj multe malpli pezas, sed eĉ tiel, vi povas rapide plenigi la disponeblajn rimedojn se vi ne prenas iujn antaŭzorgojn.

Estas pluraj specoj de bildoj kiuj ne estas rekte videblaj por la finuzanto:

  • mezaj bildoj, surbaze de kiuj aliaj bildoj estas kolektitaj - ili ne povas esti forigitaj se vi uzas ujojn bazitajn sur ĉi tiuj "aliaj" bildoj;
  • pendantaj bildoj estas mezaj bildoj, kiuj ne estas referencitaj de iu el la kurantaj ujoj - ili povas esti forigitaj.
  • Per la jena komando vi povas kontroli por pendantaj bildoj en via sistemo:

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

Vi povas forigi ilin jene:

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

Ni ankaŭ povas uzi la prune-subkomandon:

$ 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

Se ni subite volas forigi ĉiujn bildojn entute (kaj ne nur pendantajn) per unu komando, tiam ni povas fari ĉi tion:

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

Disko-uzado laŭ volumoj

Volumoj estas uzataj por stoki datumojn ekster la dosiersistemo de la ujo. Ekzemple, se ni volas konservi la rezultojn de aplikaĵo por uzi ilin alimaniere. Ofta ekzemplo estas datumbazoj.

Ni lanĉu MongoDB-ujon, muntu volumon eksteran al la ujo kaj restarigu datumbazan sekurkopion de ĝi (ni havas ĝin havebla en la bck.json-dosiero):

# 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

La datumoj troviĝos sur la gastiga maŝino en la dosierujo /var/lib/docker/volumes. Sed kial ne ĉe la lego-skriba nivelo de la ujo? Ĉar en la Dockerfile de la MongoDB-bildo, la dosierujo /data/db (kie MongoDB stokas siajn datumojn defaŭlte) estas difinita kiel volumo.

Docker-Konsiloj: Forigu vian maŝinon de rubaĵo

Flanka noto: multaj bildoj, kiuj devas produkti datumojn, uzas volumojn por stoki tiujn datumojn.

Kiam ni sufiĉe ludas kun MongoDB kaj ĉesas (aŭ eble eĉ forigas) la ujon, la volumo ne estos forigita. Ĝi daŭre okupos nian altvaloran diskspacon ĝis ni eksplicite forigos ĝin per komando tia:

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

Nu, aŭ ni povas uzi la prune-subkomandon, kiu jam estas konata al ni:

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

Uzante diskon por bildkonstrua kaŝmemoro

En Docker 18.09, la procezo de kreado de bildoj spertis kelkajn ŝanĝojn danke al la ilo BuildKit. Ĉi tiu afero pliigas la rapidecon de la procezo kaj optimumigas datumstokadon kaj sekurecan administradon. Ĉi tie ni ne konsideros ĉiujn detalojn de ĉi tiu mirinda ilo; ni nur koncentriĝos pri kiel ĝi traktas problemojn pri uzado de diskspaco.

Ni diru, ke ni havas tute simplan aplikaĵon Node.Js:

  • la index.js-dosiero komencas simplan HTTP-servilon, kiu respondas per linio al ĉiu ricevita peto:
  • la package.json dosiero difinas la dependecojn, el kiuj nur expressjs estas uzata por ruli la HTTP-servilon:

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

La Dockerfile por konstrui la bildon aspektas jene:

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

Ni konstruu la bildon laŭ la kutima maniero, sen uzi BuildKit:

$ docker build -t app:1.0 .

Se ni kontrolas la uzadon de la diskospaco, ni povas vidi, ke nur la baza bildo (nodo:13-alpine) kaj la cela bildo (app:1.0) okupas spacon:

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

Ni konstruu la duan version de nia aplikaĵo, uzante BuildKit. Por fari tion, ni nur bezonas agordi la variablon DOCKER_BUILDKIT al 1:

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

Se ni nun kontrolas la uzadon de la disko, ni vidos, ke la konstrukaŝmemoro (buid-cache) nun estas implikita tie:

$ 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

Por forigi ĝin, uzu la jenan komandon:

$ 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

Forigi ĉion!

Do, ni rigardis purigadon de diskospaco okupita de ujoj, bildoj kaj volumoj. La prune-subkomando helpas nin pri tio. Sed ĝi ankaŭ povas esti uzata ĉe la docker-sistema nivelo, kaj ĝi purigos ĉion, kion ĝi povas:

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

Se ial vi ŝparas diskspacon sur maŝino, kiu funkcias Docker, tiam periode ruli ĉi tiun komandon devus fariĝi kutimo.

fonto: www.habr.com

Aldoni komenton