Petua Docker: Kosongkan mesin anda daripada sampah

Petua Docker: Kosongkan mesin anda daripada sampah

Hello, Habr! Saya membentangkan kepada anda terjemahan artikel "Petua Docker: Bersihkan Mesin Tempatan Anda" pengarang Luc Juggery.

Hari ini kita akan bercakap tentang cara Docker menggunakan ruang cakera mesin hos, dan kami juga akan memikirkan cara untuk membebaskan ruang ini daripada sisa imej dan bekas yang tidak digunakan.


Petua Docker: Kosongkan mesin anda daripada sampah

Jumlah penggunaan

Docker adalah perkara yang menarik, mungkin hanya sedikit orang yang meraguinya hari ini. Hanya beberapa tahun yang lalu, produk ini memberi kami cara baharu sepenuhnya untuk membina, menyampaikan dan menjalankan sebarang persekitaran, membolehkan kami menjimatkan sumber CPU dan RAM dengan ketara. Sebagai tambahan kepada ini (dan bagi sesetengah orang ini akan menjadi perkara yang paling penting) Docker telah membenarkan kami untuk sangat memudahkan dan menyatukan pengurusan kitaran hayat persekitaran pengeluaran kami.

Walau bagaimanapun, semua keseronokan kehidupan moden ini ada pada harganya. Apabila kami menjalankan kontena, memuat turun atau mencipta imej kami sendiri dan menggunakan ekosistem yang kompleks, kami perlu membayar. Dan kami membayar, antara lain, dengan ruang cakera.

Jika anda tidak pernah memikirkan berapa banyak ruang yang digunakan oleh Docker pada mesin anda, anda mungkin terkejut dengan output arahan ini:

$ docker system df

Petua Docker: Kosongkan mesin anda daripada sampah

Ini menunjukkan penggunaan cakera Docker dalam konteks yang berbeza:

  • imej – jumlah saiz imej yang dimuat turun daripada repositori imej dan dibina pada sistem anda;
  • bekas – jumlah ruang cakera yang digunakan oleh bekas yang dijalankan (bermaksud jumlah volum lapisan baca-tulis semua bekas);
  • isipadu tempatan – isipadu storan tempatan yang dipasang pada bekas;
  • bina cache – fail sementara yang dijana oleh proses pembinaan imej (menggunakan alat BuildKit, tersedia bermula dengan versi Docker 18.09).

Saya yakin bahawa selepas pemindahan mudah ini anda tidak sabar-sabar untuk membersihkan cakera anda daripada sampah dan menghidupkan semula gigabait berharga (nota: terutamanya jika anda membayar sewa untuk gigabait ini setiap bulan).

Penggunaan cakera oleh bekas

Setiap kali anda mencipta bekas pada mesin hos, beberapa fail dan direktori dibuat dalam direktori /var/lib/docker, antaranya perkara berikut perlu diberi perhatian:

  • Direktori /var/lib/docker/containers/container_ID – apabila menggunakan pemacu pengelogan standard, di sinilah log peristiwa disimpan dalam format JSON. Log yang terlalu terperinci, serta log yang tidak dibaca atau diproses oleh sesiapa pun, selalunya menyebabkan cakera menjadi penuh.
  • Direktori /var/lib/docker/overlay2 mengandungi lapisan baca-tulis bekas (overlay2 ialah pemacu pilihan dalam kebanyakan pengedaran Linux). Jika kontena menyimpan data dalam sistem failnya, maka dalam direktori ini ia akan diletakkan.

Mari bayangkan sistem di mana Docker murni dipasang, yang tidak pernah terlibat dalam melancarkan kontena atau membina imej. Laporan penggunaan ruang cakeranya akan kelihatan seperti ini:

$ 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

Mari kita lancarkan beberapa bekas, sebagai contoh, NGINX:

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

Apa yang berlaku kepada cakera:

  • imej menduduki 126 MB, ini adalah NGINX yang sama yang kami lancarkan dalam bekas;
  • bekas mengambil 2 bait yang tidak masuk akal.

$ 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

Berdasarkan kesimpulannya, kami belum mempunyai sebarang ruang yang boleh kami kosongkan. Memandangkan 2 bait adalah remeh sama sekali, mari bayangkan NGINX kami secara tidak dijangka menulis 100 Megabait data di suatu tempat dan mencipta ujian fail.img dengan saiz ini di dalam dirinya sendiri.

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

Mari kita periksa penggunaan ruang cakera pada hos sekali lagi. Kita akan melihat bahawa kontena (bekas) menduduki 100 Megabait di sana.

$ 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

Saya rasa otak anda yang ingin tahu sudah tertanya-tanya di mana letak fail test.img kami. Jom cari:

$ 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

Tanpa pergi ke butiran, kita boleh ambil perhatian bahawa fail test.img terletak dengan mudah pada tahap baca-tulis, dikawal oleh pemacu tindanan2. Jika kami menghentikan bekas kami, hos akan memberitahu kami bahawa ruang ini, pada dasarnya, boleh dikosongkan:

# 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

Bagaimana kita boleh melakukan ini? Dengan memadamkan bekas, yang memerlukan mengosongkan ruang yang sepadan pada tahap baca-tulis.

Dengan arahan berikut, anda boleh mengalih keluar semua bekas yang dipasang dalam satu masa dan mengosongkan cakera anda daripada semua fail baca-tulis yang dibuat oleh mereka:

$ 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

Jadi, kami membebaskan 104,9 Megabait dengan memadamkan bekas. Tetapi memandangkan kami tidak lagi menggunakan imej yang dimuat turun sebelum ini, ia juga menjadi calon untuk memadam dan membebaskan sumber kami:

$ 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: Selagi imej digunakan oleh sekurang-kurangnya satu bekas, anda tidak akan dapat menggunakan helah ini.

Subperintah prune yang kami gunakan di atas hanya mempunyai kesan pada bekas yang dihentikan. Jika kita mahu memadam bukan sahaja berhenti tetapi juga menjalankan bekas, kita harus menggunakan salah satu daripada arahan ini:

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

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

Nota sampingan: jika anda menggunakan parameter -rm semasa memulakan bekas, maka apabila ia berhenti, semua ruang cakera yang didudukinya akan dibebaskan.

Menggunakan imej cakera

Beberapa tahun yang lalu, saiz imej beberapa ratus megabait adalah normal sepenuhnya: imej Ubuntu seberat 600 megabait, dan imej Microsoft .Net seberat beberapa gigabait. Pada hari-hari kelam itu, memuat turun hanya satu imej boleh mengambil tol besar pada ruang cakera kosong anda, walaupun anda berkongsi tahap antara imej. Hari ini - pujian kepada yang hebat - imej lebih ringan, tetapi walaupun begitu, anda boleh mengisi sumber yang ada dengan cepat jika anda tidak mengambil beberapa langkah berjaga-jaga.

Terdapat beberapa jenis imej yang tidak dapat dilihat secara langsung kepada pengguna akhir:

  • imej perantaraan, berdasarkan imej lain dikumpulkan - ia tidak boleh dipadamkan jika anda menggunakan bekas berdasarkan imej "lain" ini;
  • imej berjuntai ialah imej perantaraan yang tidak dirujuk oleh mana-mana bekas yang sedang berjalan - ia boleh dipadamkan.
  • Dengan arahan berikut anda boleh menyemak imej berjuntai pada sistem anda:

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

Anda boleh mengeluarkannya dengan cara berikut:

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

Kita juga boleh menggunakan subperintah 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

Jika kita tiba-tiba mahu memadamkan semua imej sama sekali (dan bukan hanya tergantung) dengan satu arahan, maka kita boleh melakukan ini:

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

Penggunaan cakera mengikut volum

Jilid digunakan untuk menyimpan data di luar sistem fail bekas. Sebagai contoh, jika kita ingin menyimpan hasil aplikasi untuk menggunakannya dalam beberapa cara lain. Contoh biasa ialah pangkalan data.

Mari lancarkan bekas MongoDB, lekapkan volum di luar bekas itu dan pulihkan sandaran pangkalan data daripadanya (kami menyediakannya dalam fail 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 akan ditempatkan pada mesin hos dalam direktori /var/lib/docker/volumes. Tetapi mengapa tidak pada tahap baca-tulis bekas? Kerana dalam Dockerfile imej MongoDB, direktori /data/db (di mana MongoDB menyimpan datanya secara lalai) ditakrifkan sebagai volum.

Petua Docker: Kosongkan mesin anda daripada sampah

Nota sampingan: banyak imej yang mesti menghasilkan data menggunakan volum untuk menyimpan data tersebut.

Apabila kita bermain cukup dengan MongoDB dan menghentikan (atau mungkin juga memadam) bekas, kelantangan tidak akan dipadamkan. Ia akan terus mengambil ruang cakera berharga kami sehingga kami memadamkannya secara eksplisit dengan arahan seperti ini:

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

Nah, atau kita boleh menggunakan subperintah prune yang sudah biasa kepada kita:

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

Menggunakan cakera untuk cache binaan imej

Dalam Docker 18.09, proses penciptaan imej telah mengalami beberapa perubahan terima kasih kepada alat BuildKit. Perkara ini meningkatkan kelajuan proses dan mengoptimumkan penyimpanan data dan pengurusan keselamatan. Di sini kami tidak akan mempertimbangkan semua butiran alat hebat ini; kami hanya akan menumpukan pada cara ia menangani isu penggunaan ruang cakera.

Katakan kita mempunyai aplikasi Node.Js yang sangat mudah:

  • fail index.js memulakan pelayan HTTP mudah yang bertindak balas dengan baris kepada setiap permintaan yang diterima:
  • fail package.json mentakrifkan kebergantungan, yang mana hanya expressjs digunakan untuk menjalankan pelayan 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"
      }
    }

Fail Docker untuk membina imej kelihatan seperti ini:

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

Mari bina imej dengan cara biasa, tanpa menggunakan BuildKit:

$ docker build -t app:1.0 .

Jika kita menyemak penggunaan ruang cakera, kita dapat melihat bahawa hanya imej asas (nod:13-alpine) dan imej destinasi (app:1.0) yang menggunakan ruang:

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

Mari bina versi kedua aplikasi kami, menggunakan BuildKit. Untuk melakukan ini, kita hanya perlu menetapkan pembolehubah DOCKER_BUILDKIT kepada 1:

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

Jika sekarang kita menyemak penggunaan cakera, kita akan melihat bahawa binaan cache (buid-cache) kini terlibat di sana:

$ 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

Untuk mengosongkannya, gunakan arahan berikut:

$ 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

Kosongkan semua!

Jadi, kami melihat pada pembersihan ruang cakera yang diduduki oleh bekas, imej dan volum. Subperintah prune membantu kami dalam hal ini. Tetapi ia juga boleh digunakan di peringkat sistem docker, dan ia akan membersihkan semua yang boleh:

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

Jika atas sebab tertentu anda menjimatkan ruang cakera pada mesin yang menjalankan Docker, maka secara berkala menjalankan arahan ini harus menjadi kebiasaan.

Sumber: www.habr.com

Tambah komen