Menjalankan Container

Menjalankan Container

Bitnesia • Sep 8, 2026 82 •EN

Setelah punya image yang siap pakai, baik hasil docker pull maupun hasil build sendiri, langkah berikutnya adalah menjalankannya menjadi container yang benar-benar hidup. Bab ini membahas perintah docker run secara menyeluruh: dari sintaks dasar, opsi-opsi penting seperti port, volume, dan environment variable, sampai perbedaan menjalankan container di mode background versus mode interaktif. Developer yang butuh menyalakan database lokal untuk development sehari-hari dan Sysadmin/DevOps Engineer yang men-deploy service ke server production sama-sama bertumpu pada pemahaman docker run yang solid, karena hampir semua opsi yang dipelajari di sini akan terus dipakai berulang-ulang di bab-bab selanjutnya.

7.1 Docker Run Command

Perintah docker run adalah cara paling umum untuk membuat sekaligus menjalankan container baru dari sebuah image. Di balik layar, perintah ini sebenarnya gabungan dua langkah: Docker membuat container baru dari image yang ditentukan (setara docker create), lalu langsung menyalakannya (setara docker start). Sintaks dasarnya sederhana.

docker run [OPSI] IMAGE [PERINTAH] [ARGUMEN...]

Coba jalankan container pertama dari image alpine, distro Linux minimalis yang sering dipakai untuk latihan dan testing karena ukurannya kecil.

docker run alpine:3.20 echo "Halo dari container"

Docker menampilkan output Halo dari container lalu container langsung berhenti. Ini perilaku normal: begitu proses utama di dalam container (dalam contoh ini perintah echo) selesai dijalankan, container ikut berhenti karena tidak ada lagi proses yang membuatnya tetap hidup. Kalau image alpine:3.20 belum ada di mesin lokal, Docker otomatis menariknya dari registry lebih dulu sebelum menjalankan container, persis seperti menjalankan docker pull secara implisit. Perhatikan contoh di atas sengaja mencantumkan tag versi 3.20 secara eksplisit, bukan mengandalkan tag latest secara default, seperti dibahas di bab tentang image naming dan tagging.

Setiap container yang dijalankan mendapat container ID unik dan bisa diberi nama yang mudah diingat lewat opsi --name. Tanpa opsi ini, Docker membuatkan nama acak dua kata secara otomatis (misalnya happy_lovelace), yang cukup merepotkan saat harus dirujuk berulang kali di perintah lain.

docker run --name demo-alpine alpine:3.20 echo "Container dengan nama"

Nama container harus unik di satu mesin Docker; mencoba membuat container baru dengan nama yang sudah dipakai container lain (termasuk yang sudah berhenti tapi belum dihapus) akan ditolak. Coba jalankan ulang perintah yang sama persis.

docker run --name demo-alpine alpine:3.20 echo "Percobaan kedua"

Docker menampilkan error docker: Error response from daemon: Conflict. The container name "/demo-alpine" is already in use by container "<container_id>". You have to remove (or rename) that container to be able to reuse that name. Pesan ini jelas menandakan nama container harus bebas duplikat; hapus dulu container lama lewat docker rm atau pakai nama lain sebelum mencoba lagi.

Cek daftar container yang pernah dibuat, termasuk yang sudah berhenti, lewat opsi -a pada docker ps.

docker ps -a
CONTAINER ID   IMAGE     COMMAND                  STATUS                     NAMES
3f9a1c2b4d5e   alpine:3.20   "echo 'Container de…"   Exited (0) 5 seconds ago  demo-alpine

Container yang sudah berhenti seperti demo-alpine di atas tidak otomatis hilang; ia tetap tersimpan di mesin kita beserta seluruh filesystem-nya sampai dihapus secara manual. Kalau kita hanya butuh container untuk keperluan sekali pakai, misalnya menjalankan perintah singkat untuk testing, opsi --rm membuat Docker langsung menghapus container begitu ia berhenti, supaya tidak menyisakan sampah container yang menumpuk.

docker run --rm alpine:3.20 echo "Container sekali pakai"

Jalankan docker ps -a lagi setelah perintah di atas; container barusan tidak akan muncul di daftar karena sudah otomatis dibersihkan. Di lapangan, kombinasi --rm ini jadi kebiasaan standar Sysadmin/DevOps Engineer saat menjalankan container untuk keperluan diagnostik atau testing cepat, supaya server tidak dipenuhi container mati yang lupa dibersihkan.

Bersihkan container contoh yang masih tersisa sebelum lanjut ke sub-bab berikutnya.

docker rm demo-alpine

7.2 Container Options

docker run menerima banyak opsi untuk mengatur bagaimana container berinteraksi dengan dunia luar. Tiga yang paling sering dipakai sehari-hari adalah pemetaan port, mount volume, dan environment variable.

7.2.1 Opsi Port dengan -p

Opsi -p (atau --publish) memetakan port di host ke port di dalam container, memakai format HOST_PORT:CONTAINER_PORT. Tarik dan jalankan image nginx sebagai contoh web server sederhana.

docker run -d --name demo-nginx -p 8080:80 nginx:1.27

Perintah di atas memetakan port 8080 di mesin host ke port 80 di dalam container, port default yang dipakai nginx. Akses http://localhost:8080 lewat browser atau curl untuk memastikan web server-nya benar-benar bisa dijangkau dari luar container.

curl -I http://localhost:8080

Response HTTP/1.1 200 OK menandakan port sudah terpetakan dengan benar dan nginx merespons normal.

Kesalahan yang paling sering ditemui di sub-bab ini adalah mencoba memetakan ke port host yang sudah dipakai container lain. Coba jalankan container kedua dengan port host yang sama persis.

docker run -d --name demo-nginx-2 -p 8080:80 nginx:1.27

Docker menolak dan menampilkan error Error response from daemon: driver failed programming external connectivity on endpoint demo-nginx-2 (<endpoint_id>): Bind for 0.0.0.0:8080 failed: port is already allocated. Satu port host hanya bisa dipetakan ke satu container pada satu waktu; solusinya, pakai port host yang berbeda atau hentikan dulu container yang sedang memakainya. Meski gagal start, container demo-nginx-2 tetap tercatat di mesin kita dalam status berhenti, jadi jangan lupa dihapus supaya tidak salah paham sebagai container yang aktif.

docker rm demo-nginx-2

7.2.2 Opsi Volume dengan -v

Opsi -v (atau --volume) menghubungkan direktori di host atau named volume ke dalam filesystem container, supaya data yang ditulis container tidak ikut hilang saat container dihapus. Detail lengkap soal jenis-jenis volume dan bind mount dibahas tuntas di bab tersendiri; di sini kita fokus ke sintaks dasarnya saat dipakai bersama docker run.

docker run -d --name demo-nginx-vol -p 8081:80 -v nginx-data:/usr/share/nginx/html nginx:1.27

Perintah di atas membuat (atau memakai ulang bila sudah ada) named volume bernama nginx-data dan menghubungkannya ke direktori /usr/share/nginx/html di dalam container, tempat nginx menyimpan file HTML yang disajikan.

Pastikan volume-nya benar-benar terbuat lewat docker volume ls.

docker volume ls
DRIVER    VOLUME NAME
local     nginx-data

Volume nginx-data di atas tetap tersimpan meski container demo-nginx-vol dihapus nanti; ini yang membedakannya dari filesystem container biasa yang ikut lenyap saat container-nya dihapus.

7.2.3 Opsi Environment Variable dengan -e

Opsi -e (atau --env) menyuntikkan environment variable ke dalam container saat dijalankan, berguna untuk mengatur konfigurasi tanpa perlu membuat ulang image. Coba dengan image mysql, yang mensyaratkan environment variable tertentu supaya bisa menyala.

docker run -d --name demo-mysql -e MYSQL_ROOT_PASSWORD=contoh_password_123 mysql:8.4

Environment variable MYSQL_ROOT_PASSWORD di atas dibaca oleh skrip inisialisasi di dalam image mysql saat container pertama kali dijalankan, untuk mengatur password akun root MySQL. Pastikan environment variable-nya sudah tersimpan benar lewat docker inspect.

docker inspect --format '{{.Config.Env}}' demo-mysql

Output-nya menampilkan seluruh environment variable milik container, termasuk MYSQL_ROOT_PASSWORD=contoh_password_123 yang barusan disuntikkan lewat -e, di antara environment variable bawaan image seperti PATH.

Untuk environment variable yang jumlahnya banyak, opsi --env-file lebih praktis karena membaca daftar variable dari sebuah file, satu pasangan KEY=VALUE per baris, alih-alih menulis banyak -e berulang di satu baris perintah. Buat dulu file mysql.env berisi baris berikut.

MYSQL_ROOT_PASSWORD=contoh_password_123
docker run -d --name demo-mysql-file --env-file ./mysql.env mysql:8.4

Di lapangan, hindari menulis password atau kredensial sensitif langsung di baris perintah lewat -e, karena nilainya bisa terekam di shell history atau terlihat lewat docker inspect oleh siapa pun yang punya akses ke mesin tersebut. Untuk kredensial di lingkungan production, pertimbangkan mekanisme secrets management yang lebih aman ketimbang environment variable biasa.

Bersihkan seluruh container contoh di sub-bab ini sebelum lanjut.

docker rm -f demo-nginx demo-nginx-vol demo-mysql demo-mysql-file
docker volume rm nginx-data

7.3 Detached vs Interactive Mode

Docker menyediakan dua cara utama menjalankan container tergantung kebutuhan: berjalan di latar belakang tanpa mengunci terminal, atau berjalan secara interaktif dengan sesi yang bisa langsung diketik.

7.3.1 Detached Mode dengan -d

Opsi -d (atau --detach) menjalankan container di latar belakang. Terminal langsung kembali ke prompt setelah menampilkan container ID, tanpa menunggu proses di dalam container selesai. Mode ini adalah pilihan default untuk service jangka panjang seperti web server atau database, yang memang dirancang untuk terus menyala tanpa campur tangan lebih lanjut.

docker run -d --name web-service nginx:1.27
7f8e9d0c1b2a3f4e5d6c7b8a9f0e1d2c3b4a5968...

Container web-service terus berjalan di background meski terminal dipakai untuk perintah lain. Cek statusnya kapan saja lewat docker ps.

docker ps

7.3.2 Interactive Mode dengan -it

Untuk kebutuhan yang berbeda, misalnya masuk langsung ke dalam shell container untuk eksplorasi atau debugging, kita butuh sesi interaktif. Kombinasi opsi -i (--interactive, menjaga STDIN tetap terbuka) dan -t (--tty, mengalokasikan pseudo-terminal) biasa ditulis bersamaan sebagai -it.

docker run -it --name demo-shell alpine:3.20 sh

Perintah di atas langsung membuka sesi shell sh di dalam container alpine, dan prompt terminal berubah menandakan kita sekarang "berada" di dalam container tersebut. Coba jalankan beberapa perintah dasar untuk memastikan sesi interaktif ini benar-benar berfungsi.

ls /
cat /etc/os-release
exit

Perintah exit mengakhiri sesi shell sekaligus menghentikan container, karena proses sh yang tadi dijalankan adalah satu-satunya proses utama container. Tanpa opsi -t, terminal memang tetap bisa mengirim perintah lewat STDIN, tapi tampilan prompt dan pemformatan output jadi kacau karena tidak ada pseudo-terminal yang mengatur tampilannya; tanpa opsi -i, STDIN langsung tertutup sehingga sesi shell tidak bisa menerima input sama sekali dan container langsung berhenti begitu dijalankan.

Di lapangan, Sysadmin/DevOps Engineer yang menjalankan docker run -it lewat skrip otomatis atau pipeline CI/CD sering menemui error the input device is not a TTY. Ini terjadi karena opsi -t butuh terminal asli yang terhubung ke STDIN dan STDOUT, sesuatu yang tidak tersedia saat perintah dijalankan lewat proses non-interaktif seperti runner CI. Solusinya, hilangkan opsi -t (cukup pakai -i saja) untuk skenario otomatis semacam ini, dan simpan kombinasi -it khusus untuk sesi yang memang dijalankan manual dari terminal.

Developer yang perlu masuk ke shell container yang sudah berjalan (bukan membuat container baru) memakai perintah berbeda, docker exec, yang dibahas lebih dalam di bab tentang interaksi dengan container. Bersihkan container contoh di sub-bab ini.

docker rm -f web-service demo-shell

7.4 Port Mapping dan Expose

Docker membedakan dua konsep yang sering tertukar: expose dan publish. Memahami perbedaan keduanya penting supaya konfigurasi jaringan container tidak salah asumsi, terutama saat container harus diakses dari luar mesin host.

Instruksi EXPOSE di dalam Dockerfile hanya berfungsi sebagai dokumentasi antara pembuat image dan pengguna image, menandakan port mana yang secara desain dipakai aplikasi di dalam container. Instruksi ini tidak membuat port tersebut bisa diakses dari luar container; ia sekadar metadata yang tercatat di image. Opsi --expose pada docker run punya efek serupa, menambahkan port yang "diekspos" saat container dijalankan tanpa benar-benar mempublikasikannya ke host.

docker run -d --name demo-expose --expose 9000 alpine:3.20 sleep 3600

Yang benar-benar membuat port bisa diakses dari luar container adalah publish, lewat opsi -p yang sudah dibahas di sub-bab sebelumnya. Opsi -P (huruf kapital, --publish-all) adalah jalan pintas untuk mempublikasikan seluruh port yang sudah ditandai EXPOSE di image atau lewat --expose, masing-masing dipetakan ke port acak yang tersedia di host.

docker run -d --name demo-nginx-random -P nginx:1.27

Cek port hasil pemetaan acak tersebut lewat docker port.

docker port demo-nginx-random
80/tcp -> 0.0.0.0:32768
80/tcp -> [::]:32768

Untuk pemetaan port yang presisi dan bisa diprediksi, seperti dibutuhkan di lingkungan production, opsi -p dengan port host yang ditentukan secara eksplisit tetap jadi pilihan yang lebih terkontrol dibanding -P. Opsi -p juga bisa memetakan hanya ke localhost host, bukan seluruh interface jaringan, dengan menambahkan alamat IP di depan pemetaan port.

docker run -d --name demo-nginx-local -p 127.0.0.1:8082:80 nginx:1.27

Container di atas hanya bisa diakses dari mesin host itu sendiri lewat 127.0.0.1:8082, tidak dari mesin lain di jaringan yang sama, sekalipun keduanya satu subnet. Pola ini berguna untuk service internal yang sengaja tidak boleh diakses langsung dari luar, misalnya database yang hanya perlu dijangkau oleh container lain lewat jaringan Docker internal.

Secara default, -p memetakan port sebagai protokol TCP. Untuk protokol UDP, tambahkan akhiran /udp secara eksplisit pada bagian port container.

docker run -d --name demo-udp -p 5353:53/udp alpine:3.20 sleep 3600

Sysadmin/DevOps Engineer yang lupa membedakan expose dan publish sering terjebak asumsi bahwa menulis EXPOSE 80 di Dockerfile sudah cukup membuat aplikasi bisa diakses dari luar container, padahal tanpa opsi -p saat docker run, port itu tetap tertutup rapat dari luar. Selalu verifikasi pemetaan port yang aktif lewat docker port <nama_container> atau kolom PORTS pada docker ps sebelum menganggap sebuah service sudah bisa diakses.

docker ps --format "table {{.Names}}\t{{.Ports}}"

Bersihkan seluruh container contoh yang dipakai sepanjang bab ini.

docker rm -f demo-expose demo-nginx-random demo-nginx-local demo-udp
OpsiFungsi
--nameMemberi nama yang mudah diingat pada container
--rmMenghapus container otomatis begitu berhenti
-p HOST:CONTAINERMemublikasikan port container ke port tertentu di host
-PMemublikasikan seluruh exposed port ke port acak di host
--exposeMenandai port sebagai exposed tanpa memublikasikannya
-vMenghubungkan volume atau bind mount ke container
-eMenyuntikkan environment variable ke container
-dMenjalankan container di background (detached)
-itMenjalankan container secara interaktif dengan pseudo-terminal