Apa Itu Container Image? Cetakan Asli yang Mencetak Container-mu

Container image adalah template read-only yang dipakai untuk membuat container yang berjalan — aplikasimu, dependensinya, plus resep untuk filesystem-nya, dibekukan jadi satu artefak yang bisa dibagikan.

Diterbitkan 18 Oktober 202611 menit bacaOleh ACY Partner Indonesia
Container image sebagai cetak biru read-only berlapis yang dipakai membuat container berjalan
300 × 250Slot Iklan TersediaPasang iklan Anda di sini

Sampai sini kamu sudah paham bahwa container itu kotak tersegel yang membawa aplikasimu beserta semua yang dibutuhkan untuk berjalan. Tapi kotak itu datang dari mana? Tidak ada yang merakit container yang berjalan dengan tangan satu per satu. Yang terjadi sebenarnya: kamu membangun sebuah container image sekali saja — sebuah cetak biru beku yang read-only — lalu mencetak container identik sebanyak yang kamu mau dari situ. Image itulah yang kamu bangun, simpan, dan bagikan; container adalah salinan hidup yang berjalan.

Beda satu ini sering bikin pemula bingung, padahal begitu jelas, sisa dunia container langsung terasa rapi. Jadi ayo kita bongkar sebuah image dan lihat persis isinya, apa yang ada di dalamnya, dan kenapa dia jadi satuan yang semua orang oper kesana-kemari.

Container image itu sebenarnya apa

Container image adalah template read-only yang berisi segala yang dibutuhkan untuk membuat sebuah container: berkas aplikasimu, library yang dia andalkan, potongan kecil sistem operasi, plus sekumpulan kecil instruksi yang menjelaskan bagaimana container harus dijalankan. Dia satu artefak utuh yang berdiri sendiri — paket yang bisa kamu salin, simpan, dan serahkan ke siapa pun, dengan jaminan dia membawa resep lengkap untuk menjalankan aplikasimu.

Cara paling gampang untuk menyimpannya di kepala adalah hubungan antara class dan object, atau resep dan masakan jadi:

  • Image adalah cetak birunya. Dia tidak pernah berubah setelah dibangun. Beku, read-only, dan identik bagi semua orang yang punya salinannya.
  • Container adalah instance yang berjalan, dibuat dari image itu. Kamu bisa menjalankan sepuluh container dari image yang sama, dan masing-masing jadi proses hidupnya sendiri — tapi semuanya berangkat dari template beku yang sama.
        IMAGE (template read-only)
        ┌──────────────────────────┐
        │  app + library + OS      │
        │  + instruksi startup     │
        └────────────┬─────────────┘
                     │  "jalankan"
         ┌───────────┼───────────┐
         ▼           ▼           ▼
   ┌─────────┐ ┌─────────┐ ┌─────────┐
   │container│ │container│ │container│   ← salinan hidup, bisa ditulis
   └─────────┘ └─────────┘ └─────────┘

Jadi waktu seseorang bilang “kirim image-nya,” maksudnya: serahkan cetak biru beku itu, dan siapa pun, di mana pun, bisa menyalakan salinan berjalan yang kelakuannya persis sama. Image itu portabel; container-nya sekali pakai. Kamu bisa membuang sebuah container dan membuat yang baru dari image-nya dalam sedetik, karena image masih memegang kebenaran utuh soal apa yang aplikasimu butuhkan.

Image itu bendanya, container itu kelakuannya

Pintasan yang berguna: image adalah apa yang kamu punya (berkas yang kamu bangun dan simpan), dan container adalah apa yang kamu lakukan dengannya (kamu jalankan, lalu dia hidup). Kamu tidak mengedit container yang sedang berjalan untuk bikin perubahan jadi permanen — kamu ubah resepnya, lalu bangun image baru. Inilah kenapa container sering disebut infrastruktur yang immutable: sumber kebenaran selalu image, bukan container yang sudah kamu otak-atik dengan tangan.

Apa yang sebenarnya ada di dalam image

Buka sebuah image, dan dia bukan satu gumpalan padat. Dia disusun dari tumpukan layer, plus sedikit metadata yang mengikat semuanya. Memahami layer adalah satu hal paling berguna yang bisa kamu pelajari soal image, karena ini yang menjelaskan kenapa image cepat dibangun, cepat dikirim, dan tidak membuang-buang ruang disk.

Kira-kira begini anatominya:

  • Layer dasar (base) — biasanya filesystem sistem operasi yang sudah dipangkas habis (cukup Linux untuk menjalankan program, bukan desktop lengkap). Di sinilah kebanyakan image bermula.
  • Satu atau lebih layer di atasnya — masing-masing satu set perubahan: pasang runtime bahasa di sini, salin berkas aplikasimu di situ, tambahkan satu langkah konfigurasi. Setiap langkah berarti dalam membangun image menambah satu layer baru.
  • Metadata — manifest kecil yang menjelaskan perintah apa yang harus dijalankan saat container menyala, port jaringan mana yang aplikasinya dengarkan, environment variable, dan seterusnya. Inilah bagian “instruksi startup” dari resepnya.
   IMAGE = tumpukan layer read-only
   ┌──────────────────────────────┐
   │  layer 4: kode aplikasimu     │  ← paling atas, paling spesifik
   ├──────────────────────────────┤
   │  layer 3: dependensi aplikasi │
   ├──────────────────────────────┤
   │  layer 2: runtime bahasa      │
   ├──────────────────────────────┤
   │  layer 1: filesystem base OS  │  ← paling bawah, paling umum
   └──────────────────────────────┘
        + metadata (perintah start, port, env)

Tiap layer bersifat read-only dan mewakili satu langkah yang sudah dibekukan. Tumpuk semuanya, dan hasilnya adalah filesystem lengkap yang dilihat aplikasimu sebagai pohon direktori biasa.

Kenapa layer itu cerdas, bukan sekadar detail teknis

Layer bukan cuma kebetulan cara image disimpan — dia desain yang benar-benar pintar dengan keuntungan nyata:

  • Cache bikin rebuild cepat. Saat kamu membangun ulang image setelah mengubah satu baris kodemu, hanya layer yang benar-benar berubah (dan layer di atasnya) yang perlu dibangun ulang. Layer base OS dan layer dependensi tidak berubah, jadi keduanya dipakai lagi seketika dari cache. Rebuild yang tadinya makan menit bisa selesai dalam hitungan detik.
  • Berbagi menghemat ruang dan bandwidth. Layer itu content-addressed, artinya dua image yang berbagi base layer yang sama benar-benar berbagi salinan tersimpan yang sama persis. Kalau kamu punya lima image yang semuanya dibangun di atas base Linux minimal yang sama, base itu disimpan sekali, bukan lima kali. Hal yang sama berlaku saat mengunduh: kalau kamu sudah punya sebuah layer secara lokal, dia tidak diambil ulang.
  • Mendorong urutan yang masuk akal. Karena layer yang berubah membatalkan semua layer di atasnya, kamu jadi terbiasa menaruh hal-hal yang jarang berubah (base, dependensi) di bawah, dan hal yang berubah terus-menerus (kode aplikasimu) di atas. Urutannya benar, dan rebuild harian cuma menyentuh layer atas yang murah.

Desain berlapis yang saling berbagi inilah sebagian besar alasan kenapa container terasa begitu ringan untuk dipindah-pindah — alasan yang sama yang membuat banyak tim memilih container sejak awal, demi pengiriman yang cepat dan konsisten.

Bagaimana sebuah image dibangun

Kamu tidak menyusun layer dengan tangan. Kamu menulis resep teks pendek — sebuah build file — yang mencantumkan langkah-langkahnya, lalu sebuah build tool membacanya dari atas ke bawah, menjalankan tiap instruksi dan membekukan hasilnya jadi layer baru. Sintaks persisnya berbeda antar-tool, tapi bentuknya universal dan kira-kira seperti ini:

# mulai dari sebuah base image kecil
FROM minimal-os:latest

# pasang runtime bahasanya
RUN install-runtime

# salin berkas aplikasimu ke dalam image
COPY ./app /app

# pasang dependensi aplikasimu
RUN install-dependencies

# beri tahu container apa yang dijalankan saat startup
START run-my-app

Baca itu sebagai sebuah urutan: mulai dari base, lapisi dengan runtime, salin kodemu, pasang yang dia butuhkan, dan catat perintah untuk dijalankan. Tiap baris yang mengubah filesystem menghasilkan satu layer. Baris terakhir adalah metadata — dia tidak menambah layer, cuma mencatat apa yang harus terjadi ketika sebuah container dibuat dari image ini.

Urutannya penting karena alasan cache di atas. Menyalin kode aplikasi yang sering berubah paling akhir, setelah pemasangan dependensi yang jarang berubah, berarti perubahan kode hanya membatalkan layer terakhir. Balik kedua langkah itu, dan tiap perubahan kode memaksa pemasangan ulang seluruh dependensi — lambat, dan sepenuhnya bisa dihindari.

Jaga base image tetap kecil

Base layer tempat kamu memulai menentukan batas bawah ukuran image-mu sekaligus paparan keamanannya. Sebuah base OS serbaguna yang lengkap bisa berukuran ratusan megabyte dan membawa setumpuk program yang aplikasimu tidak akan pernah pakai — masing-masing jadi celah yang berpotensi perlu ditambal. Base image minimal (sering dilabeli “slim”, “alpine”, atau “distroless”) memangkasnya sampai ke hal yang benar-benar pokok. Image yang lebih kecil di-pull lebih cepat, menyala lebih cepat, dan memberi penyerang lebih sedikit bahan untuk dimainkan. Kalau ragu, mulai dari yang lebih kecil dan tambahkan hanya yang benar-benar kamu butuhkan.

Tag: cara kamu memberi nama dan versi pada image

Sebuah image butuh nama supaya bisa kamu rujuk, dan cara untuk mengatakan versi mana yang kamu maksud. Untuk itulah tag ada. Rujukan lengkap ke sebuah image biasanya tampak seperti ini:

   registry/namespace/nama:tag
   │        │         │    │
   │        │         │    └─ label versi, mis. 1.4.0, atau "latest"
   │        │         └────── nama image-nya, mis. my-api
   │        └──────────────── pemilik / akun, mis. acypartner
   └───────────────────────── tempat penyimpanannya (sering dihilangkan)

Contoh konkretnya bisa acypartner/my-api:1.4.0. Bagian setelah titik dua — 1.4.0 — itulah tag-nya. Dia cuma label ramah-manusia yang menunjuk ke satu build spesifik dari image. Kamu bisa punya my-api:1.4.0, my-api:1.5.0, dan my-api:latest berjajar bersebelahan, masing-masing menunjuk ke build beku yang berbeda.

Beberapa hal yang perlu kamu tahu soal tag:

  • Tag itu label yang bisa berpindah, bukan identitas permanen. Besok kamu bisa memberi tag latest ke build yang berbeda. Jadi “latest” tidak berarti “yang terbaru selamanya” — dia berarti “build mana pun yang terakhir kali ditunjuk seseorang ke label itu.” Mengandalkan latest di production adalah jebakan klasik: image di baliknya bisa berubah tanpa nomor versimu ikut berubah.
  • Identitas aslinya adalah digest. Di balik tag yang ramah itu, tiap build image punya digest unik — hash konten panjang seperti sha256:9b2c.... Digest dihitung dari isi image yang sebenarnya, jadi dia tidak pernah bohong dan tidak pernah berpindah. Kalau kamu perlu yakin sedang menjalankan bit yang sama persis tiap kali, kamu mengunci ke digest, bukan ke tag.
  • Kunci versi di production. Untuk apa pun yang serius, rujuk tag versi tertentu (atau sebuah digest) alih-alih latest. Ini bikin deployment-mu bisa direproduksi: image yang kamu tes terbukti adalah image yang dikirim.
   my-api:latest    →  (hari ini)   menunjuk ke build A
   my-api:latest    →  (besok)      menunjuk ke build B   ← label pindah!

   my-api@sha256:9b2c...  →  selalu byte yang sama persis  ← tak pernah pindah

Di mana image tinggal dan bagaimana mereka berpindah

Setelah kamu membangun sebuah image, dia ada di mesinmu — tapi intinya kan untuk dibagikan. Image di-push ke dan di-pull dari sebuah container registry, layanan penyimpanan yang dibuat khusus untuk mereka. Kamu push sebuah image ke registry untuk menerbitkannya, dan orang lain (atau server production-mu) pull dia turun untuk dijalankan.

   mesinmu                      registry                server production
   ┌──────────┐   push image   ┌──────────┐   pull     ┌──────────────┐
   │  bangun  │ ─────────────► │ menyimpan│ ─────────► │ jalankan     │
   │          │                │  image   │            │ container    │
   └──────────┘                └──────────┘            └──────────────┘

Karena image itu berlapis dan content-addressed, transfer ini efisien: hanya layer yang belum dimiliki pihak lain yang dipindahkan lewat jaringan. Registry adalah topik tersendiri — di situlah penamaan, kontrol akses, dan distribusi bertemu — dan itu langkah lanjutan yang alami setelah artikel ini. Untuk sekarang, yang perlu kamu pegang adalah alurnya: bangun sebuah image → push ke registry → pull dan jalankan di mana saja.

Hubungan image dan container, sekali lagi

Layak ditegaskan karena semua hal lain bergantung pada ini. Siklus hidupnya begini:

  1. Kamu menulis resep dan membangun sebuah image — cetak biru beku, berlapis, dan read-only.
  2. Kamu menyimpan dan membagikan image itu (secara lokal, atau lewat registry).
  3. Kamu menjalankan image-nya, yang membuat sebuah container — instance hidup dengan satu layer tipis yang bisa ditulis di atas image read-only, sehingga aplikasi yang berjalan bisa membuat berkas sementara tanpa mengubah image itu sendiri.
  4. Kamu bisa menjalankan container sebanyak yang kamu mau dari satu image. Hentikan, hapus, mulai yang baru — image-nya tak tersentuh dan selalu siap mencetak lebih banyak.
   IMAGE  (read-only, dibagikan, permanen)

     │  tambah satu layer tipis bisa-ditulis tiap dijalankan

   CONTAINER  (hidup, bisa ditulis, sekali pakai)

Layer tipis bisa-ditulis itulah yang membuat sebuah container bisa berjalan dan mencorat-coret data sementara sementara image di bawahnya tetap bersih. Saat container dihapus, layer bisa-ditulis itu ikut hilang — dan justru itulah kenapa apa pun yang ingin kamu simpan harus tinggal di luar container, bukan di dalamnya. Tapi itu topik penyimpanan untuk lain hari. Inti dari sini adalah pemisahan yang bersih: image adalah sumber kebenaran yang awet, container adalah salinan berjalan yang bisa dibuang.

Kenapa ini penting

Image adalah artefak paling penting di seluruh alur kerja container. Dialah yang dihasilkan proses build-mu, yang diuji oleh tes-mu, yang disimpan, yang dikirim, dan yang dijalankan di production — byte beku yang sama di tiap tahap. Kesamaan itulah seluruh janji container: image yang kamu bangun dan tes di laptop terbukti adalah image yang berjalan di server, layer demi layer.

Ini juga mengubah cara kamu memikirkan perubahan. Kamu tidak memperbaiki container yang bertingkah dengan login lalu mengutak-atiknya. Kamu ubah resepnya, bangun image baru, lalu gulirkan — meninggalkan jejak rapi berupa artefak yang terversi dan bisa direproduksi. Begitu pola pikir ini nyantol, deployment berhenti jadi peristiwa menegangkan sekali-kejadian dan berubah jadi pergantian rutin nan berulang dari satu image yang sudah-terbukti-baik ke image lain.

Kalau kamu mau gambaran yang lebih luas soal bagaimana ini cocok dengan sisa dunia container, dia langsung berdiri di atas apa itu container dan pas dipasangkan dengan memahami bedanya container dengan virtual machine, karena sifat image yang ringan dan berlapis adalah alasan besar kenapa container menyala jauh lebih cepat daripada VM.

Penutup

Ini seluruh idenya dalam satu tempat:

  • Container image adalah cetak biru read-only yang berdiri sendiri — aplikasimu, dependensinya, potongan OS minimal, dan instruksi startup — dibekukan jadi satu artefak yang bisa dibagikan.
  • Image itu template-nya; container adalah instance yang berjalan yang dibuat darinya. Satu image, banyak container; image tidak pernah berubah saat kamu menjalankannya.
  • Image dibangun dari layer, masing-masing satu langkah beku. Layer memungkinkan rebuild cepat lewat cache serta penyimpanan yang dibagi dan hemat ruang — sebabnya kamu mengurutkan langkah dari yang paling jarang berubah (base) ke yang paling sering berubah (kodemu).
  • Tag (bagian setelah titik dua, seperti :1.4.0 atau :latest) adalah label ramah-manusia yang bisa berpindah. Identitas asli yang permanen adalah digest — kunci versi atau digest di production, bukan latest.
  • Kamu membangun image, push ke registry, lalu pull dan jalankan di mana saja — dan hanya layer yang belum dimiliki sebuah mesin yang berpindah lewat jaringan.

Pertanyaan lanjutan yang jelas adalah di mana semua image ini disimpan dan dibagikan setelah kamu membangunnya — registry yang memberi mereka nama, versi, dan membagikannya. Persis ke situlah artikel ini mengarah, dan itu tempat alami untuk kamu tuju berikutnya.

Tag:servercontainerimagedevopspemula
728 × 90Slot Iklan TersediaPasang iklan Anda di sini

Artikel Terkait

Lihat Semua Artikel

Artikel yang Mungkin Kamu Suka

SSL dan enkripsi at rest — data terlindungi saat berjalan dan saat tersimpan di disk
Server / Keamanan Server

SSL dan Enkripsi at Rest: Melindungi Data Saat Berjalan dan Saat Tersimpan

Enkripsi melindungi data di dua tempat: saat data lewat di jaringan (in transit) dan saat data nganggur di disk (at rest). Pahami bedanya, kenapa kamu butuh keduanya, bagaimana TLS, enkripsi disk, dan pengelolaan kunci sebenarnya saling melengkapi, plus kesalahan praktis yang sering bikin sia-sia.

9 Nov 202612 menit baca
Mengamankan port dan service — menutup pintu di server yang tidak kamu pakai
Server / Keamanan Server

Mengamankan Port dan Service: Menutup Pintu yang Tidak Kamu Pakai

Setiap port yang terbuka di server adalah satu pintu yang bisa dicoba orang lain. Pahami port dan service itu sebenarnya apa, kenapa service yang terekspos jadi risiko terbesarmu, dan kebiasaan sederhana menutup semua yang tidak kamu butuhkan — dijelaskan dari nol.

8 Nov 202610 menit baca
Prinsip least privilege — memberi hanya akses minimum yang dibutuhkan tiap user dan proses
Server / Keamanan Server

Prinsip Least Privilege: Beri Setiap Hal Hanya Akses yang Benar-Benar Dibutuhkan

Least privilege adalah aturan diam-diam di balik hampir semua setup keamanan yang solid: setiap user, proses, dan kunci hanya dapat akses minimum untuk menjalankan tugasnya, tidak lebih.

7 Nov 202612 menit baca
Fail2ban dan dasar intrusi — mengawasi log dan mem-banned otomatis pelaku yang menggedor berulang kali
Server / Keamanan Server

Fail2ban dan Dasar Intrusi: Mem-banned Otomatis Bot yang Terus Menggedor Server-mu

Penyerang tidak berhenti setelah sekali salah tebak — mereka terus menggedor, ribuan kali sehari. Pahami seperti apa sebenarnya percobaan intrusi, apa yang dikerjakan fail2ban, bagaimana ia mengawasi log dan mem-banned pelaku otomatis, dan cara menyetelnya dengan masuk akal tanpa mengunci dirimu.

6 Nov 202612 menit baca
Menjaga software tetap update — menutup lubang keamanan yang sudah diketahui sebelum penyerang memakainya
Server / Keamanan Server

Menjaga Software Tetap Update: Kebiasaan Membosankan yang Mencegah Sebagian Besar Pembobolan Server

Kebanyakan server tidak dibobol lewat serangan baru yang canggih — tapi lewat lubang lama yang sudah diketahui, yang sebenarnya cukup ditutup dengan update. Pelajari kenapa update itu penting, apa saja yang harus di-update, cara melakukannya dengan aman tanpa merusak apa pun, dan cara.

5 Nov 20269 menit baca
Konfigurasi firewall — aturan default-deny yang hanya membuka port yang kamu butuhkan
Server / Keamanan Server

Konfigurasi Firewall: Menyusun Aturan Default-Deny Tanpa Mengunci Diri Sendiri

Tahu apa itu firewall dan benar-benar mengonfigurasinya dengan rapi adalah dua keterampilan berbeda. Pelajari cara menyusun aturan default-deny, mengurutkan aturan dengan benar, membuka akses sendiri lebih dulu, menangani IPv6 dan security group cloud, lalu mengujinya sebelum dipakai — panduan.

4 Nov 202614 menit baca