Section Image Build dan Optimisasi ditutup dengan pengakuan yang perlu kita pegang sejak sekarang: image yang baik hanyalah separuh kebenaran Docker, karena image mendeskripsikan apa yang dijalankan, bukan bagaimana container menjalankannya. Section ini mengurus belahan kedua — seluruh knob runtime yang dibaca docker run pada saat container diciptakan, dari perintah start sampai siklus hidupnya. Knob pertama yang kita bedah bahkan bukan flag: segala argumen yang diketik setelah nama image secara diam-diam menggantikan perintah bawaan container. Budi menabrak kebutuhan ini begitu myapp mulai dipakai tim — ia ingin memeriksa versi Node.js yang terpasang di dalam image tanpa memasang apa pun di host, lalu menjalankan pekerjaan singkat yang selesai dalam hitungan detik memakai image yang sama persis.
Argumen Setelah Nama Image #
Bentuk lengkap docker run selama ini kita pakai tanpa dua bagian ekornya. Sintaks resminya adalah docker run [OPTIONS] IMAGE [COMMAND] [ARG...] — segala sesuatu yang diketik setelah nama image menjadi COMMAND beserta argumennya. Image myapp:1.0 membawa perintah bawaan CMD ["node", "server.js"] sejak dibangun pada Chapter Membangun Image dengan Dockerfile, dan perilaku CMD serta ENTRYPOINT sudah kita bedah tuntas pada Chapter CMD dan ENTRYPOINT. Bila COMMAND disebut saat docker run, daemon memakai COMMAND itu sebagai proses utama container dan mengabaikan CMD image sepenuhnya — hanya untuk container yang sedang diciptakan itu, tanpa menyentuh image aslinya.
Mari kita buktikan dengan menanyakan versi Node.js yang hidup di dalam image:
$ docker run --rm myapp:1.0 node --versionOutput yang Dihasilkan:
v22.20.0Mari kita telaah satu baris output di atas:
node --versionmenggantikannode server.js— daemon tidak menjalankan server HTTP myapp sama sekali; proses utama container kali ini adalahnodedengan argumen--version, yang mencetak versi lalu langsung selesai.v22.20.0— versi Node.js yang terpasang di dalam imagenode:22-alpine; angka mayor 22-lah yang dipatok tag, sedangkan angka minor dan patch mengikuti build basis yang tersimpan di mesinmu, jadi nilainya bisa berbeda di lingkungan lain.--rmmembuang bekasnya — perintah sekali jalan meninggalkan container berstatusExited (0)bila flag ini ditiadakan;--rmmembersihkan container begitu prosesnya selesai, kebiasaan yang kita bawa sejak Section Dasar Docker CLI.- Image tidak berubah — pemanggilan
docker run myapp:1.0berikutnya tanpa args kembali menjalankannode server.js; penimpaan menempel pada container, bukan pada image.
Bagaimana daemon memutuskan proses apa yang akhirnya dijalankan? Diagram berikut merangkum satu-satunya percabangan yang relevan:
Mari kita telaah jalur pada diagram di atas: cabang kiri berlaku untuk image yang hanya mendefinisikan CMD seperti myapp dan alpine, sedangkan cabang kanan mengurus image yang memasangkan ENTRYPOINT dengan CMD — keluarga besar image resmi seperti redis dan postgres. Kedua cabangnya kita bedah satu per satu sepanjang chapter ini.
Tanpa Shell, Tanpa Fitur Shell #
Args yang diketik setelah image dieksekusi langsung oleh daemon tanpa perantara shell. Konsekuensinya lurus: penggabungan perintah dengan &&, pipe, pengalihan berkas, dan penilaian variabel $VAR tidak bekerja, karena fitur-fitur itu milik shell, bukan milik proses. Perintah sh -c menghadirkan shell di dalam container kapan pun diperlukan — bentuk paling sederhananya menjalankan satu perintah di dalamnya:
$ docker run --rm myapp:1.0 sh -c "echo tes"Output yang Dihasilkan:
tesShell yang hadir lewat sh -c membawa seluruh fiturnya, dan perbedaannya paling terasa saat variabel ikut bermain. Mari kita bandingkan dua cara mencetak nilai HOME:
$ docker run --rm myapp:1.0 echo $HOMEOutput yang Dihasilkan:
/home/budi$ docker run --rm myapp:1.0 sh -c 'echo $HOME'Output yang Dihasilkan:
/rootMari kita telaah dua jawaban yang berbeda itu:
$HOMEpada perintah pertama diganti oleh shell host — sebelumdocker runmenerima argumen apa pun, shell di laptop Budi sudah mengganti$HOMEmenjadi/home/budi; container menerima args mentahecho /home/budidan mencetaknya apa adanya.- Kutip tunggal menunda penilaian sampai container — string
echo $HOMEsampai utuh keshdi dalam container, dan shell itulah yang menilai$HOMEmenjadi/root, direktori rumah root — user bawaan myapp:1.0 yang akan kita ganti pembahasannya pada Chapter User dan Permissions. sh -c "echo tes"bekerja dengan cara yang sama — bentuk kutip ganda sah selama tidak ada variabel yang ingin ditunda penilaiannya; kutip tunggal adalah kebiasaan yang lebih aman karena isinya tidak pernah disentuh shell host.
Pola Container Sekali Jalan #
Kemampuan menimpa perintah melahirkan pola yang sangat produktif: container one-shot — dinyalakan untuk satu pekerjaan, selesai, lalu dibuang. Tabel berikut memetakan kebutuhan yang paling sering muncul sehari-hari:
| Kebutuhan | Pola perintah | Alasannya |
|---|---|---|
| Memeriksa tool di dalam image | docker run –rm image tool –versi | versi tercetak tanpa memasang tool di host |
| Migrasi database | docker run –rm image-app perintah-migrasi | pekerjaan sekali jalan; jejak container dibersihkan |
| Skrip diagnosa atau laporan | docker run –rm image skrip.sh | hasil tercetak ke terminal, container langsung dibuang |
| Shell interaktif singkat | docker run -it image sh | menjelajah filesystem image sambil hidup |
Image alpine memberikan demo paling ringkas untuk pola ini. Argumen echo halo menimpa CMD bawaan alpine — yang merupakan sh — sehingga container mencetak sapaan lalu selesai:
$ docker run --rm alpine:3.20 echo haloOutput yang Dihasilkan:
haloTanpa args, container alpine menjalankan CMD aslinya dan berperilaku sangat berbeda:
$ docker run --rm alpine:3.20
$ echo "exit code: $?"Output yang Dihasilkan:
exit code: 0Mari kita telaah keheningan pada perintah pertama itu:
- CMD alpine adalah
sh— container menjalankan shell sebagai proses utama, tetapi tanpa flag-isaluran masuknya tertutup, sehinggashtidak menerima satu ketikan pun dan langsung mengakhiri dirinya. exit code: 0— kepergian yang bersih; proses utama selesai dengan sukses sehingga container berhenti normal, persis klasifikasi yang kita latih pada Chapter Memahami Exit Code.- Inilah sebabnya
docker run -it alpine shterasa hidup — flag-itmembuka masukan dan menyiapkan terminal semu, mengubah shell yang sama menjadi sesi interaktif:
$ docker run -it alpine:3.20 shOutput yang Dihasilkan:
/ # echo di dalam shell container
di dalam shell container
/ # exitPrompt / # adalah wajah busybox sh di Alpine. Perintah exit mengakhiri sh — proses utama container — sehingga container ikut berhenti; ini berbeda dari docker exec pada Chapter Menjalankan Perintah dalam Container yang menambahkan proses baru tanpa mengganggu proses utama container yang hidup.
Ketika Image Memakai ENTRYPOINT #
Image resmi besar umumnya memasangkan ENTRYPOINT dengan CMD, dan di sinilah miskonsepsi paling sering lahir: args setelah image tidak menggantikan ENTRYPOINT. Args tetap menggantikan CMD — tetapi karena ENTRYPOINT-lah yang dijalankan, args berubah peran menjadi parameter untuk ENTRYPOINT. Kita baca dulu konfigurasi image redis yang sudah tersimpan lokal sejak Section Dasar Docker CLI:
$ docker image inspect --format 'Entrypoint: {{.Config.Entrypoint}}' redis:7Output yang Dihasilkan:
Entrypoint: [docker-entrypoint.sh]$ docker image inspect --format 'Cmd: {{.Config.Cmd}}' redis:7Output yang Dihasilkan:
Cmd: [redis-server]Mari kita telaah konsekuensi kedua baris metadata itu:
- Tanpa args, container redis menjalankan
docker-entrypoint.sh redis-server— ENTRYPOINT menerima CMD sebagai parameter; skrip entrypoint menyiapkan berkas-berkas yang dibutuhkan, lalu menyerahkan kendali keredis-server. - Dengan args, CMD digantikan — perintah
docker run -d redis:7 redis-server --requirepass rahasia123membuat entrypoint menerima parameterredis-server --requirepass rahasia123; inilah cara resmi image redis dikonfigurasi kata sandinya, dan args-nya memang sengaja berbentuk perintah lengkap. - ENTRYPOINT tetap tak tersentuh — flag
--entrypointadalah satu-satunya cara menimpa ENTRYPOINT saat runtime, jarang dibutuhkan, dan pembahasan lengkapnya menunggu Chapter CMD dan ENTRYPOINT.
Dua wajah image berikut merangkum seluruh perilaku penimpaan:
| Bentuk image | Tanpa args | Dengan args setelah image | Contoh |
|---|---|---|---|
| CMD saja | CMD dijalankan sebagai proses utama | args menggantikan CMD sepenuhnya | myapp:1.0, alpine |
| ENTRYPOINT dan CMD | ENTRYPOINT dijalankan dengan CMD sebagai parameter | ENTRYPOINT tetap; args mengambil peran CMD sebagai parameter | redis:7, postgres, nginx |
Command override memberi kita kuasa mengubah apa yang dijalankan container untuk satu kali jalan. Kebutuhan yang jauh lebih sering muncul justru lebih halus: aplikasi yang sama harus berperilaku berbeda antar lingkungan tanpa satu baris kode pun berubah — mode production di server, mode uji dengan basis data lain di laptop Siti. Konfigurasi semacam itulah wilayah environment variable, knob runtime kedua yang kita bedah pada Chapter Environment Variable.
Referensi #
- docker container run — CLI Reference
— bentuk
IMAGE [COMMAND] [ARG...], flag--rm, dan--entrypoint. - Dockerfile Reference — interaksi CMD dan ENTRYPOINT saat image dijalankan dengan argumen runtime.
- docker image inspect — CLI Reference — membaca konfigurasi image tanpa menyalakan container.