Это руководство поможет настроить автоматическое удаление старых лог-файлов контейнера Ринго. Ротация логов предотвращает переполнение дискового пространства и упрощает администрирование системы.
В результате выполнения инструкции у вас будет:
Скрипт выполняет следующие действия:
roll-deploy-backend запущен, директория /logs существует внутри контейнераВыберите вариант в зависимости от того, как запущен Docker на вашем сервере:
Если вы не уверены, какой вариант используется, выполните команду:
docker info | grep -i root
Если в выводе есть rootless, используйте Вариант 2. В противном случае — Вариант 1.
Этот вариант подходит, если Docker установлен стандартным способом и работает от пользователя root.
Создайте файл скрипта:
sudo nano /usr/local/sbin/docker-log-rotate.sh
Вставьте следующий код:
#!/usr/bin/env bash
set -euo pipefail
########################################
# Config
########################################
CONTAINER_NAME="roll-deploy-backend"
LOG_DIR="/logs"
MAX_MB=100 # total size limit
MAX_DAYS=30 # retention days
DEBUG=0 # 1 = dry-run
########################################
# Helpers
########################################
dexec() {
docker exec -i "$CONTAINER_NAME" sh -c "$*"
}
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
safe_delete() {
local f="$1"
if [ "$DEBUG" -eq 1 ]; then
log "[DEBUG] would delete: $f"
else
dexec "rm -f '$f'"
log "deleted: $f"
fi
}
########################################
# Preflight checks
########################################
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log "error: container ${CONTAINER_NAME} not running"
exit 1
fi
if ! dexec "[ -d '$LOG_DIR' ]"; then
log "error: log directory $LOG_DIR not found in container"
exit 1
fi
########################################
# Identify files
########################################
FILES=$(dexec "ls -1t $LOG_DIR" || true)
if [ -z "$FILES" ]; then
log "no log files found"
exit 0
fi
# the first file in ls -t is the active one
ACTIVE_FILE=$(echo "$FILES" | head -n1)
log "active log file: $ACTIVE_FILE"
########################################
# Time-based cleanup
########################################
log "running time-based cleanup: older than $MAX_DAYS days"
THRESH=$(date -d "$MAX_DAYS days ago" +%s)
for file in $(dexec "ls -1 $LOG_DIR"); do
[ "$file" = "$ACTIVE_FILE" ] && continue
TS=$(dexec "stat -c %Y $LOG_DIR/$file" || echo 0)
if [ "$TS" -lt "$THRESH" ]; then
safe_delete "$LOG_DIR/$file"
fi
done
########################################
# Size-based cleanup
########################################
get_size_mb() {
dexec "du -sm $LOG_DIR | cut -f1"
}
CUR_SIZE=$(get_size_mb)
log "current log size: ${CUR_SIZE}MB"
if [ "$CUR_SIZE" -le "$MAX_MB" ]; then
log "size is within limit ($MAX_MB MB)"
exit 0
fi
log "running size-based cleanup: limit $MAX_MB MB"
# sort oldest last: reverse chronological order, skip active file
FILES_SORTED=$(echo "$FILES" | tail -n +2 | tac)
for f in $FILES_SORTED; do
CUR_SIZE=$(get_size_mb)
[ "$CUR_SIZE" -le "$MAX_MB" ] && break
safe_delete "$LOG_DIR/$f"
done
CUR_SIZE=$(get_size_mb)
log "final log size: ${CUR_SIZE}MB"
exit 0
Отредактируйте переменные в начале скрипта при необходимости:
CONTAINER_NAME — название контейнера backend (по умолчанию roll-deploy-backend)LOG_DIR — путь к директории логов внутри контейнера (по умолчанию /logs)MAX_MB — максимальный размер всех логов в мегабайтах (по умолчанию 100)MAX_DAYS — срок хранения логов в днях (по умолчанию 30)DEBUG — режим отладки: 1 включает dry-run (показывает, какие файлы будут удалены, но не удаляет их), 0 — нормальная работаВыполните команды:
sudo chmod 750 /usr/local/sbin/docker-log-rotate.sh
sudo chown root:root /usr/local/sbin/docker-log-rotate.sh
Запустите скрипт вручную:
sudo /usr/local/sbin/docker-log-rotate.sh
Скрипт должен вывести информацию о текущем размере логов и удалённых файлах (если они превышают установленные лимиты).
Создайте файл сервиса:
sudo nano /etc/systemd/system/docker-log-rotate.service
Вставьте следующее содержимое:
[Unit]
Description=Ringo backend container log rotation
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/docker-log-rotate.sh
Пояснения:
After=docker.service — сервис запускается только после запуска DockerRequires=docker.service — сервис зависит от работы DockerType=oneshot — сервис выполняется один раз при каждом запускеСоздайте файл таймера:
sudo nano /etc/systemd/system/docker-log-rotate.timer
Вставьте следующее содержимое:
[Unit]
Description=Daily Ringo log rotation
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
Пояснения:
OnCalendar=daily — таймер запускается раз в суткиPersistent=true — если сервер был выключен в момент запуска, задача выполнится при включенииВыполните команды:
sudo systemctl daemon-reload
sudo systemctl enable --now docker-log-rotate.timer
Убедитесь, что таймер активен:
systemctl list-timers | grep docker-log-rotate
В выводе должна быть строка с информацией о следующем запуске.
Ручной запуск сервиса:
sudo systemctl start docker-log-rotate.service
Просмотр логов выполнения:
journalctl -u docker-log-rotate.service
Остановка таймера:
sudo systemctl stop docker-log-rotate.timer
Отключение автозапуска:
sudo systemctl disable docker-log-rotate.timer
Этот вариант подходит, если Docker запущен от непривилегированного пользователя (например, dockeruser).
Создайте директорию bin в домашнем каталоге пользователя:
mkdir -p ~/bin
Создайте файл скрипта:
nano ~/bin/docker-log-rotate.sh
Вставьте следующий код:
#!/usr/bin/env bash
set -euo pipefail
########################################
# Config
########################################
CONTAINER_NAME="roll-deploy-backend"
LOG_DIR="/logs"
MAX_MB=100 # total size limit
MAX_DAYS=30 # retention days
DEBUG=0 # 1 = dry-run
########################################
# Helpers
########################################
dexec() {
docker exec -i "$CONTAINER_NAME" sh -c "$*"
}
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
safe_delete() {
local f="$1"
if [ "$DEBUG" -eq 1 ]; then
log "[DEBUG] would delete: $f"
else
dexec "rm -f '$f'"
log "deleted: $f"
fi
}
########################################
# Preflight checks
########################################
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
log "error: container ${CONTAINER_NAME} not running"
exit 1
fi
if ! dexec "[ -d '$LOG_DIR' ]"; then
log "error: log directory $LOG_DIR not found in container"
exit 1
fi
########################################
# Identify files
########################################
FILES=$(dexec "ls -1t $LOG_DIR" || true)
if [ -z "$FILES" ]; then
log "no log files found"
exit 0
fi
# the first file in ls -t is the active one
ACTIVE_FILE=$(echo "$FILES" | head -n1)
log "active log file: $ACTIVE_FILE"
########################################
# Time-based cleanup
########################################
log "running time-based cleanup: older than $MAX_DAYS days"
THRESH=$(date -d "$MAX_DAYS days ago" +%s)
for file in $(dexec "ls -1 $LOG_DIR"); do
[ "$file" = "$ACTIVE_FILE" ] && continue
TS=$(dexec "stat -c %Y $LOG_DIR/$file" || echo 0)
if [ "$TS" -lt "$THRESH" ]; then
safe_delete "$LOG_DIR/$file"
fi
done
########################################
# Size-based cleanup
########################################
get_size_mb() {
dexec "du -sm $LOG_DIR | cut -f1"
}
CUR_SIZE=$(get_size_mb)
log "current log size: ${CUR_SIZE}MB"
if [ "$CUR_SIZE" -le "$MAX_MB" ]; then
log "size is within limit ($MAX_MB MB)"
exit 0
fi
log "running size-based cleanup: limit $MAX_MB MB"
# sort oldest last: reverse chronological order, skip active file
FILES_SORTED=$(echo "$FILES" | tail -n +2 | tac)
for f in $FILES_SORTED; do
CUR_SIZE=$(get_size_mb)
[ "$CUR_SIZE" -le "$MAX_MB" ] && break
safe_delete "$LOG_DIR/$f"
done
CUR_SIZE=$(get_size_mb)
log "final log size: ${CUR_SIZE}MB"
exit 0
Отредактируйте переменные в начале скрипта при необходимости (аналогично варианту 1).
Выполните команду:
chmod 750 ~/bin/docker-log-rotate.sh
Запустите скрипт вручную:
~/bin/docker-log-rotate.sh
Скрипт должен вывести информацию о текущем размере логов и удалённых файлах.
Создайте директорию для пользовательских сервисов:
mkdir -p ~/.config/systemd/user
Создайте файл сервиса:
nano ~/.config/systemd/user/docker-log-rotate.service
Вставьте следующее содержимое:
[Unit]
Description=Ringo log rotation (rootless)
[Service]
Type=oneshot
ExecStart=%h/bin/docker-log-rotate.sh
Пояснения:
%h — автоматически подставляется домашняя директория пользователяType=oneshot — сервис выполняется один раз при каждом запускеСоздайте файл таймера:
nano ~/.config/systemd/user/docker-log-rotate.timer
Вставьте следующее содержимое:
[Unit]
Description=Daily Ringo log rotation (rootless)
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
Выполните команды:
systemctl --user daemon-reload
systemctl --user enable --now docker-log-rotate.timer
Убедитесь, что таймер активен:
systemctl --user list-timers
В выводе должна быть строка с docker-log-rotate.timer.
Важно! Без этого шага таймер не будет работать, когда пользователь
dockeruserне залогинен в системе.
Выполните команду от имени root или через sudo:
sudo loginctl enable-linger dockeruser
Что делает эта команда:
Проверка выполнения команды:
loginctl show-user dockeruser | grep Linger
В выводе должно быть Linger=yes.
Ручной запуск сервиса:
systemctl --user start docker-log-rotate.service
Просмотр логов выполнения:
journalctl --user -u docker-log-rotate.service
Остановка таймера:
systemctl --user stop docker-log-rotate.timer
Отключение автозапуска:
systemctl --user disable docker-log-rotate.timer
Вы можете изменить параметры работы скрипта, отредактировав переменные в его начале:
Для увеличения лимита до 500 МБ:
MAX_MB=500
Для хранения логов 60 дней:
MAX_DAYS=60
Для проверки работы скрипта без фактического удаления файлов:
DEBUG=1
После изменения параметров всегда тестируйте скрипт вручную перед использованием с таймером.
Для варианта 1:
journalctl -u docker-log-rotate.service -n 50
Для варианта 2:
journalctl --user -u docker-log-rotate.service -n 50
Узнайте текущий размер директории с логами:
docker exec -i roll-deploy-backend du -sh /logs
Посмотрите все лог-файлы с датами:
docker exec -i roll-deploy-backend ls -lht /logs