Пошук уроків, статей та іншого контенту
Налаштуєте збір, ротацію та перегляд логів контейнерів без неконтрольованого заповнення диска.
За замовчуванням Docker збирає все, що процес контейнера записує у:
stdout — стандартний вивід;
stderr — вивід помилок.
Переглянути ці повідомлення можна командою:
docker logs <container>Такий підхід зручний, але в production необмежене логування швидко заповнює диск. Особливо це небезпечно, якщо застосунок:
записує великі stack trace;
працює з високою кількістю запитів;
виводить службові повідомлення на кожен запит;
ніколи не видаляє старі журнали.
Логи контейнера мають бути:
доступними для перегляду;
обмеженими за розміром;
автоматично ротованими;
придатними для подальшої передачі в централізовану систему.
stdout і stderrУ контейнеризованих застосунках зазвичай не записують основні логи у файли всередині контейнера. Застосунок виводить їх у stdout або stderr, а Docker або зовнішня система збирає цей вивід.
Приклад простого контейнера, який генерує логи:
docker run -d \
--name demo-logger \
alpine:3.20 \
sh -c 'i=0; while true; do i=$((i + 1)); echo "$(date -Iseconds) INFO request_id=$i status=200"; sleep 1; done'Перегляд усіх логів:
docker logs demo-loggerПерегляд останніх 20 рядків:
docker logs --tail 20 demo-loggerПерегляд нових повідомлень у реальному часі:
docker logs --follow demo-loggerДодавання часових міток до виводу Docker:
docker logs --timestamps demo-loggerПоєднання параметрів:
docker logs --follow --tail 50 --timestamps demo-loggerВидалення тестового контейнера:
docker rm --force demo-loggerЛог повинен містити достатньо контексту для пошуку проблеми:
2026-09-02T10:15:42Z level=error request_id=8f31 status=500 message="database connection failed"Корисні поля:
рівень повідомлення: debug, info, warn, error;
час;
ідентифікатор запиту;
назва сервісу;
код відповіді;
короткий опис помилки.
Не слід записувати в логи:
паролі;
токени доступу;
ключі API;
повні дані банківських карток;
інші секрети.
Docker використовує logging driver для збереження та обробки логів контейнерів. Перевірити драйвер за замовчуванням можна так:
docker info --format '{{.LoggingDriver}}'Драйвер конкретного контейнера:
docker inspect --format '{{.HostConfig.LogConfig.Type}}' demo-loggerТиповим драйвером є json-file. У цьому випадку Docker зберігає повідомлення у файлах на диску хоста. Шлях до даних контейнера можна перевірити так:
docker inspect --format '{{.LogPath}}' demo-loggerНе варто редагувати або видаляти ці файли вручну під час роботи Docker. Для керування їхнім розміром потрібно налаштувати ротацію через logging driver.
json-fileДля контейнера можна встановити максимальний розмір одного файлу журналу та кількість збережених файлів:
docker run -d \
--name demo-logger \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=5 \
alpine:3.20 \
sh -c 'while true; do echo "$(date -Iseconds) application message"; sleep 1; done'У цьому прикладі:
max-size=10m — один файл не перевищує 10 МБ;
max-file=5 — Docker зберігає до п’яти файлів;
загальний обсяг логів цього контейнера буде обмежений приблизно 50 МБ.
Ротація відбувається під час запису нових повідомлень. Якщо контейнер уже створено без потрібних параметрів, зміна налаштувань Docker не завжди змінить конфігурацію цього контейнера. Надійний спосіб — створити контейнер заново з новими параметрами.
Якщо всі або більшість контейнерів на хості мають використовувати однакові обмеження, logging driver можна налаштувати у файлі конфігурації Docker Engine.
Типовий шлях до файлу:
/etc/docker/daemon.jsonПриклад конфігурації:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}Після зміни конфігурації потрібно перевірити JSON і перезапустити Docker Engine:
sudo python3 -m json.tool /etc/docker/daemon.json
sudo systemctl restart dockerПісля перезапуску нові контейнери отримають ці параметри. Уже створені контейнери потрібно перевірити окремо та, за потреби, пересоздати.
Перевірка налаштування:
docker infoТакож можна перевірити logging driver нового контейнера:
docker run --rm alpine:3.20 true
docker ps -a --latest --format '{{.ID}} {{.Names}}'Для зміни logging driver існуючого контейнера зазвичай використовують такий порядок:
docker inspect demo-logger
docker rm --force demo-logger
docker run -d \
--name demo-logger \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=5 \
alpine:3.20 \
sh -c 'while true; do echo "$(date -Iseconds) application message"; sleep 1; done'Перед видаленням production-контейнера потрібно врахувати спосіб його розгортання та наявність persistent-даних.
У Docker Compose logging driver задають для кожного сервісу через секцію logging.
services:
app:
image: alpine:3.20
command: >
sh -c 'i=0;
while true;
do i=$((i + 1));
echo "$(date -Iseconds) INFO request_id=$i status=200";
sleep 1;
done'
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"Запуск:
docker compose up -dПерегляд логів сервісу:
docker compose logs --tail 50 appПерегляд у реальному часі:
docker compose logs --follow appПісля зміни параметрів logging driver сервіс потрібно пересоздати:
docker compose up -d --force-recreate appПеревірка конфігурації контейнера:
docker inspect \
--format '{{json .HostConfig.LogConfig}}' \
"$(docker compose ps -q app)"docker logs --tail 100 --timestamps apidocker logs \
--since 30m \
--until 10m \
apiПараметри часу можуть бути відносними, наприклад 10m, 2h, або абсолютними датами у форматі, який підтримує Docker.
Для Compose:
docker compose logs --tail 100 --timestampsДля пошуку помилок у поточному виводі:
docker compose logs --no-color api | grep -i errorПараметр --no-color корисний для командного пошуку та перенаправлення в інші інструменти.
Загальна інформація про використання Docker:
docker system dfБільш детальна інформація:
docker system df --verboseРозмір каталогу Docker на Linux-хості:
sudo du -sh /var/lib/dockerРозмір каталогів із журналами контейнерів:
sudo du -sh /var/lib/docker/containers/* 2>/dev/nullУ production такі перевірки варто виконувати через моніторинг дискового простору, а не лише вручну після виникнення проблеми.
Створіть контейнер із малим лімітом для тестування:
docker run -d \
--name rotation-test \
--log-driver json-file \
--log-opt max-size=1m \
--log-opt max-file=3 \
alpine:3.20 \
sh -c 'while true; do printf "%0100d\n" 0; done'Перевірте налаштування:
docker inspect --format '{{json .HostConfig.LogConfig}}' rotation-testПеревірте файли логів:
sudo ls -lh "$(docker inspect --format '{{.LogPath}}' rotation-test)"У результаті кількість і розмір файлів мають відповідати заданим обмеженням. Після перевірки видаліть контейнер:
docker rm --force rotation-testДля невеликого хоста або тимчасового середовища достатньо:
виводити логи в stdout і stderr;
встановити max-size;
встановити max-file;
регулярно контролювати вільне місце.
Для production із кількома сервісами зазвичай потрібен централізований збір. У такій архітектурі:
контейнер пише логи в stdout або stderr;
Docker logging driver або агент збору передає їх назовні;
централізована система зберігає, індексує та шукає записи;
локальна ротація захищає диск хоста навіть у разі недоступності зовнішньої системи.
Централізований збір не скасовує локальні обмеження. Якщо зовнішня система тимчасово недоступна, черга або локальні файли все одно можуть зайняти весь диск.
Не всі контейнери мають однаковий обсяг логів. Наприклад:
для API може бути достатньо 10m і 5 файлів;
для worker із великою кількістю помилок потрібні суворіші обмеження;
для сервісу, який рідко пише логи, достатньо стандартних параметрів.
У Compose це можна налаштувати окремо:
services:
api:
image: example/api:1.0
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
worker:
image: example/worker:1.0
logging:
driver: json-file
options:
max-size: "5m"
max-file: "3"Важливо узгодити ці значення з реальною частотою логування та політикою зберігання. Надто малий ліміт ускладнить розслідування інцидентів, а надто великий може створити ризик заповнення диска.
Перед запуском контейнерів перевірте:
застосунок пише логи у stdout і stderr;
у логах немає секретів;
для кожного сервісу визначено logging driver;
встановлено max-size і max-file або інший механізм ротації;
після зміни конфігурації контейнери пересоздано;
налаштовано моніторинг вільного місця;
логи можна переглянути за часовим діапазоном;
передбачено спосіб передачі логів у централізовану систему;
перевірено поведінку під час великої кількості повідомлень.
Docker не побачить файл застосунку через docker logs. Якщо файлова модель справді необхідна, потрібен окремий процес або агент збору, який читає цей файл.
Для стандартної Docker-моделі краще налаштувати застосунок на вивід у stdout і stderr.
Команда docker logs не обмежує розмір журналу. Без max-size і max-file логи можуть поступово заповнити диск.
daemon.json без пересоздання контейнерівГлобальні налаштування застосовуються до нових контейнерів. Після зміни конфігурації перевіряйте вже запущені контейнери та пересоздавайте їх, якщо потрібно.
Видалення файлів у /var/lib/docker/containers вручну може призвести до некоректної роботи Docker. Керуйте розміром журналів через logging driver, а не через ручне очищення.
Логування кожного внутрішнього кроку на рівні info збільшує витрати на диск і централізоване сховище. Для production потрібно вибрати корисний рівень деталізації та окремо контролювати debug.
Повідомлення на кшталт failed без назви операції, ідентифікатора запиту або причини мало допомагають під час діагностики. Формат логів має бути послідовним і містити потрібні поля.
Контейнери мають виводити журнали у stdout і stderr.
docker logs використовується для перегляду та фільтрації виводу.
Для production необхідно обмежувати розмір логів через max-size і max-file.
Налаштування можна задати глобально у /etc/docker/daemon.json або окремо для сервісу в Compose.
Після зміни logging driver уже створені контейнери потрібно перевірити та, за потреби, пересоздати.
Ротація захищає диск, але не замінює централізований збір логів.
Моніторинг вільного місця та перевірка реального розміру журналів є частиною експлуатації production-середовища.