Bagaimana cara menghapus log dengan benar untuk wadah Docker?

210

Saya gunakan docker logs [container-name]untuk melihat log dari wadah tertentu.

Apakah ada cara yang elegan untuk menghapus log ini?

Youssouf Maiga
sumber
14
Pada sidenote, Anda bisa mendapatkan ukuran log melaluisudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log"
Daniel F

Jawaban:

251

Dari pertanyaan ini ada satu garis yang dapat Anda jalankan:

echo "" > $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

atau ada perintah truncate yang serupa:

truncate -s 0 $(docker inspect --format='{{.LogPath}}' <container_name_or_id>)

Saya bukan penggemar berat dari mereka karena mereka memodifikasi file Docker secara langsung. Penghapusan log eksternal dapat terjadi saat buruh pelabuhan sedang menulis data diformat json ke file, menghasilkan garis parsial, dan melanggar kemampuan untuk membaca log dari docker logscli.

Sebagai gantinya, Anda dapat membuat Docker secara otomatis memutar log untuk Anda. Ini dilakukan dengan flag tambahan untuk dockerd jika Anda menggunakan driver logging JSON default :

dockerd ... --log-opt max-size=10m --log-opt max-file=3

Anda juga dapat mengatur ini sebagai bagian dari file daemon.json Anda alih-alih memodifikasi skrip startup Anda:

{
  "log-driver": "json-file",
  "log-opts": {"max-size": "10m", "max-file": "3"}
}

Opsi ini perlu dikonfigurasi dengan akses root. Pastikan untuk menjalankan systemctl reload dockersetelah mengubah file ini agar pengaturan diterapkan. Pengaturan ini kemudian akan menjadi default untuk setiap wadah yang baru dibuat. Catatan, wadah yang ada perlu dihapus dan dibuat ulang untuk menerima batas log yang baru.


Opsi log yang serupa dapat diteruskan ke masing-masing kontainer untuk menimpa default ini, memungkinkan Anda untuk menyimpan lebih banyak atau lebih sedikit log pada masing-masing kontainer. Dari docker runini terlihat seperti:

docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 ...

atau dalam file penulisan:

version: '3.7'
services:
  app:
    image: ...
    logging:
      options:
        max-size: "10m"
        max-file: "3"

Untuk penghematan ruang tambahan, Anda dapat beralih dari driver log json ke driver log "lokal". Dibutuhkan opsi max-size dan max-file yang sama, tetapi alih-alih menyimpannya di json ia menggunakan sintaks biner yang lebih cepat dan lebih kecil. Ini memungkinkan Anda untuk menyimpan lebih banyak log dalam file berukuran sama. Entri daemon.json untuk itu terlihat seperti:

{
  "log-driver": "local",
  "log-opts": {"max-size": "10m", "max-file": "3"}
}

Kelemahan dari driver lokal adalah parser / forwarder log eksternal yang bergantung pada akses langsung ke json log tidak lagi berfungsi. Jadi jika Anda menggunakan alat seperti filebeat untuk mengirim ke Elastic, atau forwarder universal Splunk, saya akan menghindari driver "lokal".

Saya mendapat sedikit lebih banyak tentang ini dalam presentasi Kiat dan Trik saya .

BMitch
sumber
6
Saya melakukan sesuatu service docker restart yang dengan sendirinya tidak berhasil. Juga harus membuat wadah baru sebelum diberlakukan. yaitu hanya memunculkan wadah lama tidak menerapkan logging baru
Robbo_UK
Saya menggunakan Docker 1.13.1, dan 'buruh pelabuhan memeriksa --format =' {{. LogPath}} '<container id>' mengembalikan string null ("") .... tapi saya masih mendapatkan output dari ' log buruh pelabuhan <container id> '?!? Dari mana datangnya dan bagaimana cara menghapusnya ??
JD Allen
@JDAllen 1.13.1 sudah lama tidak didukung. Saya tidak memiliki sistem yang setua itu untuk melihat hasil keluaran mereka.
BMitch
Akan lebih baik lagi echo -n > .... Bagaimanapun, saya ingin dapat memiliki kontrol lebih besar atas log saya. Sebagai contoh, setelah restart docker-compose , saya akan senang memiliki mekanisme untuk melakukan sesuatu dengan log yang diawetkan.
NarūnasK
2
@AlexisWilke jika Anda dapat menghentikan buruh pelabuhan, maka kemungkinan Anda dapat menghentikan kontainer Anda. Jika Anda dapat melakukan yang terakhir, maka menciptakan kembali wadah dengan opsi logging akan menjadi saran saya. Wadah baru tidak memiliki log lama, dan log baru akan digulung secara otomatis, sekaligus menyelesaikan masalah jangka pendek dan jangka panjang.
BMitch
227

Menggunakan:

truncate -s 0 /var/lib/docker/containers/*/*-json.log

Anda mungkin perlu sudo

sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"

ref. Jeff S. Bagaimana menghapus log dengan benar untuk wadah Docker?

Referensi: Memotong file saat sedang digunakan (Linux)

duketwo
sumber
4
truncate: tidak dapat membuka '/var/lib/docker/containers/*/*-json.log' untuk menulis: Tidak ada file atau direktori seperti itu
BTR Naidu
2
@ BTRNaidu Anda harus menjalankannya sebagai root / sudo, konten containerstidak tersedia sebaliknya.
spydon
25
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"- bekerja untuk saya
Jeff S.
7
Abaikan dua profesional di atas. Jika Anda tidak yakin, Anda dapat mengecek "ls /var/lib/docker/containers/*/*-json.log" apa yang sedang dipotong.
duketwo
1
setelah mengosongkan file log, saya mendapatkan kesalahan ini:error from daemon in stream: Error grabbing logs: invalid character '\x00' looking for beginning of value
arcol
42

Pada Docker untuk Windows dan Mac, dan mungkin yang lain juga, dimungkinkan untuk menggunakan opsi ekor. Sebagai contoh:

docker logs -f --tail 100

Dengan cara ini, hanya 100 baris terakhir yang ditampilkan, dan Anda tidak perlu terlebih dahulu menggulir melalui garis 1M ...

(Dan dengan demikian, menghapus log mungkin tidak perlu)

Egbert Nierop
sumber
12
Idenya adalah membersihkan file log dan tidak mencetak n baris terakhir file log
Youssouf Maiga
41
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"
richard
sumber
4
Untuk mendapatkan ukuran log sudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log", hanya mendapatkan total ukuran logsudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log | grep total"
Daniel F
Apakah ada masalah dengan dockerd / auf yang tidak tahu dan tidak mampu menghapus file log yang diputar?
ThorSummoner
Perintah ini bekerja untuk saya sedangkan perintah lain dalam SO ini belum. Jika itu penting, saya menjalankan Docker versi 18 di CentOS 7
Tundra Fizz
27

Anda dapat mengatur logrotate untuk menghapus log secara berkala.

Contoh file di /etc/logrotate.d/docker-logs

/var/lib/docker/containers/*/*.log {
 rotate 7
 daily
 compress
 size=50M
 missingok
 delaycompress
 copytruncate
}
AlexPnt
sumber
dan bagaimana saya menggunakan ini? digunakan sebagai default dengan docker run? file /etc/logrotate.d/docker-logstidak ada, saya harus membuatnya?
Carlos.V
Anda harus memanggil utilitas logrotate (logrotate <config-file>) dan itu akan membaca konfigurasi Anda dan menjalankan pembersihan. Anda juga dapat mengaturnya sebagai tugas cron misalnya.
AlexPnt
Masalah dengan ini adalah bahwa itu mungkin tidak disinkronkan dengan benar dengan apa yang dilakukan buruh pelabuhan. Menggunakan fasilitas buruh pelabuhan mungkin jauh lebih bijaksana. ( "log-opts"seperti yang ditunjukkan oleh BMitch)
Alexis Wilke
12

Docker4Mac, solusi 2018:

LOGPATH=$(docker inspect --format='{{.LogPath}}' <container_name_or_id>)
docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i -- truncate -s0 $LOGPATH

Baris pertama mendapatkan jalur file log, mirip dengan jawaban yang diterima.

Baris kedua menggunakan nsenter yang memungkinkan Anda untuk menjalankan perintah di xhyveVM yang server sebagai tuan rumah untuk semua kontainer buruh pelabuhan di bawah Docker4Mac. Perintah yang kami jalankan adalah jawaban yang tidak asing truncate -s0 $LOGPATHuntuk Mac.

Jika Anda menggunakan docker-compose , baris pertama menjadi:

local LOGPATH=$(docker inspect --format='{{.LogPath}}' $(docker-compose ps -q <service>))

dan <service>nama layanan dari docker-compose.ymlfile Anda .

Berkat https://github.com/justincormack/nsenter1 untuk nsentercaranya.

Elifiner
sumber
4
Dan untuk memotong log dari semua kontainer, Anda dapat menggunakan shell wildcard seperti yang ditunjukkan dalam jawaban lain, jadi itu hanya satu perintah:docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i -- sh -c 'truncate -s0 /var/lib/docker/containers/*/*-json.log'
bradenm
11

Anda tidak dapat melakukan ini secara langsung melalui perintah Docker.

Anda dapat membatasi ukuran log, atau menggunakan skrip untuk menghapus log yang terkait dengan sebuah wadah. Anda dapat menemukan contoh skrip di sini (baca dari bawah): Fitur: Kemampuan untuk menghapus riwayat log # 1083

Lihat bagian logging dari referensi file komposisi buruh pelabuhan, di mana Anda dapat menentukan opsi (seperti rotasi log dan batas ukuran log) untuk beberapa driver logging.

Tristan
sumber
7

Sebagai pengguna root , cobalah untuk menjalankan yang berikut:

>  /var/lib/docker/containers/*/*-json.log

atau

cat /dev/null > /var/lib/docker/containers/*/*-json.log

atau

echo "" > /var/lib/docker/containers/*/*-json.log
matson kepson
sumber
6

Di server Ubuntu saya bahkan sebagai sudo saya akan dapatkan Cannot open ‘/var/lib/docker/containers/*/*-json.log’ for writing: No such file or directory

Tetapi menyisir buruh pelabuhan memeriksa dan memotong jawaban berhasil:

sudo truncate -s 0 `docker inspect --format='{{.LogPath}}' <container>`
aqwan
sumber
2

Saya lebih suka yang ini (dari solusi di atas):

truncate -s 0 /var/lib/docker/containers/*/*-json.log

Namun saya menjalankan beberapa sistem (Ubuntu 18.x Bionic misalnya), di mana jalur ini tidak berfungsi seperti yang diharapkan. Docker dipasang melalui Snap, sehingga jalur ke wadah lebih seperti:

truncate -s 0 /var/snap/docker/common/var-lib-docker/containers/*/*-json.log
igraczech
sumber
1

Anda juga dapat menyediakan parameter log-opts pada docker runbaris perintah, seperti ini:

docker run --log-opt max-size=10m --log-opt max-file=5 my-app:latest

atau di docker-compose.yml seperti ini

my-app:
image: my-app:latest
logging:
    driver: "json-file"
    options:
        max-file: "5"
        max-size: 10m

Kredit: https://medium.com/@Quigley_Ja/rotating-docker-logs-keeping-your-overlay-folder-small-40cfa2155412 (James Quigley)

Dag Baardsen
sumber
Nilai parameter harus dikutip (yaitu "5"dan "10m"masing - masing), seperti yang ditunjukkan di sini untuk file daemon.json global, tetapi itu sama untuk docker-compose.yml. Dalam kedua kasus, itu hanya akan mempengaruhi wadah yang baru dibuat.
Adrian W
@AdrianW: docker-compose.yml tidak perlu tanda kutip. Ini adalah format file yang sama sekali berbeda. Dan ya, Anda benar: perintah "buruh pelabuhan menjalankan" dan parameter susunan buruh pelabuhan hanya memengaruhi wadah yang baru dibuat - sebagai lawan dari jawaban di sini dengan suara terbanyak yang memengaruhi hanya me-restart dockerd daemon dan tersedia melalui akses root saja. Jawaban saya seharusnya menunjukkan jalur yang jauh lebih sederhana dan diperbarui daripada mengedit daripada memulai kembali seluruh proses dockerd.
Dag Baardsen
Tanpa tanda kutip, saya dapat: ERROR: untuk aplikasi Tidak dapat membuat wadah untuk aplikasi layanan: json: tidak dapat menghapus nomor ke bidang Go struct LogConfig.Config dari tipe string Jika saya mengutip seperti ini: "5"berfungsi. The 10mbekerja tanpa mengutip memang.
Adrian W
Sepertinya ada perbedaan antara Docker untuk Windows dan Docker untuk Linux. Pada yang terakhir, saya harus menyertakan nilai dalam tanda kutip. Bukan pada yang pertama. Deskripsi yang diperbarui sesuai dengan keduanya. Terima kasih, @AdrianW
Dag Baardsen
0

Docker untuk pengguna Mac, berikut solusinya:

    1. Temukan jalur file log dengan:

      $ docker inspect | grep log

    1. SSH ke mesin buruh pelabuhan (misalkan namanya default, jika tidak, jalankan docker-machine lsuntuk mencari tahu):

      $ docker-machine ssh default

    1. Ubah ke root pengguna ( referensi ):

      $ sudo -i

    1. Hapus konten file log:

      $ echo "" > log_file_path_from_step1

Jinsong Li
sumber
2
mesin docker tidak bekerja dengan Docker untuk Mac. Anda malah dapat menjalankan "docker run -ti v / var / lib / buruh pelabuhan / kontainer: / var / awal CentOS bash" kemudian "truncate --size 0 /var/inception/08d29a7d469232cfef4456dc6eebcbf313bf01ba73e479520a036150c5ab84de/08d29a7d469232cfef4456dc6eebcbf313bf01ba73e479520a036150c5ab84de-json.log"
Jamshid
Anda dapat menggunakan docker exec -it default shuntuk memasukkan shell sh dalam wadah. Namun, banyak kontainer tidak secara implisit membuat sudoperintah tersedia.
Dag Baardsen