Docker İpuçları: Makinenizi gereksiz öğelerden temizleyin

Docker İpuçları: Makinenizi gereksiz öğelerden temizleyin

Ey Habr! Makalenin çevirisini dikkatinize sunuyorum. "Docker İpuçları: Yerel Makinenizi Temizleyin" yazar Luc Juggery.

Bugün Docker'ın ana makinenin disk alanını nasıl kullandığından bahsedeceğiz ve ayrıca bu alanı kullanılmayan görüntü ve konteyner artıklarından nasıl kurtaracağımızı da bulacağız.


Docker İpuçları: Makinenizi gereksiz öğelerden temizleyin

Toplam kullanım

Docker harika bir şey, muhtemelen bugün çok az kişi bundan şüphe ediyor. Sadece birkaç yıl önce bu ürün bize herhangi bir ortamı oluşturmanın, sunmanın ve çalıştırmanın tamamen yeni bir yolunu sunarak CPU ve RAM kaynaklarından önemli ölçüde tasarruf etmemize olanak tanıdı. Buna ek olarak (bazıları için en önemli şey bu olacaktır) Docker, üretim ortamlarımızın yaşam döngüsü yönetimini inanılmaz derecede basitleştirmemize ve birleştirmemize olanak tanıdı.

Ancak modern yaşamın tüm bu zevklerinin bir bedeli var. Container'ları çalıştırdığımızda, kendi görüntülerimizi indirdiğimizde veya oluşturduğumuzda ve karmaşık ekosistemleri dağıttığımızda ödeme yapmak zorundayız. Ve diğer şeylerin yanı sıra disk alanıyla da ödeme yapıyoruz.

Docker'ın makinenizde gerçekte ne kadar yer kapladığını hiç düşünmediyseniz, bu komutun çıktısı sizi hoş olmayan bir şekilde şaşırtabilir:

$ docker system df

Docker İpuçları: Makinenizi gereksiz öğelerden temizleyin

Bu, Docker'ın farklı bağlamlardaki disk kullanımını gösterir:

  • resimler – resim havuzlarından indirilen ve sisteminizde oluşturulan resimlerin toplam boyutu;
  • kapsayıcılar – çalıştırılan kapsayıcılar tarafından kullanılan toplam disk alanı miktarı (tüm kapsayıcıların okuma-yazma katmanlarının toplam hacmi anlamına gelir);
  • yerel hacimler – konteynerlere monte edilen yerel depolamanın hacmi;
  • derleme önbelleği - görüntü oluşturma işlemi tarafından oluşturulan geçici dosyalar (Docker sürüm 18.09'dan itibaren kullanılabilen BuildKit aracı kullanılarak).

Bahse girerim ki, bu basit transferden sonra diskinizi çöpten temizlemeye ve değerli gigabaytları yeniden hayata döndürmeye heveslisiniz (not: özellikle bu gigabaytlar için her ay kira ödüyorsanız).

Kapsayıcılara göre disk kullanımı

Ana makinede her konteyner oluşturduğunuzda, /var/lib/docker dizininde çeşitli dosyalar ve dizinler oluşturulur; bunların arasında aşağıdakiler dikkate değerdir:

  • Dizin /var/lib/docker/containers/container_ID – standart günlük sürücüsü kullanıldığında, olay günlükleri JSON formatında kaydedildiği yerdir. Çok ayrıntılı günlüklerin yanı sıra kimsenin okumadığı veya başka bir şekilde işlemediği günlükler sıklıkla disklerin dolmasına neden olur.
  • /var/lib/docker/overlay2 dizini kapsayıcı okuma-yazma katmanlarını içerir (overlay2 çoğu Linux dağıtımında tercih edilen sürücüdür). Kap, verileri dosya sisteminde saklıyorsa, bu dizine yerleştirilecektir.

Konteynerlerin başlatılmasında veya görüntülerin oluşturulmasında hiçbir zaman yer almamış, bozulmamış bir Docker'ın kurulu olduğu bir sistem hayal edelim. Disk alanı kullanım raporu şu şekilde görünecektir:

$ 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

NGINX gibi bir konteyner başlatalım:

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

Diske ne olur:

  • resimler 126 MB yer kaplıyor; bu, kapta başlattığımız NGINX'in aynısı;
  • kaplar gülünç bir 2 bayt kaplıyor.

$ 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

Sonuca bakılırsa henüz boşaltabileceğimiz bir alanımız yok. 2 bayt tamamen anlamsız olduğundan, NGINX'imizin beklenmedik bir şekilde 100 Megabaytlık bir yere veri yazdığını ve kendi içinde tam olarak bu boyutta bir test.img dosyası oluşturduğunu hayal edelim.

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

Host üzerindeki disk alanı kullanımını tekrar inceleyelim. Orada Container’ların (konteynerlerin) 100 Megabyte yer kapladığını göreceğiz.

$ 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

Sanırım meraklı beyniniz zaten test.img dosyamızın nerede olduğunu merak ediyor. Hadi arayalım:

$ 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

Detaylara girmeden test.img dosyasının overlay2 sürücüsü tarafından kontrol edilen okuma-yazma seviyesinde uygun bir şekilde konumlandırıldığını belirtebiliriz. Konteynerimizi durdurursak, sunucu bize bu alanın prensipte boşaltılabileceğini söyleyecektir:

# 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

Bunu nasıl yapabiliriz? Okuma-yazma düzeyinde ilgili alanın temizlenmesini gerektirecek olan kabı silerek.

Aşağıdaki komutla, kurulu tüm kapsayıcıları tek bir hamlede kaldırabilir ve diskinizi, bunlar tarafından oluşturulan tüm okuma-yazma dosyalarından temizleyebilirsiniz:

$ 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

Böylece konteyneri silerek 104,9 Megabayt yer açtık. Ancak daha önce indirdiğimiz görseli artık kullanmadığımız için aynı zamanda silinmeye ve kaynaklarımızın serbest bırakılmasına da aday oluyor:

$ 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

Not: Görüntü en az bir kapsayıcı tarafından kullanıldığı sürece bu numarayı kullanamazsınız.

Yukarıda kullandığımız Prune alt komutunun yalnızca durdurulan konteynerler üzerinde etkisi vardır. Yalnızca durdurulan değil, çalışan konteynerleri de silmek istiyorsak şu komutlardan birini kullanmalıyız:

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

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

Yan notlar: Bir kabı başlatırken -rm parametresini kullanırsanız, durduğunda kapladığı tüm disk alanı serbest bırakılır.

Disk görüntülerini kullanma

Birkaç yıl önce, birkaç yüz megabaytlık bir görüntü boyutu tamamen normaldi: Bir Ubuntu görüntüsü 600 megabayt ağırlığındaydı ve bir Microsoft .Net görüntüsü birkaç gigabayt ağırlığındaydı. O kötü günlerde, görüntüler arasında seviye paylaşıyor olsanız bile, tek bir görüntünün indirilmesi, boş disk alanınızda büyük bir maliyete neden olabiliyordu. Bugün -büyüklere şükürler olsun- görsellerin ağırlığı çok daha az, ancak yine de bazı önlemler almazsanız mevcut kaynakları hızla doldurabilirsiniz.

Son kullanıcının doğrudan göremediği çeşitli resim türleri vardır:

  • diğer görüntülerin toplandığı ara görüntüler - bu "diğer" görüntülere dayalı kaplar kullanırsanız silinemezler;
  • sarkan görüntüler, çalışan kapsayıcıların hiçbiri tarafından referans verilmeyen ara görüntülerdir; bunlar silinebilir.
  • Aşağıdaki komutla sisteminizde sarkan görüntüleri kontrol edebilirsiniz:

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

Bunları aşağıdaki şekilde kaldırabilirsiniz:

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

Prune alt komutunu da kullanabiliriz:

$ 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

Aniden tek bir komutla tüm görüntüleri (ve yalnızca sarkanları değil) tamamen silmek istersek, şunu yapabiliriz:

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

Birimlere göre disk kullanımı

Birimler, verileri kapsayıcının dosya sisteminin dışında depolamak için kullanılır. Örneğin, bir uygulamanın sonuçlarını başka bir şekilde kullanmak üzere kaydetmek istiyorsak. Yaygın bir örnek veritabanlarıdır.

Bir MongoDB konteyneri başlatalım, konteynerin dışında bir birim bağlayalım ve buradan bir veritabanı yedeğini geri yükleyelim (bck.json dosyasında mevcut):

# 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

Veriler ana makinede /var/lib/docker/volumes dizininde yer alacaktır. Peki neden kabın okuma-yazma seviyesinde olmasın? Çünkü MongoDB imajının Docker dosyasında /data/db dizini (MongoDB'nin varsayılan olarak verilerini sakladığı yer) birim olarak tanımlanmıştır.

Docker İpuçları: Makinenizi gereksiz öğelerden temizleyin

Yan not: Veri üretmesi gereken birçok görüntü, bu verileri depolamak için hacimler kullanır.

MongoDB ile yeterince oynadığımızda ve konteyneri durdurduğumuzda (veya hatta sildiğimizde), birim silinmeyecektir. Aşağıdaki gibi bir komutla açıkça silene kadar değerli disk alanımızı kaplamaya devam edecektir:

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

Veya zaten aşina olduğumuz Prune alt komutunu kullanabiliriz:

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

Görüntü oluşturma önbelleği için disk kullanma

Docker 18.09'da BuildKit aracı sayesinde imaj oluşturma süreci bazı değişikliklere uğradı. Bu şey sürecin hızını artırır ve veri depolama ve güvenlik yönetimini optimize eder. Burada bu harika aracın tüm ayrıntılarını ele almayacağız; yalnızca disk alanı kullanımı sorunlarını nasıl ele aldığına odaklanacağız.

Diyelim ki tamamen basit bir Node.Js uygulamamız var:

  • index.js dosyası, alınan her isteğe bir satırla yanıt veren basit bir HTTP sunucusunu başlatır:
  • package.json dosyası, HTTP sunucusunu çalıştırmak için yalnızca expressjs'nin kullanıldığı bağımlılıkları tanımlar:

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

Görüntüyü oluşturmaya yönelik Docker dosyası şuna benzer:

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

İmajı BuildKit kullanmadan her zamanki gibi oluşturalım:

$ docker build -t app:1.0 .

Disk alanı kullanımını kontrol edersek yalnızca temel imajın (node:13-alpine) ve hedef imajın (app:1.0) yer kapladığını görebiliriz:

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

BuildKit kullanarak uygulamamızın ikinci versiyonunu oluşturalım. Bunu yapmak için DOCKER_BUILDKIT değişkenini 1'e ayarlamamız yeterli:

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

Şimdi disk kullanımını kontrol edersek, derleme önbelleğinin (buid-cache) artık burada yer aldığını göreceğiz:

$ 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

Temizlemek için aşağıdaki komutu kullanın:

$ 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

Hepsini temizle!

Bu nedenle kapların, görüntülerin ve birimlerin kapladığı disk alanını temizlemeye baktık. Prune alt komutu bu konuda bize yardımcı olur. Ancak liman işçisi sistemi düzeyinde de kullanılabilir ve yapabileceği her şeyi temizleyecektir:

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

Herhangi bir nedenle Docker çalıştıran bir makinede disk alanından tasarruf ediyorsanız, bu komutu periyodik olarak çalıştırmak bir alışkanlık haline gelmelidir.

Kaynak: habr.com

Yorum ekle