Praktik terbaik untuk mem-build container

Last reviewed 2023-02-28 UTC

Artikel ini menjelaskan kumpulan praktik terbaik untuk mem-build container. Praktik ini mencakup berbagai tujuan, mulai dari mempersingkat waktu build, hingga membuat image yang lebih kecil dan lebih tangguh, dengan tujuan membuat container lebih mudah dibuat (misalnya, dengan Cloud Build), dan lebih mudah dijalankan di Google Kubernetes Engine (GKE).

Praktik terbaik ini juga tidak sama tingkat kepentingannya. Misalnya, Anda mungkin berhasil menjalankan workload produksi tanpa sebagian di antaranya, tetapi workload lainnya bersifat mendasar. Secara khusus, pentingnya keamanan terkait praktik terbaik adalah bersifat subjektif Apakah Anda mengimplementasikannya bergantung pada lingkungan dan batasan Anda.

Untuk mendapatkan hasil maksimal dari artikel ini, Anda memerlukan pengetahuan tentang Docker dan Kubernetes. Beberapa praktik terbaik yang dibahas di sini juga berlaku untuk container Windows, tetapi sebagian besar mengasumsikan bahwa Anda menggunakan container Linux. Saran tentang cara menjalankan dan mengoperasikan container tersedia di Praktik terbaik untuk mengoperasikan container.

Paket satu aplikasi per container

Tingkat kepentingan: TINGGI

Ketika Anda mulai menggunakan container, adalah kesalahan umum untuk memperlakukannya sebagai virtual machines (VMs) yang dapat menjalankan banyak hal berbeda secara bersamaan. Container dapat digunakan dengan cara ini, tetapi cara ini akan mengurangi sebagian besar keunggulan model container. Contohnya, gunakan stack Apache/MySQL/PHP klasik: Anda mungkin tergoda untuk menjalankan semua komponen dalam satu container. Namun, praktik terbaik adalah menggunakan dua atau tiga container yang berbeda: satu untuk Apache, satu untuk MySQL, dan satu untuk PHP jika Anda menjalankan PHP-FPM.

Karena container didesain untuk memiliki lifecycle yang sama dengan aplikasi yang di-host, setiap container Anda hanya dapat mencakup satu aplikasi. Saat container dimulai, begitu juga aplikasi dan saat aplikasi berhenti, demikian juga container. Diagram berikut menunjukkan praktik terbaik ini.

Diagram yang menunjukkan proses booting tanpa image kustom.

Gambar 1. Container di sebelah kiri mengikuti praktik terbaik. Container di sebelah kanan tidak demikian.

Jika Anda memiliki beberapa aplikasi dalam satu container, aplikasi tersebut mungkin memiliki siklus proses yang berbeda, atau berada dalam status yang berbeda. Misalnya, Anda mungkin berujung dengan container yang berjalan, tetapi salah satu komponen intinya error atau tidak responsif. Tanpa health check tambahan, keseluruhan sistem pengelolaan container (Docker atau Kubernetes) tidak dapat mengetahui apakah container dalam keadaan sehat. Dalam kasus Kubernetes, artinya jika komponen inti tidak responsif, Kubernetes tidak dapat memulai ulang container Anda secara otomatis.

Anda mungkin melihat tindakan berikut pada image publik, tetapi jangan ikuti contohnya:

Menangani PID 1, penanganan sinyal, dan zombie processes dengan benar

Tingkat kepentingan: TINGGI

Sinyal Linux merupakan cara utama untuk mengontrol siklus proses di dalam container. Sesuai dengan praktik terbaik sebelumnya, untuk menautkan siklus proses aplikasi Anda ke container secara tepat, pastikan aplikasi Anda menangani sinyal Linux dengan benar. Sinyal Linux yang paling penting adalah SIGTERM karena menghentikan sebuah proses. Aplikasi Anda mungkin juga menerima sinyal SIGKILL, yang digunakan untuk menghentikan proses secara paksa, atau sinyal SIGINT, yang dikirim saat Anda mengetik Ctrl+C dan biasanya diperlakukan seperti SIGTERM singkat ini.

ID proses (PID) merupakan ID unik yang diberikan kernel Linux untuk setiap proses. PID adalah namespace, yang berarti container memiliki kumpulan PID sendiri yang dipetakan ke PID pada sistem host. Proses awal yang diluncurkan ketika memulai kernel Linux memiliki PID 1. Untuk sistem operasi normal, proses ini adalah sistem init, misalnya, systemd atau SysV. Demikian pula, proses pertama yang diluncurkan di container mendapatkan PID 1. Docker dan Kubernetes menggunakan sinyal untuk berkomunikasi dengan proses di dalam container terutama untuk menghentikannya. Docker dan Kubernetes keduanya hanya dapat mengirim sinyal ke proses yang memiliki PID 1 di dalam container.

Dalam konteks container, sinyal PID dan Linux menciptakan dua gangguan untuk dipertimbangkan.

Masalah 1: Bagaimana kernel Linux menangani sinyal

Kernel Linux menangani sinyal secara berbeda untuk proses yang memiliki PID 1 dibandingkan proses lainnya. Pengendali sinyal tidak secara otomatis terdaftar untuk proses ini, yang berarti sinyal seperti SIGTERM atau SIGINT tidak memiliki pengaruh secara default. Secara default, Anda harus menghentikan proses dengan menggunakan SIGKILL untuk mencegah penghentian paksa. Tergantung pada aplikasi Anda, penggunaan SIGKILL dapat menyebabkan error yang ditampilkan kepada pengguna, penulisan terganggu (untuk penyimpanan data), atau pemberitahuan yang tidak diinginkan dalam sistem pemantauan Anda.

Masalah 2: Cara sistem init klasik menangani proses yang terlantar

Sistem init klasik seperti systemd juga digunakan untuk menghapus (reap) zombie processes yang terlantar. Proses terlantar—proses yang induknya telah mati— dilampirkan kembali ke proses yang memiliki PID 1, yang seharusnya me-reap ketika mati. Sistem init yang normal melakukannya. Tetapi dalam container, tanggung jawab ini ada pada proses apa pun yang memiliki PID 1. Jika proses tersebut tidak menangani reaping dengan tepat, Anda berisiko kehabisan memori atau beberapa resource lainnya.

Masalah ini memiliki beberapa solusi umum, yang diuraikan pada bagian-bagian berikut.

Solusi 1: Jalankan sebagai PID 1 dan daftarkan pengendali sinyal

Solusi ini hanya mengatasi masalah awal. Valid jika aplikasi Anda memulai proses turunan dengan cara yang terkontrol (yang sering muncul), menghindari masalah kedua.

Cara termudah untuk menerapkan solusi ini adalah dengan meluncurkan proses Anda dengan instruksi CMD dan/atau ENTRYPOINT di Dockerfile Anda. Misalnya, pada Dockerfile berikut, nginx adalah proses pertama dan satu-satunya yang akan diluncurkan.

FROM debian:11

RUN apt-get update && \
    apt-get install -y nginx

EXPOSE 80

CMD [ "nginx", "-g", "daemon off;" ]

Terkadang, Anda mungkin perlu menyiapkan lingkungan di container untuk proses Anda berjalan dengan tepat. Dalam hal ini, praktik terbaik adalah membuat container meluncurkan skrip shell saat memulai. Skrip shell ditugaskan untuk menyiapkan lingkungan dan meluncurkan proses utama. Namun, jika Anda mengambil pendekatan ini, skrip shell memiliki PID 1, bukan proses Anda, yang mana Anda harus menggunakan perintah exec untuk meluncurkan proses dari shell skrip. Perintah exec akan menguba skrip dengan program yang Anda inginkan. Proses Anda akan mewarisi PID 1.

Solusi 2: Aktifkan proses berbagi namespace di Kubernetes

Saat Anda mengaktifkan proses berbagi namespace untuk Pod, Kubernetes akan menggunakan satu proses namespace untuk semua container dalam Pod tersebut. Container infrastruktur Pod Kubernetes menjadi PID 1 dan secara otomatis menuai proses yang terlantar.

Solusi 3: Gunakan sistem init yang khusus

Seperti yang Anda lakukan di lingkungan Linux yang lebih klasik, Anda juga dapat menggunakan sistem init untuk menyelesaikan masalah tersebut. Namun, sistem init normal seperti systemd atau SysV lebih kompleks dan luas untuk tujuan ini, yang mana membuat kami merekomendasikan Anda menggunakan sistem init seperti tini, yang dibuat khusus untuk container.

Jika Anda menggunakan sistem init khusus, proses init tersebut memiliki PID 1 yang dapat melakukan hal berikut:

  • Mendaftarkan pengendali sinyal yang tepat.
  • Memastikan sinyal berfungsi untuk aplikasi Anda.
  • Menuai setiap zombie process yang mungkin terjadi.

Anda dapat menggunakan solusi ini di Docker dengan menggunakan opsi --init dari perintah docker run. Untuk menggunakan solusi ini di Kubernetes, Anda harus menginstal sistem init di image container dan menggunakannya sebagai entrypoint pada container Anda.

Optimalkan Docker build cache

Tingkat kepentingan: TINGGI

Docker mem-build cache yang dapat mempercepat pembuatan image container. Image dibuat berlapis dan dalam Dockerfile, setiap petunjuk menciptakan lapisan pada image yang dihasilkan. Selama build, jika memungkinkan, Docker menggunakan kembali lapisan dari build sebelumnya dan melewati langkah yang berpotensi merugikan. Docker dapat menggunakan build cache hanya jika semua langkah build sebelumnya juga menggunakannya. Meskipun perilaku ini biasanya merupakan hal baik yang membuat build berjalan lebih cepat, Anda perlu mempertimbangkan beberapa kasus.

Misalnya, untuk mendapatkan manfaat utuh dari cache build Docker, Anda harus memosisikan langkah-langkah build yang sering berubah di bagian bawah Dockerfile. Jika Anda menempatkannya di bagian atas, Docker tidak dapat menggunakan cache build-nya untuk langkah-langkah build lain yang tidak sering berubah. Karena image Docker baru biasanya dibuat untuk setiap versi baru dari kode sumber Anda, tambahkan kode sumber ke image selambat mungkin di Dockerfile. Pada diagram berikut, Anda dapat melihat bahwa jika Anda mengubah STEP 1, Docker hanya dapat menggunakan kembali lapisan berbeda dari langkah FROM debian:11. Namun, jika Anda mengubah STEP 3, Docker dapat menggunakan kembali lapisan berbeda STEP 1 dan STEP 2.

Contoh bagaimana cara menggunakan cache build Docker

Gambar 2. Contoh bagaimana cara menggunakan cache build Docker Pada warna hijau, lapisan dapat Anda gunakan kembali. Pada warna merah, lapisan harus dibuat kembali.

Menggunakan kembali lapisan memiliki konsekuensi lain: jika langkah build mengandalkan pada jenis cache yang disimpan di sistem file lokal, cache ini harus dihasilkan dalam langkah build yang sama. Jika cache ini tidak dihasilkan, langkah build Anda mungkin dijalankan dengan cache yang kedaluwarsa yang berasal dari build sebelumnya. Anda mungkin sering melihat perilaku ini dengan pengelola paket seperti apt atau yum: Anda harus memperbarui repositori dalam perintah RUN yang sama dengan penginstalan paket Anda.

Jika Anda mengubah langkah RUN kedua di Dockerfile berikut, perintah apt-get update tidak akan dijalankan kembali, sehingga Anda memiliki cache apt yang kedaluwarsa.

FROM debian:11

RUN apt-get update
RUN apt-get install -y nginx

Sebagai ganti, gabungkan kedua perintah tersebut dalam satu langkah RUN:

FROM debian:11

RUN apt-get update && \
    apt-get install -y nginx

Hapus alat yang tidak diperlukan

Tingkat kepentingan: SEDANG

Untuk melindungi aplikasi Anda dari penyerang, cobalah untuk mengurangi permukaan serangan terhadap aplikasi Anda dengan menghapus alat yang tidak diperlukan. Misalnya, hapus utilitas suka netcat, yang dapat Anda gunakan untuk membuat shell terbalik di dalam sistem Anda. Jika netcat tidak ada di container, penyerang harus mencari cara lain.

Praktik terbaik berlaku untuk semua workload, meskipun tidak dalam container. Perbedaannya adalah praktik terbaik ini dioptimalkan untuk container, daripada VM klasik atau server bare-metal.

Ketika Anda menghapus alat yang tidak diperlukan, hal ini dapat membantu Anda meningkatkan proses debug. Misalnya, jika Anda menerapkan praktik terbaik ini dengan cukup lengkap, logs lengkap pelacakan, dan pembuatan profil dapat menyentuh .mandat. Akibatnya, Anda tidak dapat lagi mengandalkan alat debug lokal karena alat tersebut sering kali memiliki hak istimewa.

Isi sistem file

Bagian pertama dari praktik terbaik ini berkaitan dengan isi image container. Menyimpan sedikit mungkin hal dalam image Anda. Jika Anda dapat mengompilasi aplikasi Anda ke dalam satu biner yang ditautkan secara statis, tambahkan biner ini ke scratch image memungkinkan Anda untuk mendapatkan image akhir yang berisihanya aplikasi Anda dan tidak lainnya. Dengan mengurangi jumlah paket alat pada image Anda, Anda mengurangi kemungkinan hal yang dapat dilakukan oleh calon penyerang pada container Anda. Untuk informasi lebih lanjut, lihat Mem-build kemungkinan image terkecil.

Keamanan sistem file

Tanpa alat pada image adalah tidak cukup: Anda harus mencegah calon penyerang menginstal alat mereka sendiri. Anda dapat menggabungkan dua metode di sini:

  • Hindari menjalankan sebagai root di dalam container: metode ini menawarkan lapisan keamanan pertama dan dapat mencegah, misalnya, penyerang mengubah file yang dimiliki root menggunakan pengelola paket yang disematkan pada image (seperti apt-get atau apk). Agar metode ini berguna, Anda harus menonaktifkan atau meng-uninstal perintah sudo. Topik ini dibahas secara lebih dalam di Menghindari berjalan sebagai root.

  • Luncurkan container dalam mode hanya baca, yang mana Anda lakukan menggunakan flag --read-only dari perintah docker run atau dengan menggunakan opsi readOnlyRootFilesystem di Kubernetes.

Membuat image sekecil mungkin

Tingkat kepentingan: SEDANG

Mem-build image yang lebih kecil memberikan keuntungan seperti waktu upload dan download lebih cepat, yang sangat penting untuk waktu cold start pada pod di Kubernetes: semakin kecil image, semakin cepat node tersebut mendownload. Namun, mem-build image kecil kemungkinan sulit karena Anda dapat secara tidak sengaja menyertakan dependensi build atau lapisan yang tidak dioptimalkan dalam image akhir.

Gunakan image dasar terkecil

Image dasar adalah image yang dirujuk dalam instruksiFROM di Dockerfile Anda. Setiap instruksi lain di Dockerfile akan dibuat di atas image ini. Semakin kecil image dasar, makin kecil image yang dihasilkan, dan semakin cepat dapat didownload. Misalnya,pada image alpine:3.17 berukuran 23 MB lebih kecil daripada imageubuntu:22.04 .

Anda bahkan dapat menggunakan image dasar scratch, yang merupakan image kosong di mana Anda dapat mem-build lingkungan runtime Anda sendiri. Jika aplikasi Anda adalah biner yang ditautkan secara statis, Anda dapat menggunakan image dasar scratch seperti berikut:

FROM scratch
COPY mybinary /mybinary
CMD [ "/mybinary" ]

Video Praktik Terbaik Kubernetes berikut mencakup strategi tambahan untuk mem-build container kecil serta mengurangi eksposur terhadap kerentanan keamanan.

Kurangi jumlah kekacauan pada image

Untuk mengurangi ukuran image, cukup instal apa yang benar-benar diperlukan di dalamnya. Anda mungkin berpikir untuk menginstal paket extra, lalu menghapusnya di langkah berikutnya. Namun, pendekatan ini kurang memadai. Karena setiap petunjuk Dockerfile membuat lapisan, menghapus data dari image pada langkah selanjutnya dari langkah pembuatannya yang tidak akan mengurangi ukuran keseluruhan iamge (data masih ada, hanya tersembunyi di lapisan yang lebih dalam). Perhatikan contoh berikut:

Dockerfile yang buruk Dockerfile yang Baik

FROM debian:11
RUN apt-get update && \ apt-get install -y \ [buildpackage] RUN [build my app] RUN apt-get autoremove --purge \ -y [buildpackage] && \ apt-get -y clean && \ rm -rf /var/lib/apt/lists/*

FROM debian:11
RUN apt-get update && \ apt-get install -y \ [buildpackage] && \ [build my app] && \ apt-get autoremove --purge \ -y [buildpackage] && \ apt-get -y clean && \ rm -rf /var/lib/apt/lists/*

Dalam versi Dockerfile yang buruk, [buildpackage] dan file dalam /var/lib/apt/lists/* masih terdapat lapisan yang terkait dengan RUN pertama. Lapisan ini adalah bagian dari image yang harus diupload dan didownload bersama sisanya, meskipun data yang ada di dalamnya tidak dapat diakses dalam image yang dihasilkan.

Dalam versi Dockerfile yang baik, semua dilakukan dalam satu lapisan yang hanya berisi aplikasi bawaan Anda. [buildpackage] dan file di /var/lib/apt/lists/* tidak muncul di mana pun dalam image yang dihasilkan, bahkan tidak tersembunyi di lapisan yang lebih dalam.

Untuk mengetahui informasi lebih lanjut tentang lapisan image, lihat Optimalkan cache build Docker.

Cara baik lainnya untuk mengurangi jumlah kekacauan di image adalah dengan menggunakan multi-staged builds (diperkenalkan di Docker 17.05). Dengan multi-staged builds, Anda dapat mem-build aplikasi Anda dalam container "build" pertama dan menggunakan hasilnya pada container lain, saat menggunakan Dockerfile yang sama.

Proses multi-staged builds Docker

Gambar 3. Proses multi-staged builds Docker.

Dalam Dockerfile berikut, biner hello dibuat pada container pertama dan dimasukkan dalam container kedua. Karena container kedua didasarkan pada scratch, image yang dihasilkan hanya berisi biner hello, bukan file sumber dan file objek yang diperlukan selama proses build. Biner harus ditautkan secara statis agar dapat berfungsi tanpa memerlukan library luar pada scratch image.

FROM golang:1.20 as builder

WORKDIR /tmp/go
COPY hello.go ./
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -ldflags '-s' -o hello

FROM scratch
CMD [ "/hello" ]
COPY --from=builder /tmp/go/hello /hello

Cobalah membuat image dengan lapisan umum

Jika Anda harus mendownload image Docker, Docker akan terlebih dahulu memeriksa apakah Anda sudah memiliki beberapa lapisan yang ada dalam image. Jika Anda memiliki lapisan itu, lapisan tersebut tidak dapat diunduh. Situasi ini dapat terjadi jika sebelumnya Anda mendownload image lain yang memiliki basis sama dengan image yang sedang didownload. Hasilnya adalah jumlah data yang didownload lebih sedikit untuk image kedua.

Di tingkat organisasi, Anda dapat memanfaatkan pengurangan ini dengan memberi developer Anda dengan kumpulan image dasar standar yang umum. Sistem Anda hanya dapat mendownload setiap image dasar satu kali. Setelah download awal, hanya lapisan yang membuat setiap image unik diperlukan. Sehingga, semakin banyak kesamaan image Anda, semakin cepat image tersebut didownload.

Cobalah membuat image dengan lapisan umum

Gambar 4. Membuat image dengan lapisan umum.

Memindai image untuk mengetahui adanya kerentanan

Tingkat kepentingan: SEDANG

Kerentanan software adalah masalah yang perlu dipahami dengan baik di dunia server bare-metal dan virtual machines. Cara umum untuk mengatasi kerentanan adalah menggunakan sistem inventaris terpusat yang mencantumkan paket yang diinstal di setiap server. Berlangganan feed kerentanan sistem operasi upstream untuk mendapatkan informasi saat ada kerentanan yang memengaruhi server, dan terapkan patch yang sesuai.

Namun, karena container seharusnya tidak dapat diubah (lihat statelessness dan ketetapan container untuk mengetahui detail selengkapnya), jangan melakukan patch jika terjadi kerentanan. Praktik terbaik adalah mem-build ulang image, menyertakan patch, dan men-deploy ulang. Container memiliki siklus proses yang jauh lebih singkat dan identitas yang tidak terlalu jelas dibandingkan server. Sehingga, menggunakan sistem inventaris terpusat yang serupa adalah cara buruk untuk mendeteksi kerentanan pada container.

Untuk membantu Anda mengatasi masalah ini, Artifact Analysis dapat memindai image Anda untuk menemukan kerentanan keamanan pada paket yang dipantau secara publik. Opsi-opsi berikut tersedia:

Pemindaian kerentanan otomatis

Jika diaktifkan, fitur ini mengidentifikasi kerentanan paket pada image container Anda. Image dipindai saat diupload ke Artifact Registry atau Container Registry dan datanya selalu dipantau untuk menemukan kerentanan baru sampai 30 hari setelah pengiriman image. Anda dapat menindaklanjuti informasi yang dilaporkan oleh fitur ini dengan beberapa cara:

  • Buatlah tugas cron-like yang mencantumkan kerentanan dan memicu proses untuk memperbaikinya, jika terdapat perbaikan.
  • Segera setelah kerentanan terdeteksi, gunakan integrasi Pub/Sub untuk memicu proses patching yang digunakan oleh organisasi Anda.
On-Demand Scanning API

Jika diaktifkan, Anda dapat memindai image lokal atau image yang disimpan di Artifact Registry atau Container Registry secara manual. Fitur ini membantu Anda mendeteksi dan mengatasi kerentanan sejak awal di pipeline build Anda. Misalnya, Anda dapat menggunakan Cloud Build untuk memindai image setelah image di-build, lalu memblokir upload ke Artifact Registry jika pemindaian mendeteksi kerentanan pada tingkat keparahan yang ditentukan. Jika Anda juga mengaktifkan pemindaian kerentanan otomatis, Artifact Registry juga akan memindai image yang Anda upload ke registry.

Kami menyarankan Anda melakukan otomatisasi proses patching dan mengandalkan pipeline continuous integration yang sudah ada yang awalnya digunakan untuk membuat image. Jika Anda yakin dengan pipeline continuous deployment, Anda juga dapat men-deploy image secara otomatis saat sudah siap. Namun, kebanyakan pengguna lebih memilih langkah verifikasi manual sebelum deployment. Proses berikut bertujuan sebagai berikut:

  1. Simpan image Anda di Artifact Registry dan aktifkan pemindaian kerentanan.
  2. Konfigurasikan tugas yang secara rutin membuat kerentanan baru dari Artifact Registry dan memicu build ulang image jika diperlukan.
  3. Saat image baru di-build, Anda dapat meminta sistem continuous deployment Anda untuk men-deploy image tersebut ke lingkungan staging.
  4. Periksa masalah pada lingkungan staging secara manual.
  5. Jika tidak ada masalah yang ditemukan, picu deployment ke produksi secara manual.

Beri tag pada image Anda dengan tepat

Tingkat kepentingan: SEDANG

Image Docker umumnya diidentifikasi oleh dua komponen: nama dan tag-nya. Misalnya, untuk image google/cloud-sdk:419.0.0, google/cloud-sdk adalah nama dan 419.0.0 adalah tag. Tag latest digunakan secara default jika Anda tidak menyediakannya di perintah Docker. Pasangan nama dan tag bersifat unik pada waktu tertentu. Namun, Anda dapat menetapkan ulang tag ke image yang berbeda sesuai dengan kebutuhan.

Saat Anda membuat image, Anda bebas memberi tag dengan tepat. Mengikuti kebijakan pemberian tag yang koheren dan konsisten. Dokumentasikan kebijakan pemberian tag Anda agar pengguna image dapat memahami dengan mudah.

Image container adalah cara mengemas dan merilis perangkat lunak. Dengan memberikan tag pada image, pengguna dapat mengidentifikasi versi software tertentu untuk mendownloadnya. Dengan alasan ini, tautkan sistem pemberian tag pada image container ke kebijakan rilis software Anda dengan kuat.

Beri tag menggunakan pembuatan versi semantik

Cara umum untuk merilis software adalah dengan "memberi tag" (seperti dalam perintah git tag) pada versi kode sumber tertentu dengan beberapa versi nomor. Spesifikasi Pembuatan Versi Semantik menyediakan cara yang mudah untuk menangani nomor versi. Dalam sistem ini, software Anda memiliki nomor versi pada tiga bagian: X.Y.Z, yang mana:

  • X adalah versi utama, yang bertambah hanya untuk perubahan API yang tidak kompatibel.
  • Y adalah versi minor, yang ditambahkan untuk fitur baru.
  • Z adalah versi patch, yang ditambahkan untuk perbaikan bug.

Setiap penambahan nomor versi minor atau patch harus ditujukan untuk perubahan yang kompatibel dengan versi sebelumnya.

Jika Anda menggunakan sistem ini, atau sistem yang serupa, beri tag pada image Anda sesuai dengan kebijakan berikut:

  • Tag latest selalu merujuk ke image terbaru (mungkin stabil). Tag ini dipindahkan segera setelah image baru dibuat.
  • Tag X.Y.Z mengacu pada versi software tertentu. Jangan memindahkannya ke image lain.
  • Tag X.Y mengacu pada rilis patch terbaru dari cabang kecil X.Y software Anda. Hal ini dipindahkan saat versi patch baru dirilis.
  • Tag X mengacu pada rilis patch terbaru dari rilis minor terbaru dari cabang utama X. Elemen tersebut dipindahkan saat versi patch baru atau versi minor baru dirilis.

Penggunaan kebijakan ini menawarkan fleksibilitas kepada pengguna untuk memilih versi software yang ingin mereka gunakan. Mereka dapat memilih versi XYZ tertentu dan dijamin bahwa image tidak akan pernah berubah, atau bisa mendapatkan pembaruan secara otomatis dengan memilih tag yang kurang spesifik.

Pemberian tag menggunakan hash commit Git

Jika memiliki sistem continuous delivery yang canggih dan sering merilis software, Anda mungkin tidak menggunakan nomor versi seperti yang dijelaskan dalam Semantic Versioning Specification. Dalam hal ini, cara umum untuk menangani nomor versi adalah dengan menggunakan hash SHA-1 Git commit (atau versi singkatnya) sebagai nomor versi. Secara desain, hash commit Git tidak dapat diubah dan mereferensikan versi tertentu software Anda.

Anda dapat menggunakan hash commit ini sebagai nomor versi software, tetapi juga sebagai tag untuk image Docker yang dibuat dari versi software tertentu ini. Tindakan ini akan membuat image Docker dapat dilacak: karena dalam hal ini tag image tidak dapat diubah, Anda akan secara langsung tahu versi tertentu software Anda yang berjalan di dalam container tertentu. Dalam pipeline continuous delivery, otomatiskan pembaruan nomor versi yang digunakan untuk deployment Anda.

Pertimbangkan dengan cermat apakah akan menggunakan image publik

Tingkat kepentingan: N/A

Salah satu keuntungan besar Docker adalah banyaknya jumlah image yang tersedia secara publik, untuk semua jenis software. image-image ini memungkinkan Anda untuk memulai dengan cepat. Namun, saat mendesain strategi penampung untuk organisasi, Anda mungkin memiliki batasan yang tidak dapat dipenuhi oleh image yang diberikan secara publik. Berikut beberapa contoh batasan yang dapat merender penggunaan image publik menjadi tidak mungkin:

  • Anda ingin mengontrol dengan tepat apa yang ada di dalam image Anda.
  • Anda tidak ingin bergantung pada repositori eksternal.
  • Anda ingin mengontrol kerentanan di lingkungan produksi dengan ketat.
  • Anda menginginkan sistem operasi dasar yang sama di setiap image.

Respons terhadap semua batasan tersebut adalah sama, dan sayangnya: Anda harus membuat image sendiri. Anda dapat membuat image sendiri untuk image pada jumlah terbatas, tetapi jumlah ini cenderung berkembang dengan cepat. Untuk memiliki peluang dalam mengelola sistem pada skala besar, pertimbangkan untuk menggunakan hal-hal berikut:

  • Cara otomatis untuk membuat image, dengan cara yang andal, bahkan untuk image yang jarang di-build. Pemicu build di Cloud Build adalah cara yang tepat untuk mencapainya.
  • Image dasar standar. Google menyediakan beberapa image dasar yang dapat Anda gunakan.
  • Cara otomatis untuk menyebarkan update ke image dasar ke image "turunan".
  • Cara untuk mengatasi kerentanan pada image Anda. Untuk mengetahui informasi selengkapnya, lihat Memindai kerentanan pada image.
  • Cara untuk menerapkan standar internal pada image yang dibuat oleh tim yang berbeda di organisasi Anda.

Ada beberapa alat untuk membantu Anda menerapkan kebijakan pada image yang Anda build dan deploy:

  • container-diff dapat menganalisis konten image dan bahkan membandingkan dua image di antaranya.
  • container-structure-test dapat menguji apakah konten image mematuhi serangkaian aturan yang Anda tentukan.
  • Grafeas adalah API artifact metadata, di mana Anda menyimpan metadata tentang image untuk memeriksa apakah image tersebut mematuhi kebijakan Anda.
  • Kubernetes memiliki pengontrol tiket masuk yang dapat Anda gunakan untuk memeriksa sejumlah prasyarat sebelum men-deploy workload di Kubernetes.

Anda mungkin juga ingin mengadopsi sistem campuran: menggunakan image publik seperti Debian atau Alpine sebagai image dasar dan membuatnya di atas image tersebut. Atau, Anda mungkin ingin menggunakan image publik untuk beberapa image nonkritis, dan membuat image Anda sendiri untuk kasus lain. Pertanyaan-pertanyaan tersebut tidak memiliki jawaban benar atau salah, tetapi Anda harus mengatasinya.

Catatan tentang lisensi

Sebelum Anda menyertakan library dan paket pihak ketiga di image Docker, pastikan lisensi memungkinkan Anda untuk melakukannya. Pihak ketiga juga dapat memberikan batasan pada pendistribusian ulang, yang berlaku saat Anda melakukan publikasi image Docker ke registry publik.

Langkah selanjutnya

Pelajari arsitektur referensi, diagram, dan praktik terbaik tentang Google Cloud. Lihat Cloud Architecture Center kami.