Kami memiliki blok berikut di Dockerfile
:
RUN yum -y update
RUN yum -y install epel-release
RUN yum -y groupinstall "Development Tools"
RUN yum -y install python-pip git mysql-devel libxml2-devel libxslt-devel python-devel openldap-devel libffi-devel openssl-devel
Saya telah diberitahu bahwa kita harus menyatukan RUN
perintah - perintah ini untuk mengurangi lapisan buruh pelabuhan yang dibuat:
RUN yum -y update \
&& yum -y install epel-release \
&& yum -y groupinstall "Development Tools" \
&& yum -y install python-pip git mysql-devel libxml2-devel libxslt-devel python-devel openldap-devel libffi-devel openssl-devel
Saya sangat baru untuk buruh pelabuhan dan tidak yakin saya sepenuhnya memahami perbedaan antara dua versi ini menentukan beberapa perintah RUN. Kapan seseorang akan menyatukan RUN
perintah menjadi satu dan ketika masuk akal untuk memiliki beberapa RUN
perintah?
docker
dockerfile
alecxe
sumber
sumber
Jawaban:
Gambar buruh pelabuhan sebenarnya adalah daftar yang terhubung dari lapisan sistem file. Setiap instruksi dalam Dockerfile membuat lapisan filesystem yang menjelaskan perbedaan dalam filesystem sebelum dan sesudah eksekusi instruksi yang sesuai.
docker inspect
Sub - perintah ini dapat digunakan pada gambar buruh pelabuhan untuk mengungkapkan sifatnya sebagai daftar tautan dari lapisan sistem file.Jumlah lapisan yang digunakan dalam suatu gambar adalah penting
Ini memiliki beberapa konsekuensi untuk bagaimana gambar harus dibangun. Saran pertama dan paling penting yang bisa saya berikan adalah:
Alasan untuk ini, adalah bahwa semua langkah sebelumnya akan di-cache dan lapisan yang sesuai tidak perlu diunduh berulang kali. Ini berarti versi yang lebih cepat dan rilis yang lebih cepat, yang mungkin Anda inginkan. Cukup menarik, ternyata sulit untuk memanfaatkan cache buruh pelabuhan secara optimal.
Saran kedua saya kurang penting tetapi saya merasa sangat berguna dari sudut pandang pemeliharaan:
Sebuah Dockerfile mengikuti saran ini akan terlihat seperti
dan seterusnya. Saran mengikat beberapa perintah dengan
&&
hanya memiliki ruang lingkup terbatas. Jauh lebih mudah untuk menulis dengan skrip, di mana Anda dapat menggunakan fungsi, dll untuk menghindari redundansi atau untuk keperluan dokumentasi.Orang-orang tertarik dengan pra-prosesor dan bersedia menghindari overhead kecil yang disebabkan oleh
COPY
langkah - langkah dan benar-benar menghasilkan Dockerfile di manaurutan digantikan oleh
di mana
…
adalah versi base64-encoded dariapt_setup.sh
.Saran ketiga saya adalah untuk orang-orang yang ingin membatasi ukuran dan jumlah lapisan dengan biaya pembuatan yang lebih lama.
File yang ditambahkan oleh beberapa instruksi buruh pelabuhan dan dihapus oleh beberapa instruksi kemudian tidak ada dalam sistem berkas yang dihasilkan tetapi disebutkan dua kali dalam lapisan buruh pelabuhan yang merupakan gambar buruh pelabuhan dalam konstruksi. Sekali, dengan nama dan konten lengkap di lapisan yang dihasilkan dari instruksi menambahkannya, dan sekali sebagai pemberitahuan penghapusan di lapisan yang dihasilkan dari instruksi menghapusnya.
Sebagai contoh, anggap kita untuk sementara membutuhkan kompiler C dan beberapa gambar dan pertimbangkan
(Contoh yang lebih realistis akan membangun beberapa perangkat lunak dengan kompiler alih-alih hanya menyatakan kehadirannya dengan
--version
bendera.)Cuplikan Dockerfile membuat tiga lapisan, yang pertama berisi suite gcc lengkap sehingga meskipun tidak ada dalam sistem file akhir, data yang sesuai masih merupakan bagian dari gambar dengan cara yang sama dan perlu diunduh, diunggah dan dibongkar setiap kali gambar akhir adalah.
The
with
-idiom adalah bentuk umum dalam pemrograman fungsional dengan kepemilikan sumber daya isolat dan sumber daya melepaskan dari logika menggunakannya. Sangat mudah untuk memindahkan idiom ini menjadi shell-scripting, dan kita dapat menguraikan kembali perintah sebelumnya sebagai skrip berikut, untuk digunakan denganCOPY & RUN
seperti pada Saran # 2.Perintah kompleks dapat diubah menjadi fungsi sehingga dapat diumpankan ke
with_c_compiler
. Dimungkinkan juga untuk melakukan panggilan ke beberapawith_whatever
fungsi, tetapi mungkin tidak terlalu diinginkan. (Menggunakan lebih banyak fitur esoteris dari shell, tentu saja memungkinkan untuk membuatwith_c_compiler
perintah kompleks, tetapi dalam semua aspek lebih baik untuk membungkus perintah kompleks ini ke dalam fungsi.)Jika kita ingin mengabaikan Saran # 2, cuplikan Dockerfile yang dihasilkan akan menjadi
yang tidak begitu mudah dibaca dan dipelihara karena kebingungan. Lihat bagaimana varian skrip shell
gcc --version
mengeluarkan penekanan pada bagian penting sementara&&
varian berantai mengubur bagian itu di tengah kebisingan.sumber
Setiap instruksi yang Anda buat di Dockerfile Anda menghasilkan lapisan gambar baru yang dibuat. Setiap lapisan membawa data tambahan yang tidak selalu merupakan bagian dari gambar yang dihasilkan. Misalnya, jika Anda menambahkan file dalam satu lapisan, tetapi menghapusnya di lapisan lain nanti, ukuran gambar akhir akan mencakup ukuran file yang ditambahkan dalam bentuk file "putih" khusus meskipun Anda menghapusnya.
Katakanlah Anda memiliki Dockerfile berikut:
Ukuran gambar yang dihasilkan akan
Sebagai kebalikan, dengan Dockerfile "mirip":
Ukuran gambar yang dihasilkan akan
Anda akan mendapatkan ukuran yang lebih kecil, jika Anda membersihkan cache yum dalam satu pernyataan RUN.
Jadi Anda ingin menjaga keseimbangan antara keterbacaan / perawatan mudah dan jumlah lapisan / ukuran gambar.
sumber
The
RUN
pernyataan mewakili masing-masing satu lapisan. Bayangkan seseorang mengunduh sebuah paket, menginstalnya dan ingin menghapusnya. Jika seseorang menggunakan tigaRUN
pernyataan maka ukuran gambar tidak akan menyusut karena ada lapisan yang terpisah. Jika seseorang menjalankan semua perintah menggunakan satuRUN
pernyataan, ukuran gambar disk dapat dikurangi.sumber