Consellos de Docker: limpar a súa máquina de lixo

Consellos de Docker: limpar a súa máquina de lixo

Ola Habr! Presento á súa atención a tradución do artigo "Consellos de Docker: Limpe a súa máquina local" autor Luc Juggery.

Hoxe falaremos de como usa Docker o espazo en disco da máquina host, e tamén descubriremos como liberar este espazo dos restos de imaxes e contedores non utilizados.


Consellos de Docker: limpar a súa máquina de lixo

Consumo total

Docker é algo interesante, probablemente pouca xente o dubide hoxe. Hai só uns anos, este produto proporcionounos unha forma completamente nova de construír, entregar e executar calquera ambiente, permitíndonos aforrar significativamente recursos de CPU e RAM. Ademais disto (e para algúns isto será o máis importante) Docker permitiunos simplificar e unificar incriblemente a xestión do ciclo de vida dos nosos contornos de produción.

Non obstante, todas estas delicias da vida moderna teñen un prezo. Cando executamos contedores, descargamos ou creamos as nosas propias imaxes e implementamos ecosistemas complexos, temos que pagar. E pagamos, entre outras cousas, con espazo en disco.

Se nunca pensaches en canto espazo ocupa realmente Docker na túa máquina, pode que te sorprendas desagradablemente a saída deste comando:

$ docker system df

Consellos de Docker: limpar a súa máquina de lixo

Isto mostra o uso do disco de Docker en diferentes contextos:

  • imaxes: o tamaño total das imaxes que se descargaron dos repositorios de imaxes e construídas no seu sistema;
  • contenedores: a cantidade total de espazo en disco utilizado polos contedores en execución (é dicir, o volume total de capas de lectura e escritura de todos os contedores);
  • volumes locais: o volume de almacenamento local montado nos contedores;
  • caché de compilación: ficheiros temporais xerados polo proceso de creación de imaxes (usando a ferramenta BuildKit, dispoñible a partir da versión 18.09 de Docker).

Aposto a que despois desta sinxela transferencia estás ansioso por limpar o teu disco de lixo e devolverlle á vida os preciosos gigabytes (nota: especialmente se pagas o aluguer por estes gigabytes todos os meses).

Uso do disco por contedores

Cada vez que crea un contedor na máquina host, créanse varios ficheiros e directorios no directorio /var/lib/docker, entre os que cabe destacar os seguintes:

  • Directorio /var/lib/docker/containers/container_ID: cando se usa o controlador de rexistro estándar, aquí se gardan os rexistros de eventos en formato JSON. Os rexistros demasiado detallados, así como os rexistros que ninguén le ou procesa, adoitan provocar que os discos se cheguen.
  • O directorio /var/lib/docker/overlay2 contén as capas de lectura e escritura do contedor (overlay2 é o controlador preferido na maioría das distribucións de Linux). Se o contedor almacena datos no seu sistema de ficheiros, entón será neste directorio onde se colocarán.

Imaxinemos un sistema no que se instala un Docker prístino, que nunca estivo implicado no lanzamento de contedores nin na construción de imaxes. O seu informe de uso de espazo en disco terá o seguinte aspecto:

$ 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

Imos lanzar algún contedor, por exemplo, NGINX:

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

Que pasa co disco:

  • as imaxes ocupan 126 MB, este é o mesmo NGINX que lanzamos no contedor;
  • os contedores ocupan 2 bytes ridículos.

$ 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 xulgar pola conclusión, aínda non temos ningún espazo que poidamos liberar. Xa que 2 bytes son completamente frívolos, imaxinemos que o noso NGINX escribiu de forma inesperada nalgún lugar 100 Megabytes de datos e creou un ficheiro test.img de exactamente este tamaño dentro de si.

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

Examinemos de novo o uso de espazo no disco no servidor. Veremos que o contedor (contedores) ocupa alí 100 Megabytes.

$ 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

Creo que o teu cerebro inquisitivo xa se pregunta onde está o noso ficheiro test.img. Buscámolo:

$ 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 entrar en detalles, podemos observar que o ficheiro test.img está convenientemente situado no nivel de lectura-escritura, controlado polo controlador overlay2. Se paramos o noso contedor, o anfitrión indicaranos que este espazo pode, en principio, liberarse:

# 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

Como podemos facer isto? Ao eliminar o contedor, o que implicará limpar o espazo correspondente no nivel de lectura-escritura.

Co seguinte comando, pode eliminar todos os contedores instalados dunha soa vez e borrar o disco de todos os ficheiros de lectura e escritura creados por eles:

$ 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

Entón, liberamos 104,9 Megabytes eliminando o contedor. Pero como xa non usamos a imaxe descargada anteriormente, tamén se converte en candidata para eliminar e liberar os nosos recursos:

$ 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

Nota: mentres a imaxe estea en uso polo menos nun recipiente, non poderás usar este truco.

O subcomando prune que usamos anteriormente só ten un efecto nos contedores parados. Se queremos eliminar non só os contedores parados senón tamén en execución, deberíamos usar un destes comandos:

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

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

Notas paralelas: se usa o parámetro -rm ao iniciar un contedor, cando se deteña, liberarase todo o espazo no disco que ocupaba.

Usando imaxes de disco

Hai uns anos, un tamaño de imaxe de varios centos de megabytes era completamente normal: unha imaxe de Ubuntu pesaba 600 megabytes e unha imaxe de Microsoft .Net pesaba varios gigabytes. Naqueles días turbios, descargar só unha imaxe podería supoñer un gran peaxe no espazo libre do teu disco, aínda que compartises niveis entre imaxes. Hoxe, eloxios sexan os grandes, as imaxes pesan moito menos, pero aínda así, podes encher rapidamente os recursos dispoñibles se non tomas algunhas precaucións.

Hai varios tipos de imaxes que non son directamente visibles para o usuario final:

  • imaxes intermedias, en función das cales se recollen outras imaxes: non se poden eliminar se usas contedores baseados nestas "outras" imaxes;
  • As imaxes colgantes son imaxes intermedias ás que ningún dos contedores en execución non fai referencia: pódense eliminar.
  • Co seguinte comando pode comprobar se hai imaxes colgantes no seu sistema:

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

Podes eliminalos do seguinte xeito:

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

Tamén podemos usar o subcomando 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

Se de súpeto queremos eliminar todas as imaxes por completo (e non só colgando) cun comando, entón podemos facelo:

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

Uso do disco por volumes

Os volumes úsanse para almacenar datos fóra do sistema de ficheiros do contedor. Por exemplo, se queremos gardar os resultados dunha aplicación para utilizalos doutro xeito. Un exemplo común son as bases de datos.

Lancemos un contedor MongoDB, montemos un volume externo ao contedor e restauremos unha copia de seguridade da base de datos a partir del (témolo dispoñible no ficheiro 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

Os datos localizaranse na máquina host no directorio /var/lib/docker/volumes. Pero por que non a nivel de lectura-escritura do contedor? Porque no Dockerfile da imaxe MongoDB, o directorio /data/db (onde MongoDB almacena os seus datos por defecto) defínese como un volume.

Consellos de Docker: limpar a súa máquina de lixo

Nota lateral: moitas imaxes que deben producir datos usan volumes para almacenar eses datos.

Cando xogamos o suficiente con MongoDB e detemos (ou quizais mesmo eliminamos) o contedor, o volume non se eliminará. Seguirá ocupando o noso precioso espazo no disco ata que o eliminemos explícitamente cun comando como este:

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

Ben, ou podemos usar o subcomando prune que xa nos é 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:~$

Usando o disco para a caché de construción de imaxes

En Docker 18.09, o proceso de creación de imaxes sufriu algúns cambios grazas á ferramenta BuildKit. Isto aumenta a velocidade do proceso e optimiza o almacenamento de datos e a xestión da seguridade. Aquí non consideraremos todos os detalles desta marabillosa ferramenta; só nos centraremos en como aborda os problemas de uso do espazo no disco.

Digamos que temos unha aplicación Node.Js completamente sinxela:

  • o ficheiro index.js inicia un servidor HTTP sinxelo que responde cunha liña a cada solicitude recibida:
  • o ficheiro package.json define as dependencias, das cales só se usa expressjs para executar o servidor 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"
      }
    }

O Dockerfile para construír a imaxe ten o seguinte aspecto:

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

Imos construír a imaxe do xeito habitual, sen usar BuildKit:

$ docker build -t app:1.0 .

Se comprobamos o uso de espazo no disco, podemos ver que só a imaxe base (nodo:13-alpine) e a imaxe de destino (app:1.0) ocupan espazo:

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

Imos construír a segunda versión da nosa aplicación, usando BuildKit. Para iso, só necesitamos establecer a variable DOCKER_BUILDKIT en 1:

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

Se agora comprobamos o uso do disco, veremos que a caché de compilación (buid-cache) está agora implicada alí:

$ 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

Para borralo, use o seguinte comando:

$ 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

Borrar todo!

Entón, miramos a limpar o espazo no disco ocupado por contedores, imaxes e volumes. O subcomando prune axúdanos con isto. Pero tamén se pode usar a nivel do sistema docker e limpará todo o que poida:

$ 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 por algún motivo estás aforrar espazo no disco nunha máquina que executa Docker, executar periodicamente este comando debería converterse nun hábito.

Fonte: www.habr.com

Engadir un comentario