Siklus hidup yang kita kuasai pada Chapter Menghentikan dan Menjalankan Container meninggalkan satu pekerjaan rumah yang belum dibereskan: setiap container yang berhenti tetap menetap di mesin, dan daftar docker ps -a kita perlahan memanjang. quirky_einstein sudah menjadi penghuni tetap sejak Chapter Menjalankan Container Pertama, dan tidak ada satu pun perintah pada chapter sebelumnya yang membuatnya pergi. Container berhenti memang tidak memakan CPU, tetapi writable layer-nya tetap memakan disk, namanya tetap memakan perhatian, dan pada mesin yang dipakai bergantian, daftar panjang semacam itu cepat atau lambat menjadi sumber kebingungan. Chapter ini melengkapi siklus hidup dengan langkah terakhirnya — penghapusan — mulai dari docker rm untuk satu container, flag --rm yang mencegah sampah lahir, sampai docker container prune yang membersihkan massal, sekaligus membahas satu pertanyaan penting: apa sebenarnya yang ikut terbuang saat sebuah container dihapus?
Menghapus Container yang Sudah Berhenti #
Perintah penghapusan adalah docker rm — bentuk modernnya docker container rm, dan keduanya setiap saat bisa saling menggantikan. Syarat utamanya tegas: container harus dalam keadaan berhenti. Kita mulai dari penghuni paling lama di mesin kita:
$ docker rm quirky_einsteinOutput yang Dihasilkan:
quirky_einsteinMari kita telaah perintah dan output di atas:
- Output
quirky_einstein— sama sepertistopdanstart, perintah penghapusan mencetak kembali identifier yang kita sebut sebagai konfirmasi; penghapusan adalah operasi permanen, dan satu baris ini adalah tanda terima resminya. - Identifier bebas dipilih — nama, ID pendek 12 karakter, maupun ID penuh 64 karakter sama-sama diterima; kebiasaan memakai nama seperti ini yang membuat
--namepadadocker runterasa berharga. - Banyak container sekaligus —
docker rmmenerima beberapa argumen sekaligus, misalnyadocker rm web cache, dan mencetak satu baris konfirmasi per container yang berhasil dihapus.
Bukti bahwa penghuni lama kita benar-benar pergi:
$ docker ps -aOutput yang Dihasilkan:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f7c2a91b3e55 nginx "/docker-entrypoint.…" 26 minutes ago Up 5 minutes 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp web
3a1c8f2e9b7d redis:7 "docker-entrypoint.s…" 20 minutes ago Up 20 minutes 6379/tcp cacheTabel kini hanya menampung dua container yang sedang hidup — baris quirky_einstein lenyap bersama seluruh jejaknya. Penghapusan memang bukan pematian: stop menidurkan container agar bisa dibangunkan, sedangkan rm membuat container tidak pernah ada.
Ketika Container Masih Hidup #
Perlindungan bawaan Docker langsung terasa begitu kita mencoba menghapus container yang masih berjalan. Mari kita uji nasibnya pada web — murni sebagai percobaan, karena container ini masih kita perlukan:
$ docker rm webOutput yang Dihasilkan:
Error response from daemon: You cannot remove a running container f7c2a91b3e55913c4a5f1c6c0a4d8e2b3f4a5b6c7d8e9f0a1b2c3d4e5f60718a. Stop the container before attempting removal or force removeMari kita telaah isi galat di atas:
You cannot remove a running container— daemon menolak permintaan;websedang hidup, dan menghapus container hidup tanpa peringatan adalah pintu menuju kecelakaan, sehingga Docker menutupnya secara bawaan.- ID penuh 64 karakter ikut dicantumkan — daemon menyebut container dengan identitas lengkapnya agar tidak ada salah sasaran, termasuk saat kita menghapus lewat ID pendek.
- Dua jalan keluar ditawarkan persis di dalam pesannya — hentikan container lebih dulu lalu hapus, atau paksa penghapusan; kalimat
Stop the container before attempting removal or force removeadalah peta kedua jalurnya.
Jalur pertama sudah kita kuasai: docker stop web diikuti docker rm web — sopan, bersih, dan memberi aplikasi kesempatan beres-beres. Jalur kedua adalah flag --force atau bentuk pendeknya -f. Agar web tetap utuh untuk chapter-chapter berikutnya, kita pakai container sekali pakai sebagai kelinci percobaan — image alpine:3.20 yang mungil, 7.8MB, belum pernah kita tarik ke mesin ini:
$ docker run -d --name uji-rm alpine:3.20 sleep 300Output yang Dihasilkan:
Unable to find image 'alpine:3.20' locally
3.20: Pulling from library/alpine
...
Status: Downloaded newer image for alpine:3.20
8bba006035ae1e292f702693fc7538c98ec49c6d6377af5cf0f324900559aef1Baris layer dan nilai digest dipotong agar ringkas — alpine hanya berlapis sangat tipis. Container uji-rm kini hidup menjalankan sleep 300, dan kita hapus paksa dalam keadaan menyala:
$ docker rm -f uji-rmOutput yang Dihasilkan:
uji-rmMari kita telaah apa yang dikerjakan flag -f:
- Dua langkah dalam satu perintah —
rm -fmenghentikan container lalu menghapusnya; secara efektif perintah ini adalahdocker killdandocker rmyang dirangkai, bukandocker stopdandocker rm. - Penghentiannya memakai SIGKILL — tanpa sinyal sopan dan tanpa masa tenggang, persis seperti
docker killpada chapter sebelumnya; aplikasi di dalamnya tidak diberi kesempatan beres-beres. - Tempatnya di alur kerja — flag ini nyaman untuk container latihan dan container sekali pakai yang tinggal namanya, tetapi untuk aplikasi yang sedang menulis data, jalur
stopdulu lalurmtetap merupakan urutan yang benar; risiko data setengah jadi yang kita bahas pada Chapter Menghentikan dan Menjalankan Container berlaku sama persis di sini.
Hapus Otomatis dengan Flag –rm #
Galat barusan terjadi karena ada container yang tertinggal hidup — tetapi masalah yang lebih sering menghantui pemula adalah kebalikannya: container yang tertinggal berhenti. Setiap docker run tanpa perlakuan khusus meninggalkan bekas, dan bekas itulah yang hari ini bernama quirky_einstein sebelum kita bersihkan. Docker menyediakan pencegahannya langsung pada docker run: flag --rm memerintahkan daemon menghapus container secara otomatis begitu prosesnya selesai. Kita uji dengan container perkenalan yang sudah menjadi image lokal:
$ docker run --rm hello-worldOutput yang Dihasilkan:
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
...Sisa pesan dipotong — isinya persis seperti yang kita baca pada Chapter Menjalankan Container Pertama. Bedanya ada di belakang layar: begitu program /hello selesai dan container berhenti, daemon langsung membersihkan container itu tanpa menunggu perintah apa pun dari kita. Sekarang kita ulangi tanpa flag tersebut:
$ docker run hello-worldOutput yang Dihasilkan:
Hello from Docker!
...Pesan yang tercetak sama persis — dipotong lebih pendek karena tidak ada yang baru — tetapi kali ini container bekasnya menetap. Docker bahkan mengarangkannya nama otomatis, dengan kebiasaan kata-sifat-plus-nama-tokoh yang sudah kita kenal:
$ docker ps -aOutput yang Dihasilkan:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f7c2a91b3e55 nginx "/docker-entrypoint.…" 30 minutes ago Up 9 minutes 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp web
3a1c8f2e9b7d redis:7 "docker-entrypoint.s…" 24 minutes ago Up 24 minutes 6379/tcp cache
93f2ea643623 hello-world "/hello" About a minute ago Exited (0) About a minute ago elegant_nightingaleMari kita telaah baris ketiga pada tabel di atas:
elegant_nightingalebaru saja lahir dan pensiun — ini bekasdocker run hello-worldyang kita jalankan tanpa--rm; statusExited (0)dicatat satu menit lalu, dan tanpa intervensi, baris ini akan menetap selama-lamanya seperti nenek moyangnyaquirky_einstein.- Bekas pemakaian
--rmtidak tampak — percobaan pertama tidak meninggalkan baris apa pun; itulah seluruh perbedaan dua flag ini:--rmmencegah sampah lahir,docker rmmembersihkannya setelah lahir. - Ukuran masalahnya kecil, frekuensinya besar — satu hello-world hanya menyisakan writable layer yang nyaris kosong, tetapi kebiasaan menjalankan container percobaan berulang kali tanpa
--rmakan menghasilkan tumpukan puluhan baris dalam hitungan hari.
Membersihkan Massal dengan docker container prune #
Ketika daftar container berhenti sudah membludak, membersihkannya satu per satu menjadi pekerjaan yang membosankan. Perintah docker container prune menghapus semua container yang sedang berhenti dalam satu ayunan — saat ini satu-satunya kandidat di mesin kita adalah elegant_nightingale:
$ docker container pruneOutput yang Dihasilkan:
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
93f2ea6436236d2fab8d40b5820a5b069a473db00997be00f2187b5fec591ed4
Total reclaimed space: 0BMari kita telaah empat bagian output di atas:
- Baris
WARNING! This will remove all stopped containers.— daemon menyatakan dampak perintahnya terlebih dahulu; semua container berstatusExiteddanCreatedakan dihapus tanpa memandang asal-usul. - Prompt
[y/N]dan jawabany— prune bersifat destruktif sehingga meminta konfirmasi; huruf besar padaNmenandakan jawaban bawaan bila kita hanya menekan Enter. Flag--forcemelewati prompt ini — berguna di skrip, berbahaya di tangan yang terburu-buru. Deleted Containers:dengan ID penuh — daftar korban dicetak dengan identitas lengkapnya; satu baris untukelegant_nightingalekita. Filter--filter until=24hmembatasi korban hanya pada container yang berumur lebih dari satu hari, dan--filter label=membatasi pada yang berlabel tertentu.Total reclaimed space: 0B— ruang disk yang direbut kembali; angka0Bbukan kegagalan. Writable layer hello-world nyaris kosong karena program/hellotidak menulis apa pun, dan angka ini memang mengukur writable layer container — bukan ukuran image, yang tidak tersentuh sama sekali.
Writable Layer yang Ikut Terbuang #
Pertanyaan penutup chapter ini: ketika sebuah container dihapus, apa sebenarnya yang terbuang? Jawabannya menegaskan arsitektur yang kita kenal sejak tahap create pada Chapter Menjalankan Container Pertama — sebuah container adalah image ditambah satu writable layer tipis di puncak tumpukan layer image yang bersifat baca-saja. Seluruh tulisan yang dilakukan proses di dalam container mendarat di layer teratas tersebut. Dan docker rm membuang tepat bagian itu: writable layer beserta konfigurasi container lenyap, sementara seluruh layer image tetap utuh di penyimpanan lokal. Buktinya bisa kita lihat sekarang juga, setelah semua container latihan tadi kita bereskan:
$ docker imagesOutput yang Dihasilkan:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 613f27b0341a 3 days ago 187MB
redis 7 dc30543fe5a6 2 weeks ago 138MB
alpine 3.20 2676beef0bef 2 weeks ago 7.8MB
hello-world latest e6590340b2f4 2 years ago 13.3kBMari kita telaah keempat baris di atas:
- Empat image tetap utuh —
uji-rmyang kitarm -fdanelegant_nightingaleyang kita prune lenyap sebagai container, tetapi imagealpine:3.20danhello-worldyang melahirkan mereka tetap tinggal;docker rmtidak pernah menyentuh image asalnya. - Konsekuensi nyatanya — menjalankan
docker run hello-worldataudocker run -d alpine:3.20 sleep 300berikutnya akan instan tanpa satu baris pull, karena cetakbirunya masih ada. - Konsekuensi yang lebih penting — data yang ditulis proses ke dalam container ikut terbuang bersama writable layer; halaman yang kita edit di dalam
web, berkas yang dibuatuji-rm, semuanya tidak akan mengikuti container baru dari image yang sama. Data yang memang harus bertahan melewati penghapusan membutuhkan volume atau bind mount — materi Section Penyimpanan Data — dan struktur layer yang membuat semua ini mungkin kita bedah tuntas pada Chapter Konsep Image Layer di Section berikutnya.
Ringkasan Perintah Penghapusan #
Empat alat penghapusan pada chapter ini masing-masing menjawab kebutuhan yang berbeda. Tabel berikut merangkumnya:
| Perintah | Yang dihapus | Kapan dipakai |
|---|---|---|
| docker rm nama | Satu atau beberapa container yang sudah berhenti | Pembersihan selektif setelah memeriksa docker ps -a |
| docker rm -f nama | Container apa pun, termasuk yang masih hidup | Container sekali pakai atau mesin latihan |
| docker run –rm … | Container itu sendiri begitu proses selesai | Tugas sekali jalan agar tidak meninggalkan bekas |
| docker container prune | Semua container berstatus Exited atau Created | Bersih-bersih massal setelah sesi latihan |
Mesin kita kini berada di titik yang rapi: hanya web dan cache yang hidup, tanpa satu pun bekas menumpuk, dan empat image siap pakai di penyimpanan lokal. Tetapi ada satu kebiasaan penting yang belum kita miliki — selama ini kita hanya bisa mengamati container dari luar lewat tabel docker ps, tanpa pernah tahu apa yang sebenarnya terjadi di dalam web sepanjang hari ini: permintaan apa saja yang datang, jawaban apa yang diberikan, dan pesan apa yang tercatat ketika sebuah halaman tidak ditemukan. Jawaban untuk semua itu mengalir lewat stdout dan stderr container, dan perintah pembacanya adalah docker logs — materi Chapter Melihat Log Container.
Referensi #
- docker container rm
— referensi resmi rm beserta flag
--force. - docker container prune
— referensi resmi prune beserta flag
--forcedan--filter. - docker container run
— referensi resmi run, termasuk perilaku flag
--rm.