Ada berbagai teknik yang terlibat, tanpa solusi tunggal. Anda mungkin ingin melakukan beberapa hal berikut:
Pertama, optimalkan layer gambar Anda untuk digunakan kembali. Masukkan langkah-langkah yang sering diubah kemudian di Dockerfile untuk meningkatkan kemungkinan bahwa lapisan awal di-cache dari build sebelumnya. Lapisan yang digunakan kembali akan muncul sebagai lebih banyak ruang disk dalam docker image ls
, tetapi jika Anda memeriksa sistem file yang mendasarinya, hanya satu salinan dari setiap lapisan yang pernah disimpan pada disk. Itu berarti 3 gambar masing-masing 2 GB, tetapi yang hanya memiliki 50 MB berbeda dalam beberapa lapisan terakhir pembangunan, hanya akan memakan ruang disk 2,1 GB, meskipun daftar membuatnya tampak bahwa mereka menggunakan 6 GB karena Anda menghitung ganda masing-masing lapisan yang digunakan kembali.
Penggunaan kembali lapisan adalah mengapa Anda melihat gambar dengan dependensi build yang jarang berubah, instal terlebih dahulu sebelum menyalin kode. Lihat contoh python yang memiliki pola seperti:
FROM python
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# note how the code is copied only after the pip install
# since code changes but requirements.txt doesn't
COPY . .
CMD ["gunicorn", "app:app"]
Pilih gambar dasar minimal. Inilah sebabnya mengapa Anda melihat orang-orang pergi dari ubuntu
ke debian:slim
(varian slim lebih kecil, pengiriman dengan alat yang lebih sedikit), atau bahkan alpine
. Ini mengurangi ukuran titik awal Anda, dan sangat membantu jika Anda terus-menerus menarik versi baru gambar dasar. Namun, jika gambar dasar Anda jarang berubah, penggunaan kembali lapisan menghilangkan banyak keuntungan dari gambar dasar minimal.
Gambar dasar terkecil yang dapat Anda pilih adalah scratch
, yang bukan apa-apa, tidak ada shell atau pustaka, dan hanya berguna untuk binari yang dikompilasi secara statis. Jika tidak, pilih gambar dasar yang mencakup alat yang Anda butuhkan tanpa banyak alat yang tidak Anda butuhkan.
Selanjutnya, setiap langkah yang mengubah atau menghapus file harus dikombinasikan dengan langkah-langkah sebelumnya yang membuat file itu. Kalau tidak, sistem file berlapis, yang menggunakan copy-on-write bahkan pada hal-hal seperti perubahan izin file, akan memiliki file asli di lapisan sebelumnya dan ukuran gambar tidak akan menyusut ketika Anda menghapus file. Inilah sebabnya mengapa rm
perintah Anda tidak berpengaruh pada ruang disk yang dihasilkan. Sebagai gantinya, Anda dapat membuat rantai perintah, seperti:
RUN apt-get update \
&& apt-get install -y \
a-package \
wget \
&& ... \
&& apt-get purge -y wget \
&& rm -r a-build-dir \
&& apt-get purge -y a-package
Perhatikan bahwa penggunaan perintah yang berlebihan dapat memperlambat build Anda karena Anda perlu menginstal ulang toolset yang sama setiap kali prasyarat berubah (misalnya kode ditarik dengan wget). Lihat multi-tahap di bawah ini untuk alternatif yang lebih baik.
File apa pun yang Anda buat yang tidak Anda butuhkan dalam gambar yang dihasilkan harus dihapus, pada langkah yang membuatnya. Ini termasuk cache paket, log, halaman manual, dll. Untuk menemukan file apa yang sedang dibuat di setiap layer, Anda dapat menggunakan alat seperti wagoodman / dive (yang saya belum diperiksa secara pribadi dan akan menyatakan kehati-hatian karena dijalankan dengan akses root penuh) pada host Anda), atau Anda dapat membuat gambar buruh pelabuhan tanpa memangkas wadah perantara dan kemudian melihat diff dengan:
# first create and leave containers from any RUN step using options on build
docker image build --rm=false --no-cache -t image_name .
# review which layers use an unexpectedly large amount of space
docker image history image_name
# list all containers, particularly the exited ones from above
docker container ps -a
# examine any of those containers
docker container diff ${container_id}
# ... repeat the diff for other build steps
# then cleanup exited containers
docker container prune
Dengan masing-masing kontainer menengah, diff akan menunjukkan file apa yang ditambahkan, diubah, atau dihapus pada langkah yang (ini ditunjukkan dengan A
, C
atau D
sebelum setiap nama file). Perbedaan yang diperlihatkan adalah sistem file baca / tulis khusus kontainer, yang merupakan file apa pun yang diubah oleh wadah dari status gambar menggunakan copy-on-write.
Cara terbaik untuk mengurangi ukuran gambar adalah menghilangkan komponen yang tidak dibutuhkan, seperti kompiler, dari gambar yang Anda kirim. Untuk itu, multi-stage build memungkinkan Anda mengkompilasi dalam satu tahap, dan kemudian hanya menyalin artefak yang dihasilkan dari tahap build ke gambar runtime yang hanya memiliki minimum yang diperlukan untuk menjalankan aplikasi. Ini menghindari perlunya mengoptimalkan langkah-langkah pembangunan karena tidak dikirimkan dengan gambar yang dihasilkan.
FROM debian:9 as build
# still chain update with install to prevent stale cache issues
RUN apt-get update \
&& apt-get install -y \
a-package \
wget \
RUN ... # perform any download/compile steps
FROM debian:9-slim as release
COPY --from=build /usr/local/bin/app /usr/local/bin/app
CMD [ "/usr/local/bin/app" ]
Multi-stage sangat ideal dengan binari yang dikompilasi secara statis yang dapat Anda jalankan dengan awal sebagai gambar dasar Anda, atau beralih dari lingkungan kompilasi seperti JDK ke runtime seperti JRE. Ini adalah cara termudah untuk secara dramatis mengurangi ukuran gambar Anda sambil tetap membuat cepat. Anda masih dapat melakukan chaining langkah-langkah di tahap rilis Anda jika Anda memiliki langkah-langkah yang mengubah atau menghapus file yang dibuat di langkah-langkah sebelumnya, tetapi untuk sebagian besar, COPY
tahap dari mengisolasi tahap rilis dari semua lapisan mengasapi berpengalaman dalam tahap membangun sebelumnya.
Catatan, saya tidak merekomendasikan memencet gambar karena ini mengurangi ukuran satu gambar dengan mengorbankan menghilangkan penggunaan kembali lapisan. Itu berarti membangun di masa depan dari gambar yang sama akan memerlukan lebih banyak disk dan lalu lintas jaringan untuk mengirim pembaruan. Untuk kembali ke contoh pertama, squashing dapat mengurangi gambar Anda dari 2 GB menjadi 1 GB, tetapi tidak 3 gambar mungkin memakan 3 GB daripada 2.1 GB.
2.37
vs.1.47 GB