Ukuran image yang membengkak selalu dapat dilacak sampai ke instruksi pembentuknya. Topik ini membahas cara membaca ukuran total pada docker images, membedah kontribusi tiap layer, lapisan penyusun image, dengan docker history, lalu mendiagnosis image yang membengkak hingga instruksi penyebabnya ditemukan. Satu pengukuran juga diperagakan secara nyata melalui API Docker Hub dengan curl, sehingga beda antara ukuran terkompresi dan ukuran terbongkar dapat dilihat langsung tanpa Docker.
Ukuran total pada docker images#
Perintah docker images menampilkan seluruh image yang tersimpan di host, komputer tempat Docker berjalan, beserta kolom SIZE yang berisi jumlah ukuran seluruh layer penyusunnya. Angka pada kolom itu bersifat logis, yaitu ukuran image sebagaimana dihitung dari penjumlahan layer, dan bukan ruang disk yang benar-benar dipakainya. Layer yang isinya sama disimpan sekali saja dan dibagi antar image, sehingga dua image berbasis yang sama tidak menduplikasi layer dasarnya di disk. Alur pull, proses menarik image dari registry ke host, mewarisi sifat itu karena layer yang sudah tersimpan tidak diunduh ulang saat penarikan berlangsung.
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# kolom SIZE menampilkan jumlah ukuran seluruh layer image
docker imagesKeluaran perintah tersebut berbentuk tabel dengan kolom REPOSITORY, TAG, IMAGE ID, CREATED, dan SIZE. Dua baris dengan repository sama tetapi tag berbeda biasanya menampilkan SIZE yang mirip, karena keduanya berbagi sebagian besar layer dan hanya berbeda pada layer pembedanya. Untuk ruang disk yang sesungguhnya, perintah docker system df merangkum total image, container, instans yang berjalan di atas image, dan cache build beserta berapa yang dapat dipulihkan. Angka SIZE inilah titik awal setiap audit ukuran, sedangkan penyebabnya dicari dengan cara berikut.
Kontribusi tiap layer pada docker history#
Perintah docker history <image> membedah ukuran image sampai ke sumbernya, yaitu instruksi Dockerfile yang membentuk setiap layer. Setiap baris keluarannya memuat satu layer dengan kolom CREATED, CREATED BY, SIZE, dan COMMENT, diurutkan dari layer terbaru di atas hingga layer image dasar di bawah. Kolom CREATED BY memuat instruksi pembentuknya, misalnya COPY app.py . atau RUN /bin/sh -c ..., dan sering terpotong karena panjang, sehingga opsi --no-trunc diperlukan untuk membacanya utuh.
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# tiap baris memuat satu layer beserta instruksi pembentuknya
docker history aplikasi-catatanCara membacanya untuk keperluan diagnosis sederhana, yaitu mengurutkan baris menurut kolom SIZE dari yang terbesar. Opsi --format membuat pengurutan itu mudah dilakukan karena ukuran dan instruksinya dapat dipipakan ke sort. Pengurutan semacam ini hanya membaca metadata layer, sehingga tidak mengubah image sama sekali.
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# instruksi diurutkan dari kontribusi ukuran terbesar
docker history aplikasi-catatan --format "{{.Size}}\t{{.CreatedBy}}" | sort -hrPada image aplikasi yang membengkak, baris teratas hasil pengurutan tersebut umumnya diisi oleh dua jenis instruksi. Pertama, RUN apt-get yang memasang paket tanpa pembersihan, karena daftar paket dan cache yang diunduh terkunci permanen di layernya. Kedua, COPY yang menyalin direktori besar, misalnya direktori berisi hasil build atau berkas data yang ikut tersalin. Setelah instruksi penyumbang terbesar ditemukan, perbaikannya dikerjakan pada Dockerfile, bukan pada image yang sudah jadi.
Ukuran terkompresi pada Docker Hub#
Angka pada docker images bukan angka yang melintasi jaringan. Registry menyimpan layer dalam bentuk terkompresi, sehingga yang diunduh saat pull adalah byte terkompresi, sedangkan daemon, layanan latar yang mengeksekusi pekerjaan Docker, membongkarnya sebelum menyimpannya di host. docker images menampilkan ukuran terbongkar, sementara API Docker Hub melaporkan ukuran terkompresi, dan keduanya hanya boleh dibandingkan dengan pasangannya masing-masing.
| Ukuran | Sumber angka | Isinya |
|---|---|---|
| Terkompresi | API Docker Hub | byte layer terkompresi yang diunduh dari registry |
| Terbongkar | kolom SIZE pada docker images | byte layer setelah didekompresi di host |
Ukuran terkompresi itu dapat diambil secara nyata tanpa Docker sama sekali, yaitu melalui API Docker Hub dengan curl. Perintah berikut membaca properti full_size, total ukuran terkompresi suatu tag, lalu mengubahnya menjadi megabyte.
curl -s "https://hub.docker.com/v2/repositories/library/python/tags/3.12-slim" \
| python3 -c "import json,sys; data=json.load(sys.stdin); print('python:3.12-slim :', round(data['full_size']/1000000, 1), 'MB')"
curl -s "https://hub.docker.com/v2/repositories/library/alpine/tags/3.20" \
| python3 -c "import json,sys; data=json.load(sys.stdin); print('alpine:3.20 :', round(data['full_size']/1000000, 1), 'MB')"python:3.12-slim : 43.3 MB
alpine:3.20 : 3.6 MBUkuran terkompresi python:3.12-slim sekitar dua belas kali ukuran alpine:3.20, dan itulah perkiraan beban jaringan saat keduanya ditarik untuk pertama kalinya pada host yang masih kosong. Angka-angka di atas adalah cuplikan pada saat topik ini ditulis, karena nilai pada API berpindah setiap tag dibangun ulang. Setelah layer terbongkar di host, ukurannya pada docker images akan lebih besar daripada angka terkompresi ini.
Kesalahan umum#
- Membaca SIZE pada
docker imagessebagai ruang disk yang dipakai. Layer yang dibagi antar image disimpan sekali saja, sehingga jumlah SIZE seluruh image melebihi pemakaian disk nyata. Perbaikannya, gunakandocker system dfuntuk angka disk dan SIZE untuk ukuran logis per image. - Membandingkan angka terkompresi Docker Hub dengan SIZE
docker imagessecara langsung. Yang satu terkompresi dan yang lain terbongkar, sehingga selisihnya besar dan menyesatkan. Perbaikannya, bandingkan angka yang sejenis, misalnya ukuran terkompresi dengan ukuran terkompresi. - Menduga image dasar sebagai penyumbang ukuran terbesar tanpa mengukur lebih dahulu. Image dasar memang besar, tetapi pemasangan paket dan penyalinan direktori sering melampauinya. Perbaikannya, urutkan
docker historymenurut SIZE sebelum memutuskan apa yang dioptimasi.
Ringkasan#
- Kolom SIZE pada
docker imagesadalah ukuran logis gabungan seluruh layer, sedangkan layer yang dibagi antar image disimpan sekali dan tidak diunduh ulang saat pull. docker historymemetakan setiap instruksi Dockerfile ke kontribusi ukurannya, dan pengurutan menurut SIZE menunjukkan instruksi penyumbang terbesar.RUN apt-gettanpa pembersihan danCOPYdirektori besar adalah penyebab pembengkakan yang paling sering ditemukan.- Ukuran terkompresi pada API Docker Hub mewakili beban unduhan, sedangkan
docker imagesmenampilkan ukuran terbongkar di host.
Referensi#
- docker image history — Docker Docs
— Mendokumentasikan kolom keluaran, opsi
--format, dan opsi--no-truncpada docker history. - Building best practices — Docker Docs — Menyarankan pembersihan cache dalam instruksi yang sama dan image sekecil mungkin.