Satu per satu knob konfigurasi telah kita pasang sepanjang section ini — perintah, environment, identitas, port, direktori kerja, kebijakan bangkit, batas resource, hingga tata kelola sinyal PID 1 — dan di setiap chapter kita berpapasan dengan kejadian-kejadian yang sama: container lahir, berjalan, kadang dibekukan, lalu berhenti atau dihapus. Chapter penutup section ini menarik mundur kamera sampai seluruh kejadian itu muat dalam satu bingkai: peta lengkap state yang bisa dihuni sebuah container, perintah mana yang memindahkannya dari satu state ke state lain, dan bagaimana membaca posinya dari luar lewat docker ps dan docker inspect. Mesin kita bersih dari container setelah chapter sebelumnya, jadi kita akan menghuni peta itu satu per satu dengan satu penumpang bernama siklus — dari diciptakan sampai tidak lagi bisa ditemukan.

Peta Lima State Container #

Sebuah container hidup dalam tepat lima keadaan besar. Diagram berikut memetakan kelimanya beserta perintah yang menjadi jalan transisinya:

Mari kita telaah tiap jalan pada peta di atas:

  1. [*] menuju Created lewat docker create — penciptaan menyiapkan segalanya kecuali kehidupan: writable layer disiapkan, konfigurasi tersimpan, nama terdaftar, tetapi PID 1 belum pernah lahir.
  2. Created menuju Running lewat docker start — proses utama dinyalakan; inilah momen namespace, cgroups, dan jaringan benar-benar dihuni oleh proses.
  3. Running dan Paused bolak-balik lewat pause dan unpause — pembekukan memakai freezer cgroup, sehingga proses tetap hidup di memori tanpa mendapat setitik waktu CPU.
  4. Running menuju Exited lewat stop atau kill — dua jalur yang sudah kita bandingkan tuntas pada Chapter *Menghentikan dan Menjalankan Container: sopan dengan SIGTERMlalu masa tenggang, atau seketika denganSIGKILL`.
  5. Exited menuju Running lewat docker start — kebangkitan manual; bila kebangkitannya diserahkan kepada daemon, kita sudah tahu pilihan kebijakannya dari Chapter Restart Policy.
  6. Tiga pintu menuju Removed — container yang dibangun saja maupun yang sudah berhenti dihapus lewat docker rm; container yang masih berjalan harus dihapus paksa lewat docker rm -f.
  7. Removed menuju [*] tanpa jalan pulang — penghapusan bersifat final: nama, konfigurasi, dan writable layer lenyap bersamaannya.

Membangun Tanpa Menjalankan #

Perintah docker create adalah bagian dari docker run yang selama ini bekerja diam-diam. docker run sebenarnya menjalankan dua langkah berurutan — menciptakan container, lalu langsung menyalakannya — dan pemisahan itu sempat kita janjikan sejak Chapter Menjalankan Container Pertama. Kini kita jalankan paruh pertamanya sendiri:

bash
$ docker create --name siklus nginx

Output yang Dihasilkan:

text
468fa01723fb92a2e080be487d8df9a66aabf72b83993c9170fb5edc7c93bc05
bash
$ docker ps -a

Output yang Dihasilkan:

text
CONTAINER ID   IMAGE   COMMAND                  CREATED         STATUS    PORTS   NAMES
468fa01723fb   nginx   "/docker-entrypoint.…"   3 seconds ago   Created           siklus
bash
$ docker inspect --format '{{.State.Status}}' siklus

Output yang Dihasilkan:

text
created

Mari kita telaah keadaan yang belum hidup itu:

  1. Output docker create adalah ID penuh — 64 karakter heksadesimal, sama persis bentuk yang dicetak docker run mode detached; penciptaan memang langkah yang sama.
  2. STATUS membaca Created, bukan Up — container terdaftar di docker ps -a namun tidak pernah di docker ps, karena PID 1-nya belum pernah dinyalakan.
  3. .State.Status berbunyi created — state ini punya nama resmi di metadata, salah satu dari lima penghuni peta kita.
  4. Kegunaannya nyata untuk persiapan — kita bisa menciptakan container beserta seluruh flag konfigurasinya lebih dulu — port, environment, batas resource — lalu menyalakannya belakangan pada momen yang kita pilih; beberapa pola deployment dan tool CI memang memakai pemisahan ini.

Menyusuri Siklus Hidup #

Sekarang kita jalani sisanya selangkah demi selangkah, memotret docker ps pada tiap perhentian. Perhentian pertama — kehidupan:

bash
$ docker start siklus

Output yang Dihasilkan:

text
siklus
bash
$ docker ps

Output yang Dihasilkan:

text
CONTAINER ID   IMAGE   COMMAND                  CREATED          STATUS         PORTS   NAMES
468fa01723fb   nginx   "/docker-entrypoint.…"   48 seconds ago   Up 4 seconds           siklus
bash
$ docker inspect --format '{{.State.Status}} {{.State.StartedAt}}' siklus

Output yang Dihasilkan:

text
running 2026-10-13T10:07:22.418392067Z

Perhentian kedua — pembekuan:

bash
$ docker pause siklus

Output yang Dihasilkan:

text
siklus
bash
$ docker ps

Output yang Dihasilkan:

text
CONTAINER ID   IMAGE   COMMAND                  CREATED          STATUS                  PORTS   NAMES
468fa01723fb   nginx   "/docker-entrypoint.…"   2 minutes ago    Up 26 seconds (Paused)          siklus

Perhentian ketiga — pencairan:

bash
$ docker unpause siklus

Output yang Dihasilkan:

text
siklus
bash
$ docker ps

Output yang Dihasilkan:

text
CONTAINER ID   IMAGE   COMMAND                  CREATED          STATUS         PORTS   NAMES
468fa01723fb   nginx   "/docker-entrypoint.…"   2 minutes ago    Up 34 seconds           siklus

Mari kita telaah tiga perhentian pertama itu:

  1. Created tidak pernah berubah menjadi Up tanpa docker start — kolom CREATED tetap mengingat usia container sejak diciptakan, sementara STATUS berganti menjadi Up 4 seconds begitu PID 1 menyala.
  2. .State.StartedAt mencatat jam dinyalakannya — waktu ISO dengan presisi nanodetik; docker restart kelak menimpanya dengan waktu yang baru, karena prosesnya memang generasi baru.
  3. (Paused) menempel pada status hidup — container yang dibekukan tetap dihitung hidup dengan umur yang terus berjalan; freezer hanya mencabut waktu CPU, bukan nyawa — persis perilaku yang kita praktikkan dengan web pada Chapter Menghentikan dan Menjalankan Container.
  4. unpause melanjutkan persis dari titik beku — status kembali menjadi Up biasa tanpa jejak; bagi nginx di dalamnya, seolah tidak ada yang terjadi.

Perhentian keempat adalah jalan buntu yang justru paling mengajar. Mari kita coba memotong jalan — menghapus container yang masih hidup:

bash
$ docker rm siklus

Output yang Dihasilkan:

text
Error response from daemon: You cannot remove a running container 468fa01723fb92a2e080be487d8df9a66aabf72b83993c9170fb5edc7c93bc05. Stop the container before attempting removal or force remove

Galat yang akrab ini — kita jumpai pertama kali pada Chapter Menghapus Container — menawarkan dua jalan keluar yang jujur. Jalan pertama adalah sopan: hentikan dulu, baru hapus. Container yang sedang dibekukan pun ditolak dengan cara serupa — cairkan dulu, baru urus penghentiannya. Jalan kedua adalah docker rm -f: mengirim SIGKILL tanpa masa tenggang lalu menghapus sisanya dalam satu tarikan napas. Kita ambil jalan pertama:

bash
$ docker stop siklus

Output yang Dihasilkan:

text
siklus
bash
$ docker ps -a

Output yang Dihasilkan:

text
CONTAINER ID   IMAGE   COMMAND                  CREATED         STATUS                      PORTS   NAMES
468fa01723fb   nginx   "/docker-entrypoint.…"   3 minutes ago   Exited (0) 7 seconds ago           siklus
bash
$ docker inspect --format '{{.State.Status}} {{.State.ExitCode}}' siklus

Output yang Dihasilkan:

text
exited 0

Perhentian terakhir — penghapusan:

bash
$ docker rm siklus

Output yang Dihasilkan:

text
siklus
bash
$ docker ps -a

Output yang Dihasilkan:

text
CONTAINER ID   IMAGE   COMMAND   CREATED   STATUS   PORTS   NAMES

Mari kita telaah dua perhentian terakhir itu:

  1. Exited (0) 7 seconds ago — nginx menutup dirinya dengan rapi lewat sinyal berhenti bawaan imagenya, dan docker stop selesai jauh sebelum masa tenggang; kode 0 di dalam kurung adalah exit code PID 1 yang juga terbaca sebagai .State.ExitCode.
  2. docker rm kali ini diterima — penghentian lebih dulu membuat penghapusan sah; urutan stop lalu rm persis ritual yang diajarkan galat ini sejak Section Dasar Docker CLI.
  3. Tabel docker ps -a menampilkan kepala kolom saja — siklus tidak lagi terdaftar di mana pun; nama dan ID-nya telah dibebaskan, dan container berpindah ke state Removed yang tidak punya jejak di daftar.

Enam Wajah STATUS di docker ps #

Kolom STATUS sepanjang perjalanan kita tadi menampilkan empat wajah — dan sepanjang section ini kita berpapasan dengan dua wajah lain. Tabel berikut merangkum keenamnya beserta state resminya:

STATUS di docker psState di inspectArtinya
Createdcreatedcontainer sudah dibangun, PID 1 belum pernah dinyalakan
Up 2 minutesrunningproses berjalan dengan sehat
Up 2 minutes (Paused)pausedproses hidup namun dibekukan freezer cgroup
Exited (0)exitedberhenti rapi — PID 1 keluar dengan kode sukses
Exited (137)exitedtumbang oleh SIGKILL — docker kill, masa tenggang habis, atau OOM killer
Restarting (1)restartingmenunggu jeda ulang kebijakan restart dengan exit code terakhir di kurung

Dua baris terakhir membawa kabar dari chapter-chapter tetangga. Exited (137) adalah warisan lapar yang kita serahkan kepada OOM killer pada Chapter CPU dan Memory Limit — dan docker inspect --format '{{.State.OOMKilled}}' adalah pembeda antara OOM dan docker kill biasa, sebagaimana kita praktikkan di sana. Restarting (1) adalah status sesaat yang kita tangkap pada Chapter Restart Policy — keadaan menunggu jeda backoff di antara dua percobaan kebangkitan, dengan angka kegagalan tercatat di dalam kurungnya.

Membaca State Lewat docker inspect #

Empat field .State berikut adalah panel indikator yang paling sering kita baca sepanjang section ini, dan kini maknanya lengkap:

FieldContoh nilaiArtinya
.State.Statuscreated, running, paused, restarting, exitedposisi container pada peta lima state saat dibaca
.State.ExitCode0 sampai 255kode keluar terakhir PID 1, termasuk konvensi 128 + sinyal
.State.StartedAt2026-10-13T10:07:22.418392067Zwaktu PID 1 terakhir kali dinyalakan
.State.OOMKilledtrue atau falseapakah kematian terakhir adalah karya OOM killer

Flag --rm menutup daftar perintah transisi dari sisi lain: menghadiahkan container penghapusan otomatis begitu keluar dari state running, tanpa kita menyebut docker rm — materi yang kita praktikkan pada Chapter Menghapus Container. Bersama docker rm -f dan seluruh perintah pada peta kita, kebutuhan sehari-hari sudah terjelaskan semua: mulai dari container sekali pakai yang menghapus dirinya sendiri, container yang disiapkan matang untuk disimpan, sampai container yang dibangkitkan tanpa henti oleh kebijakannya.

Peta yang barusan kita susuri juga menyimpan satu fakta yang sengaja kita simpan untuk penutup section ini: docker rm tidak hanya menghapus nama dan konfigurasi. Seluruh tulisan yang dibuat proses di dalam container — berkas log yang ditulis nginx, berkas yang diunduh, basis data kecil yang tumbuh — hidup di writable layer, dan layer itu lenyap bersama container-nya pada perhentian terakhir. Exited masih menyimpan semuanya; Removed tidak menyimpan apa-apa. Maka pertanyaan section berikutnya menanti dengan sendirinya: bagaimana caranya membuat data hidup lebih lama dari container yang menampungnya? Section Penyimpanan Data menjawabnya dari fondasinya — dimulai dari Chapter Writable Container Layer, tempat kita membongkar lapisan yang barusan kita lihat lenyap itu.

Referensi #