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

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

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

24 ответа

Решение

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

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

Я не большой поклонник модификации файлов Докера напрямую. Вы можете сделать так, чтобы 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"}
}

Обязательно запустите systemctl reload docker после изменения этого файла, чтобы применить настройки.

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

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

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

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

например, журналы докера -f --tail 100 msftmodbus

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

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

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

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

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

/var/lib/docker/containers/*/*.log {
 rotate 7
 daily
 compress
 size=50M
 missingok
 delaycompress
 copytruncate
}

Вы также можете указать параметры 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 (Джеймс Куигли)

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 трюк.

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

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

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

Вот кроссплатформенное решение для очистки журналов контейнера докеров:

docker run --rm -v /var/lib/docker:/var/lib/docker alpine sh -c "echo '' > $(docker inspect --format='{{.LogPath}}' CONTAINER_NAME)"

Вставьте это в свой терминал и измените CONTAINER_NAME на желаемое имя или идентификатор контейнера.

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

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

или же

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

или же

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

На моих серверах 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>`
      sudo find /var/lib/docker/containers/ -type f -name "*.log" -delete

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

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

Делюсь этим, поскольку другие ответы кажутся слишком сложными.

Самый простой способ удалить журналы связанных контейнеров — принудительно воссоздать их.

      docker-compose up -d [container] --force-recreate

Затем бегdocker-compose logs [container]должно привести к появлению только новых записей с момента открытия контейнера.

Не уверен, что это полезно для вас, но удаление контейнера всегда помогает.

Итак, если вы используете docker-compose для своей настройки, вы можете просто использовать docker-compose down && docker-compose up вместо того docker-compose restart. При правильной настройке (обязательно используйте монтирование томов для постоянных данных) таким образом вы не потеряете никаких данных.

Конечно, это больше, чем требовалось. Но есть различные ситуации, когда другие ответы не могут помочь (при использовании удаленного докер-сервера или работе на машине с Windows)

САЛАМ
Благодаря ответу @BMitch, я только что написал сценарий оболочки для очистки журналов всех контейнеров:

      #!/bin/bash
ids=$(docker ps -a --format='{{.ID}}')
for id in $ids
do
        echo $(docker ps -a --format='{{.ID}} ### {{.Names}} ### {{.Image}}' | fgrep $id)
        truncate -s 0 $(docker inspect --format='{{.LogPath}}' $id)
        ls -llh $(docker inspect --format='{{.LogPath}}' $id)
done

Я АЛИ.

Linux / Ubuntu:

Если у вас несколько контейнеров, и вы хотите удалить только один журнал, но не другие.

  • ( Если у вас есть такие проблемы, как "Permission denied", сначала сделайте sudo su. )
  • Перечислите все контейнеры:
  • Найдите желаемый контейнер и скопируйте CONTAINER ID. Пример: .
  • Папки контейнеров и настоящие имена длиннее, но первые 12 символов - это те, которые приводят к docker ps -a.
  • Удалите только этот журнал: > /var/lib/docker/containers/E1X2A3M4P5L6*/E1X2A3M4P5L6*-json.log (Заменять E1X2A3M4P5L6за ваш результат !! )

Как видите, внутри /containers - это контейнеры, а журналы имеют то же имя, но с -json.logв конце. Вам просто нужно знать эти первые 12 символов, потому что * означает «что угодно».

Мне нужно было что-то, что я мог бы запустить как одну команду, вместо того, чтобы писать docker psи копирование каждого идентификатора контейнера и выполнение команды несколько раз. Я адаптировал ответ BMitch и подумал, что поделюсь, если кому-то это может пригодиться.

Смешивание xargs кажется, снимает то, что мне нужно здесь:

docker ps --format='{{.ID}}' | \
  xargs -I {} sh -c 'echo > $(docker inspect --format="{{.LogPath}}" {})'

Это захватывает каждый идентификатор контейнера, указанный docker ps(сотрет ваши журналы для любого контейнера в этом списке!), направляет его в xargs а затем отображает пустую строку, чтобы заменить путь к журналу контейнера.

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

Если вам нужно сохранить резервную копию файлов журнала перед их удалением, я создал сценарий, который выполняет следующие действия (вы должны запустить его с помощью sudo) для указанного контейнера:

  1. Создает папку для хранения сжатых файлов журнала в качестве резервной копии.
  2. Ищет идентификатор работающего контейнера (указанный в имени контейнера).
  3. Скопируйте файл журнала контейнера в новое место (папку на шаге 1), используя случайное имя.
  4. Сожмите предыдущий файл журнала (для экономии места).
  5. Обрезает файл журнала контейнера до определенного размера, который вы можете определить.

Примечания:

  • Он использует команду shuf . Убедитесь, что он есть в вашем дистрибутиве Linux, или замените его на другой генератор случайных чисел, поддерживаемый bash.
  • Перед использованием измените переменную CONTAINER_NAME, чтобы она соответствовала вашему работающему контейнеру; это может быть частичное имя (не обязательно точно совпадающее имя).
  • По умолчанию он усекает файл журнала до 10 МБ (10 мегабайт), но вы можете изменить этот размер, изменив переменную SIZE_TO_TRUNCATE.
  • Он создает папку по пути: / opt / your-container-name / logs , если вы хотите хранить сжатые журналы в другом месте, просто измените переменную LOG_FOLDER.
  • Перед запуском в продакшн выполните несколько тестов.
      #!/bin/bash
set -ex

############################# Main Variables Definition:
CONTAINER_NAME="your-container-name"
SIZE_TO_TRUNCATE="10M"

############################# Other Variables Definition:
CURRENT_DATE=$(date "+%d-%b-%Y-%H-%M-%S")
RANDOM_VALUE=$(shuf -i 1-1000000 -n 1)
LOG_FOLDER="/opt/${CONTAINER_NAME}/logs"
CN=$(docker ps --no-trunc -f name=${CONTAINER_NAME} | awk '{print $1}' | tail -n +2)
LOG_DOCKER_FILE="$(docker inspect --format='{{.LogPath}}' ${CN})"
LOG_FILE_NAME="${CURRENT_DATE}-${RANDOM_VALUE}"

############################# Procedure:
mkdir -p "${LOG_FOLDER}"
cp ${LOG_DOCKER_FILE} "${LOG_FOLDER}/${LOG_FILE_NAME}.log"
cd ${LOG_FOLDER}
tar -cvzf "${LOG_FILE_NAME}.tar.gz" "${LOG_FILE_NAME}.log"
rm -rf "${LOG_FILE_NAME}.log"
truncate -s ${SIZE_TO_TRUNCATE} ${LOG_DOCKER_FILE}

Вы можете создать задание cron для запуска предыдущего скрипта каждый месяц. Первый забег:

      sudo crontab -e

Введите a на клавиатуре, чтобы перейти в режим редактирования. Затем добавьте следующую строку:

      0 0 1 * * /your-script-path/script.sh

Хит побега для выхода из режима редактирования. Сохраните файл, набрав :wq и нажав Enter. Убедитесь, что у файла script.sh есть разрешения на выполнение.

Чтобы удалить / очистить журналы контейнера докеров, мы можем использовать команду ниже

$(docker inspect container_id | grep "LogPath" | cut -d "" "-f4) или $(docker inspect container_name | grep" LogPath "| cut -d" "" -f4)

На компьютерах с рабочим столом docker мы используем:truncate -s 0 //wsl.localhost/docker-desktop-data/data/docker/containers/*/*-json.log

Для дистрибутивов Linux вы можете использовать это, у меня работает этот путь:truncate -s 0 /var/lib/docker/containers/*/*-json.log

Если ваш хост-компьютер использует systemd , рассмотрите возможность использования драйвера журнала Journald .

Таким образом, вы получаете централизованное управление журналами вместо тихой регистрации в локальном неротируемом файле ( драйвер регистрации json-файла по умолчанию делает именно это ). В моем случае использование настроек докера по умолчанию привело к исчерпанию дискового пространства (файл журнала съеден более 7 ГБ).

Демон Journald можно легко настроить для ротации журналов, см. документацию.

docker system prune
запустите эту команду в командной строке

Другие вопросы по тегам