Как правильно очистить логи для контейнера Docker?

210

Я использую, docker logs [container-name]чтобы увидеть журналы конкретного контейнера.

Есть ли элегантный способ очистить эти журналы?

Юсуф Майга
источник
14
Вы можете узнать размер логов черезsudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log"
Даниэль Ф

Ответы:

251

Из этого вопроса есть одна строка, которую вы можете запустить:

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

или есть аналогичная команда усечения:

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

Я не большой поклонник ни одного из них, так как они изменяют файлы Docker напрямую. Удаление внешнего журнала может произойти, когда Docker записывает данные в формате json в файл, что приводит к появлению частичной строки и нарушению возможности чтения любых журналов из docker logscli.

Вместо этого вы можете сделать так, чтобы Docker автоматически поворачивал журналы для вас. Это делается с помощью дополнительных флагов для dockerd, если вы используете драйвер ведения журнала JSON по умолчанию :

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

Вы также можете установить это как часть вашего файла daemon.json вместо изменения ваших скриптов запуска:

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

Эти параметры должны быть настроены с правами root. Обязательно запустите systemctl reload dockerпосле изменения этого файла, чтобы применить настройки. Этот параметр будет по умолчанию для всех вновь создаваемых контейнеров. Обратите внимание, что существующие контейнеры необходимо удалить и создать заново, чтобы получить новые ограничения журнала.


Аналогичные параметры журнала могут быть переданы отдельным контейнерам, чтобы переопределить эти значения по умолчанию, что позволяет вам сохранять больше или меньше журналов для отдельных контейнеров. Из docker runэтого выглядит:

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

или в файле композиции:

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

Для дополнительной экономии места вы можете переключиться с драйвера журнала json на «локальный» драйвер журнала. Он принимает те же параметры max-size и max-file, но вместо сохранения в json использует двоичный синтаксис, который быстрее и меньше. Это позволяет хранить больше журналов в одном файле размера. Запись daemon.json для этого выглядит так:

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

Недостатком локального драйвера являются внешние парсеры / пересылки журналов, которые зависят от прямого доступа к журналам json, больше не будут работать. Поэтому, если вы используете такой инструмент, как filebeat для отправки в Elastic, или универсальный перенаправитель Splunk, я бы избегал «локального» драйвера.

У меня есть немного больше об этом в моей презентации Tips and Tricks .

BMitch
источник
6
Я сделал, service docker restart который сам по себе не работал. Также пришлось брендировать создание новых контейнеров, прежде чем оно вступило в силу. то есть, просто подняв старые контейнеры, вы не применили новую регистрацию
Robbo_UK
Я использую Docker 1.13.1, и 'docker inspect --format =' {{. LogPath}} '<идентификатор контейнера>' возвращает пустую строку ("") .... но я все еще получаю вывод из ' Докер регистрирует <идентификатор контейнера> '?!? Откуда это происходит и как мне это очистить ??
Джей Аллен
@JDAllen 1.13.1 давно не поддерживается. У меня нет такой старой системы, чтобы просматривать их результаты.
BMitch
А еще лучше будет echo -n > .... В любом случае, я бы хотел иметь больше контроля над моими журналами. Например, после перезапуска docker-compose мне бы хотелось иметь механизм, позволяющий что-то делать с сохраненными журналами.
NarūnasK
2
@AlexisWilke, если вы можете остановить докер, то вы, вероятно, сможете остановить свой контейнер. Если вы можете сделать последнее, то мой совет - воссоздать контейнер с параметрами ведения журнала. В новом контейнере нет старых журналов, и новые журналы будут автоматически обновляться, что решает как краткосрочные, так и долгосрочные проблемы одновременно.
BMitch
227

Использование:

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

Вам может понадобиться sudo

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

ссылка Джефф С. Как правильно очистить логи для контейнера Docker?

Справка: усечение файла во время его использования (Linux)

duketwo
источник
4
усечение: не могу открыть «/var/lib/docker/containers/*/*-json.log» для записи: нет такого файла или каталога
BTR
2
@BTRNaidu вы должны запустить его как root / sudo, containersиначе содержимое недоступно.
Спидон
25
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"- работал для меня
Джефф С.
7
Проигнорируйте двух профессионалов выше. Если вы не уверены, вы можете просто проверить с помощью "ls /var/lib/docker/containers/*/*-json.log", что именно усекается.
duketwo
1
после очистки лог файла я получаю эту ошибку:error from daemon in stream: Error grabbing logs: invalid character '\x00' looking for beginning of value
arcol
42

В Docker для Windows и Mac, а также, возможно, и других, можно использовать опцию tail. Например:

docker logs -f --tail 100

Таким образом, отображаются только последние 100 строк, и вам не нужно сначала просматривать 1M строк ...

(И, следовательно, удаление журнала, вероятно, не требуется)

Эгберт Ниероп
источник
12
Идея состоит в том, чтобы очистить файлы журналов, а не печатать последние n строк файлов журналов
Юссуф Майга,
41
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"
Ричард
источник
4
Чтобы получить размер журналов sudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log", чтобы получить только общий размер журналовsudo sh -c "du -ch /var/lib/docker/containers/*/*-json.log | grep total"
Даниэль Ф
Есть ли проблемы с тем, что dockerd / aufs не знают и не могут удалить повернутые файлы журнала?
ThorSummoner
Эта команда работала для меня, тогда как другие команды в этом SO - нет. Если это имеет значение, я запускаю Docker версии 18 на CentOS 7
Tundra Fizz
27

Вы можете настроить logrotate для периодической очистки журналов.

Файл примера в /etc/logrotate.d/docker-logs

/var/lib/docker/containers/*/*.log {
 rotate 7
 daily
 compress
 size=50M
 missingok
 delaycompress
 copytruncate
}
AlexPnt
источник
и как мне это использовать? используется по умолчанию с docker run? файл /etc/logrotate.d/docker-logsне существует, я должен его создать?
Carlos.V
Вы должны вызвать утилиту logrotate (logrotate <config-file>), и она прочитает вашу конфигурацию и запустит очистку. Например, вы можете установить его как задание cron.
AlexPnt
Проблема с этим в том, что он может быть неправильно синхронизирован с тем, что делает докер. Использование докера, вероятно, намного мудрее. ( "log-opts"как показано BMitch)
Алексис Уилк
12

Docker4Mac, решение 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

Первая строка получает путь к файлу журнала, аналогично принятому ответу.

Вторая строка использует это, nsenterчто позволяет вам запускать команды в xhyveвиртуальной машине, которые являются серверами в качестве хоста для всех док-контейнеров под Docker4Mac. Команда, которую мы запускаем, знакома truncate -s0 $LOGPATHиз ответов, не относящихся к Mac.

Если вы используете docker-compose, первая строка становится:

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

и <service>имя службы из вашего docker-compose.ymlфайла.

Спасибо https://github.com/justincormack/nsenter1 за nsenterхитрость.

elifiner
источник
4
И чтобы обрезать журналы всех контейнеров, вы можете использовать подстановочный знак оболочки, как показано в других ответах, так что это всего лишь одна команда: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

Вы не можете сделать это напрямую через команду Docker.

Вы можете либо ограничить размер журнала, либо использовать скрипт для удаления журналов, связанных с контейнером. Вы можете найти примеры сценариев здесь (читайте снизу): Функция: Возможность очистить историю журнала # 1083

Ознакомьтесь с разделом ведения журнала в справочнике файлов docker-compose, где вы можете указать параметры (например, ротацию журналов и ограничение размера журналов) для некоторых драйверов ведения журналов.

Тристан
источник
7

Как пользователь root , попробуйте выполнить следующее:

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

или

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

или

echo "" > /var/lib/docker/containers/*/*-json.log
Мэтсон Кепсон
источник
6

На моих серверах Ubuntu даже как sudo я получу Cannot open ‘/var/lib/docker/containers/*/*-json.log’ for writing: No such file or directory

Но расчесывание докера проверяет и усекает ответы:

sudo truncate -s 0 `docker inspect --format='{{.LogPath}}' <container>`
aqwan
источник
2

Я предпочитаю это (из решений выше):

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

Однако я использую несколько систем (например, Ubuntu 18.x Bionic), где этот путь не работает должным образом. Docker устанавливается через Snap, поэтому путь к контейнерам больше похож на:

truncate -s 0 /var/snap/docker/common/var-lib-docker/containers/*/*-json.log
igraczech
источник
1

Вы также можете указать параметры log-opts в docker runкомандной строке, например:

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

или в docker-compose.yml, как это

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

Кредиты: https://medium.com/@Quigley_Ja/rotating-docker-logs-keeping-your-overlay-folder-small-40cfa2155412 (Джеймс Куигли)

Даг Баардсен
источник
Значения параметров должны быть заключены в кавычки (т.е. "5"и "10m"соответственно), как показано здесь для глобального файла daemon.json, но то же самое для docker-compose.yml. В обоих случаях это повлияет только на вновь созданные контейнеры.
Адриан В.
@AdrianW: docker-compose.yml кавычки не нужны. Это совершенно разные форматы файлов. И да, вы правы: команды «docker run» и параметры docker-compose влияют только на вновь созданные контейнеры - в отличие от ответа с большинством голосов, который затрагивает только перезапущенные демоны dockerd и доступен только через root-доступ. Мой ответ должен показывать гораздо более простой и обновленный путь, чем редактирование, чем перезапуск всего процесса dockerd.
Даг Баардсен
Без кавычек я получаю: ОШИБКА: для приложения Невозможно создать контейнер для приложения-службы: json: не могу удалить номер в поле структуры Go LogConfig.Config типа string Если я цитирую вот так: "5"это работает. 10mРабота , не цитируя действительно.
Адриан З
Похоже, что есть разница между Docker для Windows и Docker для Linux. На последнем я должен заключить значения в кавычки. Не по прежнему. Обновлено описание, чтобы соответствовать обоим. Спасибо, @AdrianW
Даг Баардсен
0

Docker для пользователей Mac, вот решение:

    1. Найти путь к файлу журнала по:

      $ docker inspect | grep log

    1. SSH в докер (предположим, что имя default, если нет, запустите, docker-machine lsчтобы узнать):

      $ docker-machine ssh default

    1. Изменить пользователя root ( ссылка ):

      $ sudo -i

    1. Удалить содержимое файла журнала:

      $ echo "" > log_file_path_from_step1

Цзиньсун Ли
источник
2
Docker-машина не работает с Docker для Mac. Вместо этого вы можете запустить "Docker запустить -ti -v / вар / Библиотека / грузчик / контейнеры: / вар / Inception CentOS Баш" , а затем "усеченный --size 0 /var/inception/08d29a7d469232cfef4456dc6eebcbf313bf01ba73e479520a036150c5ab84de/08d29a7d469232cfef4456dc6eebcbf313bf01ba73e479520a036150c5ab84de-json.log"
Джамшид
Вы можете использовать docker exec -it default shдля ввода оболочки sh в контейнер. Однако многие контейнеры неявно делают sudoкоманду доступной.
Даг Баардсен