Tip Docker: Bersihkan mesin Anda dari sampah

Tip Docker: Bersihkan mesin Anda dari sampah

Hei Habr! Untuk perhatian Anda, saya persembahkan terjemahan artikel tersebut "Tips Docker: Bersihkan Mesin Lokal Anda" penulis Luc Juggery.

Hari ini kita akan berbicara tentang bagaimana Docker menggunakan ruang disk mesin host, dan kita juga akan mencari cara untuk mengosongkan ruang ini dari sisa-sisa gambar dan wadah yang tidak digunakan.


Tip Docker: Bersihkan mesin Anda dari sampah

Jumlah konsumsi

Docker adalah hal yang keren, mungkin hanya sedikit orang yang meragukannya saat ini. Beberapa tahun yang lalu, produk ini memberi kami cara baru untuk membangun, menghadirkan, dan menjalankan lingkungan apa pun, sehingga memungkinkan kami menghemat sumber daya CPU dan RAM secara signifikan. Selain itu (dan bagi sebagian orang ini akan menjadi hal yang paling penting), Docker telah memungkinkan kami menyederhanakan dan menyatukan manajemen siklus hidup lingkungan produksi yang kami gunakan.

Namun, semua kesenangan hidup modern ini ada harganya. Saat kami menjalankan container, mengunduh atau membuat gambar kami sendiri, dan menerapkan ekosistem yang kompleks, kami harus membayar. Dan kami membayar, antara lain, dengan ruang disk.

Jika Anda belum pernah memikirkan berapa banyak ruang yang sebenarnya digunakan Docker di mesin Anda, Anda mungkin akan terkejut dengan keluaran perintah ini:

$ docker system df

Tip Docker: Bersihkan mesin Anda dari sampah

Ini menunjukkan penggunaan disk Docker dalam konteks berbeda:

  • gambar – ukuran total gambar yang diunduh dari repositori gambar dan dibangun di sistem Anda;
  • container – jumlah total ruang disk yang digunakan oleh container yang sedang berjalan (berarti total volume lapisan baca-tulis semua container);
  • volume lokal – volume penyimpanan lokal yang dipasang pada kontainer;
  • build cache – file sementara yang dihasilkan oleh proses pembuatan image (menggunakan alat BuildKit, tersedia mulai Docker versi 18.09).

Saya yakin setelah transfer sederhana ini Anda ingin sekali membersihkan disk Anda dari sampah dan menghidupkan kembali gigabyte yang berharga (catatan: terutama jika Anda membayar sewa untuk gigabyte tersebut setiap bulan).

Penggunaan disk berdasarkan kontainer

Setiap kali Anda membuat container di mesin host, beberapa file dan direktori dibuat di direktori /var/lib/docker, di antaranya yang perlu diperhatikan adalah:

  • Direktori /var/lib/docker/containers/container_ID – saat menggunakan driver logging standar, di sinilah log peristiwa disimpan dalam format JSON. Log yang terlalu detail, serta log yang tidak dibaca atau diproses oleh siapa pun, sering kali menyebabkan disk menjadi penuh.
  • Direktori /var/lib/docker/overlay2 berisi lapisan container read-write (overlay2 adalah driver pilihan di sebagian besar distribusi Linux). Jika container menyimpan data dalam sistem filenya, maka di direktori inilah data tersebut akan ditempatkan.

Mari kita bayangkan sebuah sistem di mana Docker asli diinstal, yang tidak pernah terlibat dalam peluncuran container atau pembuatan image. Laporan penggunaan ruang disknya akan terlihat 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 luncurkan beberapa container, misalnya NGINX:

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

Apa yang terjadi pada disk:

  • gambar menempati 126 MB, ini adalah NGINX yang sama yang kami luncurkan di dalam container;
  • kontainer memakan 2 byte yang konyol.

$ 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

Dilihat dari kesimpulannya, kami belum memiliki ruang yang dapat dikosongkan. Karena 2 byte benar-benar remeh, bayangkan NGINX kita secara tak terduga menulis data sebesar 100 Megabyte dan membuat file test.img dengan ukuran persis seperti ini di dalamnya.

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

Mari kita periksa kembali penggunaan ruang disk pada host. Kita akan melihat bahwa container (wadah) menempati 100 Megabyte 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 pikir otak Anda yang ingin tahu sudah bertanya-tanya di mana file test.img kami berada. Mari kita mencarinya:

$ 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 merinci lebih lanjut, kita dapat mencatat bahwa file test.img berlokasi di tingkat baca-tulis, dikendalikan oleh driver overlay2. Jika kami menghentikan wadah kami, tuan rumah akan memberi tahu kami bahwa ruang ini, pada prinsipnya, dapat 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 bisa melakukan ini? Dengan menghapus wadah, yang berarti mengosongkan ruang yang sesuai di tingkat baca-tulis.

Dengan perintah berikut, Anda dapat menghapus semua container yang terpasang dalam satu gerakan dan membersihkan disk Anda dari semua file baca-tulis yang dibuat oleh container tersebut:

$ 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 mengosongkan 104,9 Megabyte dengan menghapus containernya. Namun karena kami tidak lagi menggunakan gambar yang diunduh sebelumnya, gambar tersebut juga menjadi kandidat untuk menghapus dan mengosongkan sumber daya 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

Catatan: Selama gambar tersebut digunakan oleh setidaknya satu wadah, Anda tidak akan dapat menggunakan trik ini.

Sub-perintah prune yang kita gunakan di atas hanya berpengaruh pada container yang dihentikan. Jika kita ingin menghapus tidak hanya container yang dihentikan tetapi juga container yang sedang berjalan, kita harus menggunakan salah satu perintah berikut:

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

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

Catatan tambahan: jika Anda menggunakan parameter -rm saat memulai sebuah wadah, maka ketika wadah itu berhenti, semua ruang disk yang ditempati akan kosong.

Menggunakan gambar disk

Beberapa tahun yang lalu, ukuran gambar beberapa ratus megabyte adalah hal yang normal: gambar Ubuntu berbobot 600 megabyte, dan gambar Microsoft .Net berbobot beberapa gigabyte. Di masa-masa sulit itu, mengunduh hanya satu gambar dapat menghabiskan banyak ruang disk kosong, bahkan jika Anda berbagi level antar gambar. Saat ini - puji bagi yang agung - gambar berbobot jauh lebih ringan, namun demikian, Anda dapat dengan cepat mengisi sumber daya yang tersedia jika Anda tidak mengambil tindakan pencegahan.

Ada beberapa jenis gambar yang tidak terlihat langsung oleh pengguna akhir:

  • gambar perantara, yang menjadi dasar pengumpulan gambar lain - gambar tersebut tidak dapat dihapus jika Anda menggunakan wadah berdasarkan gambar "lainnya" ini;
  • gambar yang menjuntai adalah gambar perantara yang tidak direferensikan oleh container mana pun yang sedang berjalan - gambar tersebut dapat dihapus.
  • Dengan perintah berikut Anda dapat memeriksa gambar yang menggantung di sistem Anda:

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

Anda dapat menghapusnya dengan cara berikut:

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

Kita juga dapat 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 ingin menghapus semua gambar sekaligus (dan tidak hanya menggantung) dengan satu perintah, kita bisa melakukan ini:

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

Penggunaan disk berdasarkan volume

Volume digunakan untuk menyimpan data di luar sistem file kontainer. Misalnya, jika kita ingin menyimpan hasil suatu aplikasi untuk digunakan dengan cara lain. Contoh umum adalah database.

Mari kita luncurkan container MongoDB, pasang volume eksternal ke container, dan pulihkan cadangan database dari container tersebut (kami menyediakannya di file 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 di mesin host di direktori /var/lib/docker/volumes. Tetapi mengapa tidak pada tingkat baca-tulis wadahnya? Karena di Dockerfile gambar MongoDB, direktori /data/db (tempat MongoDB menyimpan datanya secara default) didefinisikan sebagai volume.

Tip Docker: Bersihkan mesin Anda dari sampah

Catatan tambahan: banyak gambar yang harus menghasilkan data menggunakan volume untuk menyimpan data tersebut.

Ketika kita cukup bermain-main dengan MongoDB dan menghentikan (atau bahkan menghapus) container, volumenya tidak akan terhapus. Ini akan terus menghabiskan ruang disk kami yang berharga sampai kami menghapusnya secara eksplisit dengan perintah seperti ini:

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

Nah, atau kita bisa menggunakan subperintah prune yang sudah tidak asing lagi bagi 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 disk untuk cache pembuatan gambar

Di Docker 18.09, proses pembuatan image telah mengalami beberapa perubahan berkat alat BuildKit. Hal ini meningkatkan kecepatan proses dan mengoptimalkan penyimpanan data dan manajemen keamanan. Di sini kami tidak akan mempertimbangkan semua detail dari alat luar biasa ini; kami hanya akan fokus pada bagaimana alat ini mengatasi masalah penggunaan ruang disk.

Katakanlah kita memiliki aplikasi Node.Js yang sangat sederhana:

  • file index.js memulai server HTTP sederhana yang merespons dengan satu baris untuk setiap permintaan yang diterima:
  • file package.json mendefinisikan dependensi, yang mana hanya expressjs yang digunakan untuk menjalankan server 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"
      }
    }

Dockerfile untuk membuat image terlihat 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 buat gambar dengan cara biasa, tanpa menggunakan BuildKit:

$ docker build -t app:1.0 .

Jika kita memeriksa penggunaan ruang disk, kita dapat melihat bahwa hanya gambar dasar (node:13-alpine) dan gambar tujuan (aplikasi: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 buat versi kedua aplikasi kita, menggunakan BuildKit. Untuk melakukan ini, kita hanya perlu mengatur variabel DOCKER_BUILDKIT ke 1:

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

Jika sekarang kita memeriksa penggunaan disk, kita akan melihat bahwa build cache (buid-cache) sekarang 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 menghapusnya, gunakan perintah 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

Bersihkan semua!

Jadi, kami melihat cara membersihkan ruang disk yang ditempati oleh container, gambar, dan volume. Sub-perintah prune membantu kita dalam hal ini. Tapi itu juga bisa digunakan di tingkat sistem buruh pelabuhan, dan itu akan membersihkan semua yang bisa dilakukannya:

$ 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 karena alasan tertentu Anda menghemat ruang disk pada mesin yang menjalankan Docker, menjalankan perintah ini secara berkala harus menjadi kebiasaan.

Sumber: www.habr.com

Tambah komentar