Anda baru saja men-deploy container Docker, namun alih-alih berjalan mulus, container Anda malah terus-menerus restart? Ini adalah skenario frustrasi yang kerap dihadapi setiap developer dan tim DevOps. Container yang terus-menerus restart, atau sering disebut “crash loop”, menandakan ada masalah mendasar yang perlu segera diatasi. Bukan hanya mengganggu, kondisi ini juga bisa menghabiskan sumber daya server dan menghambat alur kerja pengembangan Anda.
Sebagai seorang software engineer atau developer, memahami cara mendiagnosis dan mengatasi masalah restart container adalah keterampilan yang esensial. Artikel ini akan memandu Anda melalui langkah-langkah debugging yang sistematis, mulai dari pemeriksaan dasar hingga analisis mendalam, memastikan Anda dapat mengidentifikasi akar masalah dan mengembalikan container Anda ke kondisi berjalaormal. Mari kita selami satu per satu.
Mengapa Docker Container Bisa Restart Terus-Menerus?
Sebelum masuk ke solusi, penting untuk memahami berbagai kemungkinan penyebab di balik perilaku restart yang tidak diinginkan ini. Beberapa penyebab umum meliputi:
- Kesalahan Aplikasi: Aplikasi di dalam container mengalami crash karena bug, konfigurasi salah, atau kegagalan inisialisasi.
- Masalah Sumber Daya: Container kehabisan memori (OOMKilled) atau CPU, sehingga Docker atau sistem operasi mematikaya.
- Kesalahan Konfigurasi Docker: Konfigurasi Dockerfile,
docker-compose.yml, atau perintahdocker runyang tidak tepat. - Dependencies Hilang atau Rusak: Aplikasi tidak dapat menemukan database, file konfigurasi, atau library yang diperlukan.
- Izin File atau Direktori: Aplikasi tidak memiliki izin yang cukup untuk mengakses file atau direktori penting di dalam container atau volume yang di-mount.
- Masalah Jaringan: Container tidak dapat terhubung ke layanan eksternal atau port yang dibutuhkan sudah digunakan.
- Restart Policy: Kebijakan restart Docker yang diatur untuk selalu mencoba memulai ulang container, meskipun ada kegagalan internal.
Langkah-Langkah Komprehensif Mengatasi Docker Container Restart Terus
Berikut adalah panduan langkah demi langkah untuk mendiagnosis dan memperbaiki container Docker yang terus-menerus restart:
1. Periksa Log Container dengan Seksama
Langkah pertama dan paling krusial adalah memeriksa log container. Log adalah “jendela” ke dalam apa yang terjadi di dalam container Anda. Pesan kesalahan di log seringkali langsung menunjukkan akar masalah.
Untuk memeriksa log container, gunakan perintah:
docker logs <container_id_atau_nama>
Jika container Anda terus-menerus restart, Anda mungkin perlu menambahkan opsi --tail dan -f untuk melihat log terbaru secara real-time saat container mencoba untuk memulai ulang.
docker logs --tail 100 -f <container_id_atau_nama>
- Analisis Log: Cari pesan kesalahan (misalnya, “Error”, “Failed to start”, “Exception”, “Segmentation fault”, “Permission denied”). Perhatikan stack trace yang mungkin muncul, karena ini dapat menunjukkan lokasi spesifik kode yang menyebabkan masalah.
- Waktu Log: Perhatikan juga timestamp log. Apakah error muncul tepat setelah container mencoba start, atau setelah beberapa waktu berjalan?
2. Periksa Status Keluar (Exit Status) Container
Ketika sebuah container berhenti, ia akan mengeluarkan exit code. Kode ini sangat informatif tentang mengapa container tersebut berhenti.
Untuk melihat semua container yang pernah berjalan (termasuk yang telah berhenti), gunakan:
docker ps -a
Lihat kolom “STATUS”. Jika Anda melihat status seperti Exited (137), Exited (1), atau Exited (255), ini mengindikasikan masalah.
- Exit Code 137: Ini adalah kode yang sangat umum dan biasanya berarti container dimatikan secara paksa oleh sistem operasi (kernel Linux) karena kehabisan memori (Out Of Memory – OOMKilled). Ini menunjukkan bahwa aplikasi di dalam container membutuhkan lebih banyak RAM daripada yang dialokasikan atau tersedia.
- Exit Code 1: Seringkali menunjukkan kesalahan umum aplikasi atau error dalam perintah
ENTRYPOINTatauCMDDockerfile. Ini bisa berarti aplikasi gagal memulai atau terjadi kesalahan yang tidak tertangani. - Exit Code 0: Ini adalah exit code yang sukses. Jika container Anda keluar dengan kode 0 namun terus restart, itu mungkin berarti aplikasi Anda memang dirancang untuk melakukan tugas singkat lalu keluar, tetapi Docker restart policy membuatnya terus mencoba ulang.
- Exit Code Laiya: Kode laiya biasanya spesifik untuk aplikasi Anda atau sistem operasi, namun intinya adalah non-zero exit code menunjukkan kegagalan.
Untuk mendapatkan informasi lebih detail termasuk exit code dan restart count, gunakan:
docker inspect <container_id_atau_nama> | grep ExitCode
docker inspect <container_id_atau_nama> | grep -i restart
3. Periksa Konfigurasi Restart Policy
Docker memiliki kebijakan restart yang menentukan kapan container harus di-restart secara otomatis. Jika diatur tidak tepat, ini bisa menjadi penyebab container terus-menerus restart bahkan ketika aplikasinya bermasalah.
Kebijakan restart yang umum:
no: Tidak otomatis restart.on-failure[:max-retries]: Restart hanya jika container keluar dengan kode non-nol, dengan opsi jumlah percobaan maksimum.always: Selalu restart, bahkan jika container keluar dengan sukses (exit code 0).unless-stopped: Selalu restart kecuali secara manual dihentikan.
Untuk melihat restart policy container Anda:
docker inspect <container_id_atau_nama> | grep -i restartpolicy
Jika Anda menggunakan always atau unless-stopped, container akan terus restart tanpa henti bahkan jika aplikasinya crash. Untuk debugging, Anda bisa coba mengubah policy menjadi no atau on-failure untuk sementara waktu, atau cukup hentikan dan hapus container lalu jalankan lagi dengan policy yang berbeda.
Anda bisa menonaktifkan kebijakan restart saat menjalankan container baru:
docker run --restart=no <image_name>
4. Cek Penggunaan Sumber Daya (Resource Usage)
Seperti disebutkan sebelumnya, Out Of Memory (OOMKilled) adalah penyebab umum container restart (exit code 137). Docker dapat mematikan container secara otomatis jika melebihi batas sumber daya yang dialokasikan.
Gunakan docker stats untuk memantau penggunaan CPU, memori, dan I/O disk secara real-time:
docker stats <container_id_atau_nama>
Perhatikan kolom “MEM USAGE / LIMIT”. Jika penggunaan memori mendekati batas yang dialokasikan, atau Anda melihat status OOMKilled di log atau docker inspect, kemungkinan besar inilah penyebabnya.
Solusi:
- Tingkatkan Batas Sumber Daya: Alokasikan lebih banyak memori atau CPU saat menjalankan container.
docker run -m 2g --cpus 1.5 <image_name>
5. Validasi Konfigurasi Aplikasi dan Dockerfile
Kesalahan dalam konfigurasi aplikasi atau Dockerfile seringkali menjadi sumber masalah.
- Dockerfile:
- ENTRYPOINT / CMD: Pastikan perintah yang dijalankan benar dan aplikasi Anda memang memulai sesuai yang diharapkan. Kesalahan ketik atau jalur yang salah di sini akan menyebabkan aplikasi gagal start.
- Dependencies: Apakah semua dependensi (seperti library, paket OS) terinstal dengan benar?
- User/Permissions: Apakah aplikasi dijalankan dengan user yang memiliki izin yang cukup?
- Konfigurasi Aplikasi:
- Environment Variables: Apakah semua variabel lingkungan yang dibutuhkan aplikasi tersedia dan memiliki nilai yang benar?
- File Konfigurasi: Apakah aplikasi dapat menemukan dan membaca file konfigurasi yang dibutuhkan (misalnya,
.env,config.json)? - Port Konflik: Pastikan aplikasi di dalam container tidak mencoba menggunakan port yang sudah terpakai di host atau oleh container lain.
Tips Debugging:
Coba jalankan container dalam mode interaktif untuk memeriksa secara manual:
docker run -it --entrypoint sh <image_name>
Kemudian, di dalam shell container, coba jalankan perintah startup aplikasi Anda secara manual. Ini akan membantu Anda melihat output atau error yang mungkin tidak muncul di log standar.
6. Periksa Dependencies dan Volume
Banyak aplikasi bergantung pada layanan eksternal (database, message queue, cache) atau volume data.
- Koneksi Database: Jika aplikasi Anda membutuhkan database, pastikan database tersebut berjalan, dapat dijangkau dari container, dan kredensialnya benar. Coba ping IP database dari dalam container.
- Volume Data: Jika Anda me-mount volume ke container, pastikan volume tersebut tidak kosong atau rusak, dan bahwa izin file/direktori di volume tersebut sesuai dengan yang dibutuhkan aplikasi di dalam container. Kesalahan izin (misalnya, aplikasi mencoba menulis ke direktori yang hanya bisa dibaca) dapat menyebabkan crash.
7. Periksa Network Configuration
Masalah jaringan bisa menyebabkan container restart jika aplikasi tidak dapat mengakses sumber daya eksternal yang penting untuk startup-nya.
- DNS Resolution: Apakah container dapat me-resolve nama host eksternal?
- Firewall: Apakah ada firewall (baik di host maupun di cloud provider) yang memblokir koneksi yang dibutuhkan?
- Port Mapping: Apakah port yang diekspos di container di-map dengan benar ke port di host atau di network Docker?
8. Uji Image Container Secara Lokal
Jika Anda curiga masalahnya ada pada image Docker itu sendiri, coba jalankan image tersebut di lingkungan lokal yang bersih atau di mesin lain. Ini akan membantu mengisolasi apakah masalahnya ada pada image atau pada lingkungan deployment Anda.
Pastikan Anda membangun ulang image setiap kali ada perubahan pada Dockerfile atau kode aplikasi Anda.
docker build -t myapp:latest .
docker run <opsi_seperti_sebelumnya> myapp:latest
9. Perbarui Docker Daemon dan Image Base
Terkadang, bug pada versi lama Docker daemon atau pada image base (misalnya, Alpine, Ubuntu) dapat menyebabkan perilaku aneh.
- Update Docker: Pastikan Anda menggunakan versi Docker Engine yang terbaru dan stabil.
- Update Base Image: Perbarui image dasar di Dockerfile Anda ke versi terbaru. Misalnya, dari
node:16-alpinemenjadinode:18-alpine. Pastikan untuk menguji kompatibilitas aplikasi Anda dengan base image yang lebih baru.
10. Gunakan Health Check dalam Dockerfile
Untuk deteksi masalah yang lebih proaktif, gunakan instruksi HEALTHCHECK di Dockerfile Anda. Health check memungkinkan Docker untuk secara berkala memeriksa apakah aplikasi di dalam container masih berfungsi dengan baik.
Contoh:
HEALTHCHECK --interval=5s --timeout=3s --retries=3 CMD curl --fail http://localhost:8080/health || exit 1
Dengan HEALTHCHECK, Docker akan menandai container sebagai “unhealthy” jika health check gagal, dan Anda bisa mengkonfigurasi orkestrator (seperti Docker Compose atau Kubernetes) untuk mengambil tindakan, misalnya, me-restart container secara otomatis.
Best Practices untuk Mencegah Container Restart di Masa Depan
Mencegah selalu lebih baik daripada mengobati. Terapkan praktik terbaik berikut untuk meminimalkan kemungkinan container restart di masa mendatang:
- Dockerfile yang Optimal: Buat Dockerfile yang efisien dan modular. Gunakan multi-stage builds untuk mengurangi ukuran image. Pastikan perintah
ENTRYPOINTdanCMDAnda stabil. - Konfigurasi yang Robust: Selalu validasi variabel lingkungan dan file konfigurasi. Gunakan sistem manajemen konfigurasi.
- Implementasi Health Check: Masukkan
HEALTHCHECKdi setiap Dockerfile untuk aplikasi yang penting. - Logging dan Monitoring: Terapkan sistem logging terpusat dan alat monitoring untuk melacak metrik container (CPU, RAM, I/O) dan log aplikasi.
- Uji Unit dan Integrasi: Pastikan aplikasi Anda memiliki cakupan tes yang memadai untuk menangkap bug sebelum deployment.
- Alokasi Sumber Daya yang Memadai: Beri container Anda sumber daya yang cukup, terutama memori. Jangan biarkan terlalu mepet.
- Versioning: Gunakan tagging versi yang jelas untuk image Docker Anda dan jangan hanya mengandalkan tag
latestuntuk produksi. - Error Handling Aplikasi: Tulis kode aplikasi dengan penanganan error yang kuat dan log pesan error yang informatif.
FAQ
Apa itu exit code 137 pada Docker?
Exit code 137 (128 + 9) biasanya berarti container Anda dimatikan secara paksa oleh kernel Linux karena kehabisan memori (Out Of Memory – OOMKilled). Angka 9 adalah sinyal SIGKILL, yang berarti proses dihentikan secara paksa dan tidak diberi kesempatan untuk membersihkan diri.
Bagaimana cara saya tahu apakah container saya OOMKilled?
Selain exit code 137, Anda bisa memeriksa log Docker daemon (misalnya journalctl -u docker di sistem Linux) untuk mencari pesan “OOMKilled” atau “Out of memory” yang terkait dengan ID container Anda. Anda juga bisa menggunakan docker inspect <container_id> dan mencari bagian State.OOMKilled.
Apa bedanya `restart: always` dengan `restart: on-failure`?
restart: always akan selalu mencoba me-restart container, terlepas dari apakah container tersebut keluar dengan sukses (exit code 0) atau karena error (exit code non-nol). Sedangkan restart: on-failure hanya akan me-restart container jika ia keluar dengan kode non-nol, yang menandakan adanya kegagalan. Untuk debugging, on-failure lebih disarankan agar Anda bisa melihat error sebelum container otomatis restart.
Mengapa container saya restart setelah update image?
Restart setelah update image seringkali disebabkan oleh perubahan dalam aplikasi atau lingkungan di dalam image baru yang tidak kompatibel dengan konfigurasi lama, dependensi yang hilang, atau bug baru. Periksa log container baru, pastikan variabel lingkungan dan volume yang di-mount masih relevan, dan coba jalankan image lama untuk membandingkan perilakunya.
Bagaimana cara menghentikan container agar tidak terus restart saat saya debugging?
Cara paling mudah adalah dengan mengubah restart policy saat menjalankan container: docker run --restart=no <image_name>. Atau, jika sudah berjalan, hentikan container secara paksa daonaktifkan restart policy-nya (membutuhkan docker update untuk container yang sudah berjalan, atau stop, remove, dan recreate dengan policy baru).
Kesimpulan
Container Docker yang terus-menerus restart adalah salah satu tantangan umum yang akan Anda hadapi dalam pengembangan dan operasi perangkat lunak modern. Kunci untuk mengatasinya adalah dengan pendekatan debugging yang sistematis, mulai dari memeriksa log, menganalisis exit code, hingga memvalidasi konfigurasi dan sumber daya.
Dengan menerapkan langkah-langkah yang diuraikan di atas dan mengadopsi praktik terbaik, Anda tidak hanya dapat mengatasi masalah yang ada, tetapi juga membangun fondasi yang lebih kokoh untuk aplikasi container Anda di masa depan. Ingatlah, setiap error adalah kesempatan untuk belajar dan meningkatkan sistem Anda menjadi lebih tangguh.
