docker stats pada Chapter Docker Stats mengukur denyut — tetapi angka yang berdenyut tidak pernah bercerita tentang sebab. Ketika cache mati mendadak, ketika worker dibangkitkan entah oleh siapa, ketika container diciptakan ulang di sela rapat singkat, semua kejadian itu lewat tanpa meninggalkan satu baris pun di tabel stats maupun di log aplikasi. Daemon sesungguhnya mencatat setiap kejadiannya sendiri — lahir, mati, dibekukan, dihapus, di-pin, ganti health — dalam satu aliran bernama docker events, dan chapter ini mengajak kita berlangganan langsung: menyaksikan kejadian lahir di layar detik demi detik, membedah anatomi satu barisnya, menyaring arus yang riuh, lalu membaca ke belakang untuk menyusun kronologi insiden.
Langganan Langsung ke Kronik Daemon #
docker events tanpa argumen adalah langganan langsung: terminal duduk tenang menunggu, dan setiap kejadian yang menimpa objek Docker di mesin ini akan tercetak seketika. Kita butuh dua terminal — terminal pertama menjadi penonton, terminal kedua menjadi aktor:
$ docker eventsTerminal pertama diam; tidak ada keluaran apa pun karena memang belum ada yang terjadi. Dari terminal kedua, kita hentikan cache stack toko dengan jalur sopan yang sudah kita kenal:
$ docker compose stop cacheOutput yang Dihasilkan (terminal kedua):
[+] Running 1/1
✔ Container toko-cache-1 Stopped 1.1sBaris ramping itu adalah versi Compose; kronik lengkapnya tercetak di terminal pertama:
2026-10-13T07:58:24.512401337+07:00 container kill 69bebb2487a6e28d27688b69f1241d4395da278739f691bc3efff7774ab2e32a (image=redis:7-alpine, name=toko-cache-1, signal=15)
2026-10-13T07:58:24.613547882+07:00 container die 69bebb2487a6e28d27688b69f1241d4395da278739f691bc3efff7774ab2e32a (image=redis:7-alpine, name=toko-cache-1, exitCode=0)
2026-10-13T07:58:24.704891245+07:00 container stop 69bebb2487a6e28d27688b69f1241d4395da278739f691bc3efff7774ab2e32a (image=redis:7-alpine, name=toko-cache-1)Mari kita telaah tiga kejadian yang lahir dari satu perintah stop:
killdengansignal=15—docker compose stoppada akhirnya menjalankandocker stop, dan ritualnya dimulai denganSIGTERM(sinyal 15) yang dikirim ke PID 1; nama kejadiannyakill, tetapi atributsignal=15menegaskan ini jalur sopan, bukandocker killyang mengirim sinyal 9.diedenganexitCode=0— Redis menangkap SIGTERM dan menutup dirinya dengan rapi; exit code 0 pada kejadian mati adalah tanda kematian paling terhormat, persis perilaku yang kita rancang pada Chapter Graceful Shutdown.stop— penutup resmi ritual: daemon menuntaskan penghentian sebelum masa tenggang 10 detik terpakai, karena prosesnya memang sudah keluar sendiri seratus milidetik setelah SIGTERM.
Kita bangunkan kembali cache dari terminal kedua:
$ docker compose start cacheOutput yang Dihasilkan (terminal kedua):
[+] Running 1/1
✔ Container toko-cache-1 Started 0.8sTerminal pertama menyambut dua kejadian:
2026-10-13T07:58:51.310294716+07:00 container start 69bebb2487a6e28d27688b69f1241d4395da278739f691bc3efff7774ab2e32a (image=redis:7-alpine, name=toko-cache-1)
2026-10-13T07:59:01.845120331+07:00 container health_status: healthy 69bebb2487a6e28d27688b69f1241d4395da278739f691bc3efff7774ab2e32a (image=redis:7-alpine, name=toko-cache-1)Dua baris penutup itu menyimpan dua pelajaran: start membawa ID yang sama persis — container yang dibangunkan adalah container yang sama, bukan ciptaan baru; dan health_status: healthy muncul sepuluh detik kemudian karena probe redis-cli ping akhirnya lulus — kejadian yang lahir bukan dari hidup-matinya proses, melainkan dari penilaian kesehatan yang kita tanam di compose.yaml.
Anatomi Satu Baris Event #
Satu baris kronik padat berisi lima unsur, dan membedahnya sekali membuat kita bisa membaca baris mana pun selamanya. Mari kita gunakan baris pertama tadi sebagai spesimen:
- Waktu kejadian —
2026-10-13T07:58:24.512401337+07:00: tanggal, jam dengan presisi nanodetik, dan zona waktu mesin kita — WIB, tujuh jam di depan UTC. - Jenis objek —
container: kejadian menimpa container; jenis lain yang mungkin adalahimage,network,volume, hinggadaemonitu sendiri. - Aksi —
kill: kata kerja kejadian; daftar katanya panjang, daricreate,start,stop,die,oom, sampaihealth_status. - ID penuh — 64 karakter heksadesimal, bukan bentuk pendek 12 seperti di
docker ps; inilah penghubung kedocker inspectdandocker logspada chapter-chapter sebelumnya. - Atribut dalam kurung — kamus
kunci=nilaiyang menemani aksi:killmembawasignal,diemembawaexitCode, semuanya membawaimagedanname; atribut inilah yang membuat satu baris kronik bisa dibaca tanpa menyalakan perintah lain.
Menyaring Arus dengan Filter #
Aliran penuh docker events riuh pada mesin yang sibuk — build, pull, network, volume, semuanya bicara bersamaan. Flag --filter menyempitkannya, dan beberapa penyaring paling berguna dirangkum di tabel berikut:
| Filter | Menyaring berdasarkan | Contoh pemakaian |
|---|---|---|
type=container | jenis objek kejadian | docker events --filter type=container |
event=die | nama aksi secara persis | docker events --filter event=die |
container=toko-backend-1 | satu objek tertentu | docker events --filter container=toko-backend-1 |
Penyaring boleh dirangkai — docker events --filter type=container --filter event=die hanya menampilkan kejadian die milik container — dan setiap penyaring tambahan mempersempit hasil dengan logika DAN. Penyaring objek juga menerima nama image, memberi kita cara mengawasi seluruh container yang lahir dari satu image.
Menoleh ke Belakang dengan –since dan –until #
Semua demo sejauh ini bersifat langganan: kita harus sedang menonton ketika kejadian terjadi. Padahal kebutuhan diagnosis yang paling sering justru menoleh ke belakang — “apa yang terjadi sepuluh menit terakhir?”. Pasangan --since dan --until mengubah perintah menjadi mode historis. Kita tekan Ctrl-C pada langganan tadi, lalu membaca ulang pagi ini:
$ docker events --since 10m --until 0sOutput yang Dihasilkan (dipotong):
2026-10-13T07:58:24.512401337+07:00 container kill 69bebb2487a6e28d27688b69f1241d4395da278739f691bc3efff7774ab2e32a (image=redis:7-alpine, name=toko-cache-1, signal=15)
2026-10-13T07:58:24.613547882+07:00 container die 69bebb2487a6e28d27688b69f1241d4395da278739f691bc3efff7774ab2e32a (image=redis:7-alpine, name=toko-cache-1, exitCode=0)
...
2026-10-13T07:59:01.845120331+07:00 container health_status: healthy 69bebb2487a6e28d27688b69f1241d4395da278739f691bc3efff7774ab2e32a (image=redis:7-alpine, name=toko-cache-1)Perintah ini berhenti dengan sendirinya — berbeda dari mode langganan: --since 10m membuka jendela sepuluh menit ke belakang, --until 0s menutup jendela tepat di detik sekarang (nol detik dari masa kini), dan setelah buffer dicetak, prompt kembali. Nilai keduanya juga menerima durasi lain seperti 1h atau timestamp mutlak, sama seperti --since milik docker logs.
Kasus Riil: Worker yang Terbunuh OOM #
Kekuatan kronik paling terasa pada kejadian yang tidak meninggalkan pesan perpisahan. Kita pinjam resep eksperimen lapar dari Chapter *CPU dan Memory Limit`: pekerja yang haus memori, kurungan yang lebih kecil dari nafsunya — kali ini sebagai container latar belakang dengan kebijakan bangkit tanpa henti. Kita hidupkan kembali langganan di terminal pertama, lalu dari terminal kedua:
$ docker run -d --name uji-worker --restart always -m 100m polinux/stress --vm 1 --vm-bytes 150M --vm-hang 0Output yang Dihasilkan:
009404942603e981671d310b53edc921d625062810e6e5459d1c4754e6d6c7a1Pekerja diminta mengalokasikan 150 MB di dalam kurungan 100 MB; nasibnya tinggal soal waktu. Terminal pertama mencatat tiga baris yang menceritakan satu putaran hidup:
2026-10-13T08:12:41.104512312+07:00 container oom 009404942603e981671d310b53edc921d625062810e6e5459d1c4754e6d6c7a1 (image=polinux/stress, name=uji-worker)
2026-10-13T08:12:41.918044293+07:00 container die 009404942603e981671d310b53edc921d625062810e6e5459d1c4754e6d6c7a1 (image=polinux/stress, name=uji-worker, exitCode=137)
2026-10-13T08:12:48.240193852+07:00 container start 009404942603e981671d310b53edc921d625062810e6e5459d1c4754e6d6c7a1 (image=polinux/stress, name=uji-worker)Mari kita telaah drama tiga babak itu:
oom— kernel menyatakan cgroup uji-worker kehabisan memori dan algojonya bekerja; pekerja berhasil mengalokasikan kira-kira 100 MB sebelum langit-langit cgroups menutup pintu.diedenganexitCode=137— 137 adalah 128 ditambah 9: proses dijatuhkanSIGKILL, sinyal yang tidak bisa ditangkap siapa pun, sehingga tidak ada satu baris log perpisahan pun didocker logs; angka ini adalah seluruh pesan yang ditinggalkan.startenam detik kemudian — kebijakan--restart alwaysmembangkitkan container dari kematian; jeda backoff yang dimulai 100 milidetik dan berlipat ganda pada setiap percobaan kini telah tumbuh menjadi sekitar enam detik — artinya uji-worker sudah berputar beberapa putaran sebelum kita mulai menonton. Putaran berikutnya sudah tertulis di nasibnya: bangkit, lapar, terbunuh, berulang — crash loop yang akan kita jinakkan pada Chapter Mengatasi Container Crash.
Kronik yang lengkap itu kita tutup dengan membersihkan korban percobaan:
$ docker rm -f uji-workerOutput yang Dihasilkan:
uji-workerTrio Diagnosis dan Waktu dalam Angka #
Untuk berkas catatan insiden, format bawaan events terlalu bertele-tele. Template --format — kosakata Go template yang sama dengan dua chapter sebelumnya — meringkasnya menjadi kolom pilihan kita:
$ docker events --since 30m --until 0s --format '{{.Time}} {{.Action}} {{.Actor.Attributes.name}}'Output yang Dihasilkan (dipotong):
1791853104 kill toko-cache-1
1791853104 die toko-cache-1
1791853104 stop toko-cache-1
1791853131 start toko-cache-1
1791853141 health_status: healthy toko-cache-1
...
1791853961 oom uji-worker
1791853961 die uji-worker
1791853968 start uji-workerMari kita telaah bentuk waktu barunya: {{.Time}} mencetak kejadian sebagai detik Unix — jumlah detik sejak 1 Januari 1970 UTC. Angka 1791853104 itu dapat kita urai: dalam UTC ia jatuh pada 2026-10-13T00:58:24Z, dan karena mesin kita berada tujuh jam di depan, momen kejadian adalah pukul 07:58:24 WIB — persis stempel baris kill yang kita baca di awal chapter. Tiga kejadian pertama berbagi angka yang sama karena lahir pada detik yang sama; presisi nanodetik dan zona waktu hilang demi bentuk yang ringkas, mudah diurutkan, dan mudah dihitung selisihnya — 1791853968 dikurangi 1791853961 langsung memberi kita jeda bangkit uji-worker tujuh detik secara kasar, tanpa kalkulator waktu.
Kronik daemon kini terbaca lancar dua arah — langsung saat kejadian dan ke belakang sesudahnya. Namun di antara semua aksi yang kita saksikan hari ini, satu baris menonjol karena sumbernya yang unik: health_status: healthy tidak lahir dari proses yang hidup atau mati, melainkan dari probe yang menilai. Siapa yang menilai, bagaimana siklus penilaiannya, dan — yang paling penting — apa yang Docker lakukan ketika putusannya buruk, adalah kisah Chapter Container Health.
Referensi #
- docker events — referensi resmi seluruh filter, format waktu, dan mode historis.
- docker compose stop — ritual penghentian service beserta masa tenggangnya.
- docker compose start — membangunkan kembali service yang berhenti.