Memperdalam siklus hidup kontainer: state machine Created, Running, Paused, Stopped, Exited, dan Dead beserta perintah pengendalinya; inspeksi metadata JSON dengan docker inspect dan jq, monitoring real-time dengan top, stats, events, serta makna exit code.

Setelah di episode 3 sebelumnya kita menjalankan kontainer pertama dan menguasai dasar-dasar CLI — docker run, ps, stop, start, rm, exec, logs, dan port mapping — pada episode kali ini kita masuk lebih dalam: memahami siklus hidup kontainer secara utuh dan cara mengelola state-nya.
Mengapa ini penting? Karena di dunia produksi, kontainer jarang "jalan dan selesai". Kontainer di-restart saat deployment, di-pause saat maintenance, crash dan restart-loop, atau menggantung dengan status yang tidak jelas. Engineer yang tidak paham state machine kontainer akan panik melihat kontainer Exited — padahal itu bisa jadi hal yang normal. Sebaliknya, engineer yang paham state bisa membaca satu baris docker ps dan langsung tahu kondisi sistem: kontainer mana yang berjalan, mana yang mengulang restart, dan mana yang benar-benar mati.
Episode 4 ini adalah jembatan dari "menjalankan kontainer" menuju "mengelola sistem produksi". Kita akan membedah state machine kontainer (Created, Running, Paused, Stopped, Exited, Dead, dan Restarting), perintah pengendali state (create, start, pause, unpause, restart, kill), inspeksi metadata JSON dengan docker inspect, monitoring real-time (top, stats, events), makna exit code, dan menutup dengan pembersihan sistem yang aman (system prune, system df).
Setiap kontainer selalu berada dalam salah satu state berikut. Pahami ini seperti peta: setiap perintah yang kalian jalankan adalah "perpindahan" dari satu titik ke titik lain.
create start
(no) ─────────► Created ───────────► Running
│ │
pause/ │ │ stop / (proses keluar)
unpause │ │
▼ ▼
Paused Stopped / Exited
│ │ rm
└──────────► (hilang)| State | Arti | Cara Masuk |
|---|---|---|
| Created | Konfigurasi tersimpan, proses belum berjalan | docker create |
| Running | Proses utama berjalan | docker start, docker run |
| Paused | Proses di-freeze (SIGSTOP), memori tetap | docker pause |
| Stopped / Exited | Proses berhenti, state + filesystem tetap | docker stop, proses keluar sendiri |
| Restarting | Sedang di-restart (crash loop) | restart policy / docker restart |
| Dead | Tidak bisa distop/dihapus normal; butuh intervensi | kondisi abnormal, proses hilang |
Perbedaan penting yang harus dicamkan:
docker ps menampilkan Exited untuk kontainer yang sudah berhenti. Bedanya halus: Stopped adalah state "resmi" hasil perintah stop, Exited adalah status akhir proses yang sudah selesai (baik disengaja maupun crash).STATUS PORTS NAMES
Up 3 minutes 0.0.0.0:8080->80 my-web
Exited (0) ... old-jobSemua perintah berikut hanya memindahkan state — tidak menciptakan image baru. Hafalkan transisinya:
docker create --name my-web nginx
docker ps -a --filter "status=created"docker create menyimpan seluruh konfigurasi kontainer (image, port, env, mount) tanpa menjalankan prosesnya. Berguna untuk menyiapkan kontainer di muka lalu menjalankannya di waktu yang tepat — dan untuk memeriksa konfigurasi sebelum dieksekusi.
docker start my-web
docker pause my-web
docker unpause my-web
docker restart my-webPerhatikan docker restart di baris terakhir — ini kombinasi stop + start dengan tenggang waktu SIGTERM. Sedangkan docker kill di bawah adalah kebalikan dari stop: ia langsung mengirim SIGKILL tanpa memberi proses kesempatan membersihkan diri:
docker kill my-webWarning
Pahami hierarki penghentian: docker stop mengirim SIGTERM (proses bisa menyimpan state, menutup koneksi dengan rapi) lalu SIGKILL setelah tenggang waktu; docker kill langsung mengirim SIGKILL (proses dihentikan paksa, tidak ada kesempatan membersihkan diri). Untuk database atau aplikasi yang menyimpan data, selalu utamakan stop — kill hanya untuk yang sudah tidak merespons.
State Restarting tadi sering membuat bingung: apakah itu state normal atau indikasi crash-loop? Jawabannya ada di restart policy — aturan yang menentukan apa yang dilakukan daemon saat kontainer berhenti. Aturan ini ditetapkan saat kontainer dibuat:
docker run -d --name my-web --restart always nginx
docker inspect my-web | jq '.[0].HostConfig.RestartPolicy'{
"Name": "always",
"MaximumRetryCount": 0
}| Policy | Perilaku | Kapan Dipakai |
|---|---|---|
no | (default) Tidak pernah di-restart otomatis | Job sekali jalan, eksperimen |
on-failure[:max] | Restart hanya jika exit code bukan 0, maksimal N kali | Service yang gagal sementara, hindari infinite loop |
unless-stopped | Restart otomatis, kecuali dihentikan manual oleh user | Layanan yang harus selalu jalan di host |
always | Selalu restart, termasuk setelah daemon restart | Layanan produksi yang wajib uptime |
Important
Ketika kalian melihat kontainer berstatus Restarting (atau Restarting (1) 5 seconds ago) di docker ps, itu berarti restart policy sedang bekerja karena proses utama keluar — biasanya karena crash. Ini bukan bug Docker, melainkan sinyal bahwa aplikasi gagal berulang. Jangan langsung menambah policy baru; baca dulu docker logs untuk mencari tahu kenapa aplikasi crash. Restart policy menahan pintu tetap terbuka — tapi pintu yang terbuka untuk aplikasi yang rusak hanyalah crash-loop yang tersamar.
docker inspect adalah pintu menuju seluruh metadata kontainer dalam bentuk JSON — inilah alat paling penting untuk memahami kondisi nyata sebuah kontainer:
docker inspect my-webOutput-nya panjang, jadi biasakan memfilter dengan jq (atau --format). Empat bidang yang paling sering dibaca:
docker inspect my-web | jq '.[0].Id'
docker inspect my-web | jq '.[0].State'
docker inspect my-web | jq '.[0].Config.Image'
docker inspect my-web | jq '.[0].Mounts'
docker inspect my-web | jq '.[0].NetworkSettings.IPAddress'{
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 12345,
"ExitCode": 0,
...
}| Bidang | Fungsi Diagnostik |
|---|---|
Id | ID penuh kontainer (bukan yang disingkat di ps) |
State | Status terkini: Running, Paused, Restarting, OOMKilled, Pid, ExitCode |
Config | Konfigurasi saat dibuat: image, Env, Cmd, Entrypoint, Hostname |
Mounts | Volume dan bind mount: Source, Destination, mode RW |
NetworkSettings | IP internal, port bindings, network yang dipakai |
Skenario khas: kontainer berhenti tanpa alasan jelas. docker inspect akan menjawab — apakah OOMKilled: true (kehabisan memori), ExitCode berapa, dan apa Error yang tercatat. Ini jauh lebih cepat daripada menebak.
Setiap kontainer berhenti dengan exit code — angka yang dicatat dari proses utamanya. Inilah "pesan terakhir" kontainer:
| Exit Code | Makna |
|---|---|
0 | Keluar normal, sukses |
1 | Error generik / aplikasi gagal |
2 | Salah penggunaan (usage error) — sering dari shell |
127 | Perintah tidak ditemukan (command not found) |
130 | Dihentikan oleh SIGINT (Ctrl+C) |
137 | SIGKILL — sering karena OOM (137 = 128 + 9) |
139 | Segmentation fault (128 + 11, SIGSEGV) |
docker run --name fail alpine sh -c "exit 1"
docker inspect fail | jq '.[0].State.ExitCode'
docker run --name oom-test -m 20m alpine sh -c "tail /dev/zero"Contoh terakhir di atas sengaja menjalankan kontainer yang memaksa OOM (membaca /dev/zero tanpa henti dengan limit memori 20 MB). Perhatikan exit code 137 — sinyal paling umum bahwa kontainer di-kill karena kehabisan memori. Belajar membaca exit code adalah keterampilan debugging pertama yang akan menyelamatkan kalian di produksi.
docker top my-webdocker top menampilkan proses yang sedang berjalan di dalam kontainer (dari perspektif host). Bandingkan dengan ps aux di host — kontainer nginx akan muncul sebagai proses nginx dengan user dan PID host.
docker statsdocker stats adalah dashboard live: kolom CPU %, memory usage/limit, network I/O, dan block I/O untuk semua kontainer aktif — diperbarui setiap beberapa detik. Alat wajib saat mencari tahu "kontainer mana yang makan memory".
docker eventsdocker events mengalirkan semua event daemon secara real-time: create, start, stop, die, restart, pause, kill, exec_start, dan lainnya. Jalankan ini di satu terminal, lalu coba docker run -d --rm alpine sleep 60 di terminal lain — kalian akan melihat event create, start, dan die mengalir. Ini alat observasi paling murni untuk mempelajari siklus hidup yang barusan kita bahas.
Tip
Untuk debugging crash-loop, kombinasi pamungkas: docker inspect <id> | jq '.[0].State.ExitCode' untuk status, docker logs <id> --tail 50 untuk pesan terakhir, dan docker stats untuk pola pemakaian resource sebelum crash. Ketiganya menjawab tiga pertanyaan: kenapa mati, apa yang dikatakan aplikasi, dan apa yang terjadi sebelumnya.
Kontainer, image, volume, dan network yang tidak terpakai akan menumpuk — dan memenuhi disk /var/lib/docker. Dua perintah berikut adalah "tukang bersih-bersih" kalian:
docker system dfdocker system df melaporkan berapa banyak disk yang dipakai image, kontainer, volume, dan build cache — plus kolom RECLAIMABLE (berapa yang bisa dibebaskan).
docker system prune
docker system prune -a
docker system prune -a --volumesPahami setiap opsi dengan hati-hati:
docker system prune — hapus kontainer berhenti, network yang tidak dipakai, image yang tergantung (dangling), dan build cache.-a (all) — selalu bertanya dulu dan menghapus semua image yang tidak dipakai kontainer aktif, bukan hanya yang dangling.--volumes — hapus volume yang tidak terpakai. Volume berisi data — perintah ini berbahaya untuk data yang tidak ter-backup.WARNING! This will remove all dangling images...
Are you sure you want to continue? [y/N]Warning
docker system prune -a --volumes adalah kombinasi paling destruktif — menghapus image yang tidak terpakai dan semua volume yang tidak dipakai, termasuk data database yang terlupakan. Sebelum menjalankan opsi ini di mesin produksi, pastikan (1) tidak ada kontainer berhenti yang masih kalian butuhkan, dan (2) volume yang tidak terpakai benar-benar aman dibuang. Saat ragu: jalankan tanpa --volumes, atau backup dulu.
Menganggap Exited selalu error. Kontainer hello-world yang Exited (0) adalah perilaku normal. Baca exit code-nya sebelum panik — 0 berarti selesai dengan sukses.
docker rm kontainer yang masih berjalan. Error "cannot remove running container". Hentikan dulu (stop) atau gunakan -f secara sadar.
Tidak membaca State.Error saat crash. docker inspect berisi pesan error dalam JSON — sering kali jawaban sudah ada di sana sebelum kalian menebak-nebak.
Melewatkan docker system df. Disk penuh di server Docker biasanya bukan karena image yang dipakai, tapi karena build cache dan kontainer/image menganggur yang menumpuk. Audit rutin dengan system df mencegah krisis disk.
Menjalankan system prune -a --volumes tanpa berpikir. Data yang tidak ter-backup bisa hilang permanen. Selalu konfirmasi apa yang akan dihapus.
Pada episode 4 ini kalian telah memperdalam pemahaman siklus hidup kontainer: state machine dari Created → Running → Paused → Stopped/Exited → Dead (plus Restarting), perintah pengendali state (create, start, pause, unpause, restart, kill), pembacaan metadata JSON dengan docker inspect dan jq (bidang State, Config, Mounts, NetworkSettings), monitoring real-time dengan docker top, docker stats, dan docker events, pemahaman makna exit code (terutama 137 untuk OOM), serta pembersihan sistem dengan docker system df dan docker system prune beserta bahaya opsi -a --volumes.
Inti yang harus kalian bawa:
pause membekukan proses; stop (SIGTERM) berhenti dengan rapi; kill (SIGKILL) memaksa berhenti.docker inspect + jq adalah mata kalian — State.ExitCode, OOMKilled, dan State.Error menjawab kenapa kontainer mati.137 = di-kill (sering OOM); 0 = selesai normal — baca sebelum panik.system df untuk audit disk; system prune untuk bersih-bersih; hati-hati dengan --volumes.Sekarang kalian tidak lagi sekadar "menjalankan kontainer" — kalian mengelola siklus hidupnya. Di episode 5 selanjutnya kita akan naik satu level: membuat image custom menggunakan Dockerfile — memahami konsep layered architecture dan build context, instruksi inti FROM, WORKDIR, COPY vs ADD, RUN, EXPOSE, serta perbedaan mendasar CMD vs ENTRYPOINT yang akan mengubah cara kalian mengemas aplikasi sendiri. Sampai jumpa di episode 5!