Topik ini membahas pembacaan log pada container dengan perintah docker logs. Log adalah catatan pesan yang dihasilkan aplikasi selama berjalan. Pembahasan mencakup asal keluaran yang ditangkap Docker, opsi -f, --tail, dan --since, serta konvensi penulisan log agar dapat dibaca perintah tersebut. Setelah membacanya, isi log sebuah container dapat ditampilkan, dipotong, dan diikuti secara langsung untuk keperluan diagnosis.
Sumber log yang ditangkap Docker#
Log container berasal dari dua aliran keluaran standar proses utama. Aliran pertama adalah stdout, aliran keluaran normal sebuah program, sedangkan aliran kedua adalah stderr, aliran khusus untuk pesan error. Setiap baris yang ditulis aplikasi ke salah satu aliran itu direkam oleh daemon, proses latar belakang Docker yang mengerjakan seluruh pekerjaan container.
Perekamannya dikelola logging driver, komponen daemon yang menentukan ke mana keluaran container disimpan. Driver bawaan bernama json-file menuliskan setiap baris log ke sebuah berkas pada host, yaitu mesin tempat Docker berjalan. Perintah docker logs kemudian membaca berkas itu dan menampilkan isinya.
Mekanisme perekaman tersebut menjelaskan satu perilaku penting yang sering luput. Perintah docker logs tidak membaca log dari dalam container, melainkan dari rekaman daemon di luar container, sehingga log tetap dapat dibaca setelah terminal tempat container dijalankan ditutup. Log container yang sudah berhenti pun masih tersedia, dan barulah hilang ketika container dihapus.
Isi lognya sendiri sepenuhnya ditentukan aplikasi. Pesan mulai, permintaan yang dilayani, data yang disimpan, dan error yang terjadi layak masuk log, satu peristiwa per baris. Baris yang teratur semacam itu inilah bahan pertama diagnosis, karena perilaku aplikasi dapat ditelusuri tanpa membuka container dan tanpa menghentikannya.
Membaca log dengan docker logs#
Perintah docker logs nama-container menampilkan seluruh log yang terkumpul sejak container dijalankan. Pada container aplikasi catatan yang berjalan di latar dengan nama catatan-app, perintah ini menampilkan setiap baris yang pernah dihasilkan aplikasi. Untuk log yang sudah panjang, opsi-opsi berikut mengatur cakupan tampilannya.
# tidak-dijalankan: daemon Docker tidak tersedia di sandbox
# tampilkan seluruh log yang terkumpul
docker logs catatan-app
# tampilkan 20 baris terakhir saja
docker logs --tail 20 catatan-app
# tampilkan log sejak sepuluh menit terakhir
docker logs --since 10m catatan-app
# ikuti baris baru sampai dihentikan dengan Ctrl-C
docker logs -f catatan-app| Opsi | Fungsi |
|---|---|
-f | Mengikuti baris baru segera setelah dihasilkan, sampai dihentikan dengan Ctrl-C |
--tail 20 | Menampilkan 20 baris terakhir saja |
--since 10m | Menampilkan log sejak waktu yang disebutkan, berupa rentang relatif atau penanda waktu |
-t | Menambahkan penanda waktu pada setiap baris |
Opsi -f adalah singkatan dari follow, yaitu terus mengikuti keluaran baru. Perilakunya sebanding dengan perintah tail -f pada sebuah berkas log di host, sehingga perkembangan aplikasi dapat diamati tanpa mengulang perintah. Perintah berakhir ketika Ctrl-C ditekan, sedangkan container tetap berjalan karena yang dihentikan hanyalah pembaca log, bukan container itu sendiri.
Opsi --since menerima penanda waktu absolut maupun rentang relatif. Format absolutnya berupa penanda waktu seperti 2013-01-02T13:23:37Z, sedangkan format relatifnya menerima singkatan seperti 10m untuk sepuluh menit dan 24h untuk sehari. Opsi -t melengkapi keduanya dengan menempelkan penanda waktu pada setiap baris, sehingga urutan peristiwa antar log dapat disusun kembali.
Konvensi log ke stdout dan stderr#
Agar dapat dibaca docker logs, aplikasi di dalam container harus menulis log ke stdout dan stderr, bukan ke berkas di dalam container. Berkas log yang dibuat di dalam container tidak direkam logging driver, sehingga isinya tidak pernah muncul pada docker logs dan ikut hilang ketika container dihapus. Konvensi ini menjadi alasan hampir semua image menyediakan cara mengarahkan log ke aliran standar, biasanya melalui variabel lingkungan atau konfigurasi.
Program berikut memperagakan aliran yang dimaksud pada aplikasi catatan. Tiga baris berlevel INFO ditulis ke stdout, sedangkan satu baris berlevel ERROR ditulis ke stderr. Bentuknya meniru log aplikasi sungguhan, lengkap dengan penanda waktu dan level.
"""Aliran log aplikasi catatan: setiap baris menuju stdout atau stderr."""
import sys
# baris log langsung ditulis tanpa ditahan buffer
sys.stdout.reconfigure(line_buffering=True)
def catat(waktu, pesan):
"""Menulis satu baris log level INFO ke stdout."""
print(f"{waktu} INFO {pesan}")
def error(waktu, pesan):
"""Menulis satu baris log level ERROR ke stderr."""
print(f"{waktu} ERROR {pesan}", file=sys.stderr)
catat("08:30:01", "Aplikasi catatan dimulai pada port 8000")
catat("08:30:01", "Memuat 12 catatan dari penyimpanan")
catat("08:30:02", "Menyimpan catatan baru dari Citra")
error("08:30:02", "Gagal membaca catatan nomor 13, berkas tidak ditemukan")08:30:01 INFO Aplikasi catatan dimulai pada port 8000
08:30:01 INFO Memuat 12 catatan dari penyimpanan
08:30:02 INFO Menyimpan catatan baru dari Citra
08:30:02 ERROR Gagal membaca catatan nomor 13, berkas tidak ditemukanDua aliran tersebut berbeda tujuan, tetapi docker logs menampilkan keduanya bercampur sesuai urutan penulisan, sama seperti terminal. Perbedaannya baru terlihat ketika salah satu aliran dialihkan. Perintah berikut menyembunyikan stderr, sehingga hanya tiga baris INFO yang tampil.
# hanya aliran stdout, baris ERROR dari stderr disembunyikan
python3 aliran-log.py 2>/dev/null08:30:01 INFO Aplikasi catatan dimulai pada port 8000
08:30:01 INFO Memuat 12 catatan dari penyimpanan
08:30:02 INFO Menyimpan catatan baru dari CitraKetika aplikasi ini berjalan sebagai proses utama sebuah container, daemon merekam kedua aliran sekaligus. Keluaran docker logs catatan-app kemudian berbentuk sama dengan keluaran demo pertama di atas, termasuk baris ERROR-nya. Kesalahan aplikasi pun tetap terlihat dari luar container, tanpa perlu membuka sesi di dalamnya.
Pembacaan log yang efektif mengikuti pola yang sama pada hampir semua kasus. Mulailah dari baris terakhir melalui --tail, karena penyebab kegagalan hampir selalu berada dekat dengan pesan terakhir. Gunakan --since ketika waktu kejadiannya diketahui, dan -f ketika gejalanya sedang berulang. Level yang tertulis pada setiap baris, INFO untuk peristiwa normal dan ERROR untuk kegagalan, mempermudah pencarian baris penting pada log yang panjang.
Ringkasan#
- Docker menangkap stdout dan stderr proses utama melalui logging driver, sedangkan driver bawaan
json-filemenyimpan rekamannya sebagai berkas di host. docker logsmenampilkan rekaman tersebut, dengan-funtuk mengikuti baris baru,--tailuntuk mengambil bagian akhir, dan--sinceuntuk membatasi rentang waktu.- Aplikasi di dalam container harus menulis log ke stdout dan stderr, sebab berkas log di dalam container tidak terbaca dan hilang bersama container.
Referensi#
- docker container logs — Docker Docs
— Rujukan opsi
--follow,--tail,--since, dan--timestampsbeserta contoh format waktunya. - docker container run — Docker Docs
— Rujukan opsi
-dyang menjalankan container di latar sehingga log dibaca lewatdocker logs.