Docker Ninja – Telegram
Docker Ninja
1.05K subscribers
30 photos
91 links
По всем вопросам обращаться к @nesudimov_eu
Download Telegram
Ты создаешь Dockerfile для веб-приложения. Нужно скопировать конфигурационный файл config.json из локальной папки /configs в контейнер по пути /app/config.json. Какую директиву использовать правильнее всего?
Anonymous Quiz
9%
VOLUME /configs/config.json /app/config.json
11%
ADD /configs/config.json /app/config.json
8%
RUN cp /configs/config.json /app/config.json
72%
COPY /configs/config.json /app/config.json
👌4👍2
Жди меня, и я вернусь

Пятница, конец недели, мозги уже настроены на выходные, а тут еще и контейнеры какие-то надо один за другим запускать - один отработал, врубить другой и тд. А настроенице то такое, чтобы весь мир подождал до понедельника, а дальше это уже проблемы завтрашнего Гомера...

Кажется, товарищам из команды разработки докера ничто человеческое не чуждо. Именно поэтому (я просто уверен) была придумана команда, которая может терпеливо ждать завершения контейнера и даже скажет, с каким кодом он завершился?

Прошу любить и жаловать - docker wait. Простая, но очень полезная команда для тех, кто любит порядок в своих скриптах! 🎯

Основы использования:
# Ждем завершения одного контейнера
docker wait my_container

# Ждем несколько контейнеров сразу
docker wait container1 container2 container3


Команда вернет exit code контейнера. 0 — все ОК, любое другое число — что-то пошло не так.

Зачем это нужно?

🔹В скриптах автоматизации часто нужно дождаться завершения одного контейнера перед запуском следующего. Представь: у тебя есть контейнер с миграциями БД, и только после их успешного завершения можно поднимать основное приложение.
🔹Тестовые пайплайны в CI/CD: запускается контейнер с тестами, а скрипт с помощью docker wait ожидает его завершения, чтобы по коду возврата определить, упали тесты или прошли успешно, и принять решение о продвижении сборки.
🔹Оркестрация зависимых сервисов: когда нужно гарантировать, что контейнер-инициатор какой-либо задачи (например, обработки данных) завершил работу, прежде чем запускать контейнер-потребитель результатов.

Помнишь наш пост про docker kill? Так вот, wait — его полная противоположность. Вместо принудительной остановки мы терпеливо ждем естественного завершения 🧘

Команда работает только с запущенными контейнерами. Если контейнер уже завершился, wait моментально вернет его последний exit code.

Простая команда, а сколько пользы для автоматизации! 🚀


🥷 Docker Ninja 🥷
🔥6👍2
🚦 Зависимые отношения 🚦

Ты пушишь в прод свежий docker-compose up -d, а через секунду получаешь unhealthy статус и сообщение в логах: "Connection to database failed". Вот это поворот... Твое веб-приложение стартануло быстрее PostgreSQL и упало так и не дождавшись готовности базы. Как бы сказал великий классик: "Ha, ha, classic"! Уж простите за тафтологию.

На такой случай имеем директиву depends_on!

Базовый пример:
services:
web:
image: nginx
depends_on:
- db
- redis

db:
image: postgres:15

redis:
image: redis:alpine


Польза данной диррективы в том, она гарантирует порядок запуска: сначала поднимутся db и redis, потом уже web.

Теперь веб дождется, когда контейнер базы стартанет и начнет стартовать! 🎯

Но есть нюанс — это НЕ означает, что PostgreSQL будет готов принимать коннекты! Как решать такие проблемы, разберем в следующих постах.

Зачем юзать?
🔹 Избегаешь race conditions между сервисами на уровне инфраструктуры
🔹 Контролируешь сложные зависимости (API → DB → Cache)
🔹 Спасаешься от факапов с "недоступной базой"

Ставь 🔥 если тоже страдал от преждевременных стартов!

🥷 Docker Ninja 🥷
👍9🔥4
👴🏼Тряхнем стариной👴🏼

Если говорить честно, то механизм depends_on существовал не всегда, но и у него были альтернативы.

Узнать, что за механизм и зачем тебе о нем знать, ты можешь нажав на кнопку ниже⬇️
🔥9
📚 Все дороги ведут в Registry 📚

Помнишь старые времена, когда образы передавали флешками и ссылками на Dropbox? Не помнишь?! И правильно, потому что никогда такого не было! Все потому, что разработчики docker придумали Docker Registry, который стал центральной нервной системой контейнерной вселенной. Но что он из себя представляет под капотом?

🔹Registry - это библиотека образов с блек джеком и прочими прелестями!

Если коротко, то Docker Registry - это специализированное веб-приложение (REST API), которое управляет хранением и распределением Docker-образов по определенному стандарту (OCI Distribution Spec). Это не просто файловое хранилище вроде S3 или FTP, а интеллектуальная система, которая понимает все нюансы Docker-образов.

🔹Архитектура: слоеный пирог

Фишка Registry в том, что образы хранятся не целиком, а слоями! Каждый слой - это дифф изменений файловой системы. Когда несколько образов используют одинаковую базу (например, Ubuntu), Registry умно дедуплицирует слои. Один слой - много ссылок. Экономия дискового пространства на лицо!

🔹Push/Pull

При пуше Docker разбивает образ на слои, хеширует их и отправляет только новые в виде tar.gz архива. При пулле скачиваются только недостающие слои в том же виде и собираются обратно в образ. Магия дедупликации работает и тут - если у тебя уже есть слой с nginx:alpine, он не будет скачиваться повторно для другого образа!

🔹Теги и версионирование

Система тегов - это не Git, это проще! Один и тот же по составу образ может иметь множество тегов, которые просто указывают на один манифест. Тег latest не последняя версия, а просто алиас, который может указывать на что угодно.

🔹Манифест:

Каждый образ содержит "инструкция по сборке" - манифест. Изнутри это JSON-файл, который содержит метаданные — список всех слоев, их хеши, размер, а также конфигурацию контейнера (например, переменные окружения, точку входа)

Когда ты делаешь docker pull, Docker сначала загружает манифест, а затем по списку в нем скачивает необходимые слои.

🔹Приватные vs публичные

Docker Hub удобен для открытых проектов, но для продакшена лучше приватный registry. Harbor, AWS ECR, Azure Container Registry - все они работают по одному API, но дают контроль над безопасностью и retention policies.


Понимание Registry - это понимание того, как живет весь Docker-экосистем!

Жми реакт, если Registry больше не кажется черной магией!

🥷 Docker Ninja 🥷
👍83
Ты создал контейнер с веб-приложением и хочешь скопировать лог-файл из контейнера на хост для анализа. Какая команда позволит это сделать?
Anonymous Quiz
31%
docker copy container_name:/app/logs/app.log ./app.log
3%
docker transfer container_name:/app/logs/app.log ./app.log
64%
docker cp container_name:/app/logs/app.log ./app.log
1%
docker move container_name:/app/logs/app.log ./app.log
👍5🔥3😱1
⏸️ Стоп слово - Fluggegecheimen ⏸️

Представь: у тебя крутится ресурсоемкая задача по обработке данных, а тут метрики хоста выдают алерт по CPU. Что же делать? Убить контейнер? Потеряешь прогресс. Проигнорировать? Ляжет весь хост...

Мда, ситуация на уровне "вилкой в глаз или...". На такие случаи важно знать стоп-слово.

Пожалуйста, docker pause - твое спасение на случай важных переговоров!

Как это работает:
# Замораживаем контейнер
docker pause my-container

# Размораживаем обратно
docker unpause my-container


В отличие от docker stop, который отправляет SIGTERM процессам, pause использует cgroups freezer — механизм ядра Linux. Все процессы контейнера буквально замораживаются на месте! Никаких сигналов, никакого graceful shutdown. Просто стоп-кадр всей жизнедеятельности.

Чем отличается от stop:
🔹 docker stop — завершает порождающий процесс контейнера
🔹 docker pause — ставит все процессы на паузу без предупреждения
🔹 Stop освобождает ресурсы, pause — оставляет все в памяти

Когда юзать?
🔹 Отладка: заморозил, подключился, изучил состояние
🔹 Экстренное освобождение CPU без потери данных
🔹 Миграция контейнеров между хостами
🔹 Создание снапшотов состояния для анализа

Важный нюанс: замороженный контейнер продолжает занимать память! Это не гибернация, а именно пауза. Сетевые соединения могут таймаутиться, пока контейнер спит.

Кстати, помнишь наш разговор про docker compose pause? Тот же принцип, только для одного контейнера!


Жми палец вверх, если пригодилось!


🥷 Docker Ninja 🥷
👍132😁2
🏃‍♂️ Утром бегит, пресс качац, анжуманя 🏃‍♂️

Коллега, все мы знаем, что с нашей сидячей работой очень важно следить за физической активностью. Иначе, есть перспектива навайбкодить себе мозоль не только на пузе, но и на вечно подгорающей точке притяжения приключений.🍑
Отсюда вывод, больше бегаешь = меньше весиш.

Кажется, такого девиза придерживаются и те, кто любит исчеркать Dockerfile бездумными вызовами RUN команд, а потом удивляются, почему их образ весит как слон после новогодних праздников!
Так что сегодня, давайте разберемся в сущности такой простой директивы как RUN в Dockerfile.

🔥 Что это вообще такое?
RUN выполняет команды во время сборки образа и создает новый слой с результатами. Каждый RUN = новый слой = +размер к образу.

Есть две формы записи:
# Shell форма (через /bin/sh -c)
RUN apt-get update && apt-get install -y nginx

# Exec форма (прямое выполнение)
RUN ["apt-get", "update"]



И как же это оптимизировать:
👉🏻Плохо (каждый RUN = отдельный слой):
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y vim
RUN rm -rf /var/lib/apt/lists/*

👉🏻Хорошо (один RUN = один слой):
RUN apt-get update && \
apt-get install -y curl vim && \
rm -rf /var/lib/apt/lists/*


Так и в чем же разница?
Для этого надо вспомнить про кэш сборки. Так вот, каждый RUN кэшируется отдельно.
💥 Значит каждый отдельный RUN оставляет следы в общем слоеном пироге нашего образа, не смотря на то, что в примере мы удаляем кэш пакетов.
💥 В общем RUN мы получаем один слой в котором уже есть установленные пакеты и отсуствует кэш этих пакетов.

Отсюда и экономия пространства.

Так что, используй RUN с умом и не забудь размяться после прочтения поста! 💪

🥷 Docker Ninja 🥷
1👍15🤮1
В CI/CD пайплайне нужно автоматически очищать старые образы после деплоя, чтобы не засорять диск агента. Какая команда удалит все неиспользуемые образы одной строкой?
Anonymous Quiz
48%
docker image rm $(docker images -q)
13%
docker rmi --force
25%
docker system prune -a —volumes
14%
docker volume prune
🔥3
🐧 Что дозволено пингвину, не дозволено киту 🐳

Помнишь, мы запускали контейнеры с флагом --memory? Как думаешь, Docker сам по себе следит за памятью? А вот и нет! Docker — это всего лишь красивая обертка над всемогущим Linux ядром.

Конкретно в данном случае работает механизм Control Groups или cgroups

Хочешь заглянуть под капот? Запусти контейнер:
docker run -d --name test-container --memory 512m nginx


А теперь подсмотри, что творится в недрах системы:
# Найдем ID контейнера 
docker inspect test-container | grep Id

# Заглянем в cgroups
ls /sys/fs/cgroup/memory/docker/

# Найдем выставленный нами лимит памяти
cat /sys/fs/cgroup/memory/docker/conatainer_id/memory.limit_in_bytes


Хоба, и там целая иерархия папок! Каждая — это отдельная cgroup для твоего контейнера. Docker автоматически создает группы:
- 🧠 Памяти (/sys/fs/cgroup/memory/docker/)
- ⚡️ CPU (/sys/fs/cgroup/cpu/docker/)
- 💾 Дискового I/O (/sys/fs/cgroup/blkio/docker/)

Зачем это знать?
Когда твой контейнер внезапно прибивается или мониторинг показывает странности с ресурсами, именно в эти файлы стоит заглянуть. Помнишь docker stats? Он как раз читает данные из cgroups! А если вдруг docker cli по какой-то причине недоступны, то раскуривать остается только файлы cgroups.

А еще это объясняет, почему контейнеры работают только на Linux — без cgroups и namespaces вся изоляция превращается в тыкву 🎃

Ставь 🔥, если хочешь узнать подробнее как, где и что копать в cgroups под Docker.

🥷 Docker Ninja 🥷
🔥26👍2🤯1
Какой сигнал Docker отправляет процессу в контейнере первым при выполнении команды docker stop?
Anonymous Quiz
40%
SIGTERM
36%
SIGSTOP
9%
SIGINT
14%
SIGKILL
😁3🤔1
🍻За связь без брака🍻

Как и обещал в прошлый понедельник, размещаю пост для любителей поковыряться в legacy.

До появления пользовательских сетей контейнеры жили в изоляции даже между собой. И тогда на арену вышел механизм links - примитивыный, но действенный способ познакомить контейнеры друг с другом!

Вот как выглядел этот винтаж:
version: '2'
services:
web:
image: nginx
links:
- db:database
- redis:cache

db:
image: postgres

redis:
image: redis


Что творилось под капотом:
🔗 Docker пробрасывал записи в /etc/hosts контейнера web:
172.17.0.2    db database
172.17.0.3 redis cache

🌍 Создавал переменные окружения типа DATABASE_PORT_5432_TCP_ADDR

А как же зависимости?
Главная проблема этой архаики в том, что работала она только в рамках одного хоста. Зато сетевая изоляция на уровне!
И, как вы видите, links - это не столько механизм порядка запуска, сколько сам механизм сети. И в данном случае, порядок запуска обеспечивался самым простым костылем - баш скриптом, который проверяет доступность сервиса по хостнейму, указанному в линке.
Например, вот так:
bash -c "while ! nc -z db 5432; do sleep 1; done && python app.py"


Так что, если увидишь данное чудо (в версиях компоуза до 2), не пугайся, смело переходи на более свежий компоуз и используй современные пользовательские сети + depends_on!

Жми 👍🏻, если рассказал своему деду про links, а он прослезился!

🥷 Docker Ninja 🥷
👍102
🧅 Сидит дед, в сто шуб одет 🧅

Мы уже не раз касались такой темы как Layered File System в Docker (6, 19, 41, 64). И уже хорошо знаем, что благодаря этому механизму обеспечивается приличное количество фич, упрощающих процесс разработки. Особенно в условиях новомодного микросервисного ада!🤯

Но как же это реализовано изнутри?? Давайте глянем.

Как мы уже говорили, есть image layer и writable layer. Если быть честным, то и того и другого слоев будет несколько. Просто то, что было сделано в базовом образе, называется image layer и по своей сути является неизменным (read-only). Writable layer же - это чистое поле для экспериментов и каждое изменение фиксируется в нем как отдельный слой со своим хэш-ом - названием (наподобие commit hash в git-е).

Как хранится?
Docker хранит эти слои как отдельные директории в /var/lib/docker/driver_name/
/var/lib/docker/overlay2/
├── abc123.../diff # Слой с изменениями
├── def456.../diff # Еще один слой
├── ......
└── merged/ # Итоговая FS


За всем этим колдунством стоит так называемый UnionFS. Storage driver-ы склеивают слои через механизм union mount. Верхние слои "перекрывают" нижние. Если файл меняется в нескольких слоях - побеждает верхний. Таким образом обеспечивается актуальность изменений.

CoW:
Операции I/O реализованны через стратегию Copy-on-Write
🔹Read: файл читается из read-only слоев
🔹Write: когда мы пытаемся изменить файл в базовом образе, он копируется в верхний writable слой, и изменяется именно копия исходного файла
🔹Delete: создается "whiteout" файл, скрывающий нижний слой


Хеширование и дедупликация:
Каждый слой идентифицируется SHA256 (об этом чутка упоминал выше). Одинаковые слои физически хранятся один раз, независимо от количества образов!

Зачем эта сложность?
🔹Пересобираются только измененные слои
🔹Скачиваются только новые слои
🔹Один слой на много образов = оптимизация хранения


Теперь ты знаешь, почему docker pull иногда показывает "Already exists" - Docker просто переиспользует существующие слои!

Ставь 🤯, если ничего не понятно, но очень интересно и ты просто требуешь пояснительной бригады в виде длино-поста с красивыми картинками!🤓


🥷 Docker Ninja 🥷
🤯15🔥1
Ты разворачиваешь веб-приложение в контейнере и хочешь убедиться, что оно корректно запускается и отвечает на запросы. Какая директива Dockerfile поможет Docker автоматически проверять состояние приложения?
Anonymous Quiz
8%
CMD curl -f http://localhost:8080/health || exit 1
12%
RUN curl -f http://localhost:8080/health || exit 1
71%
HEALTHCHECK --interval=30s CMD curl -f http://localhost:8080/health || exit 1
9%
EXPOSE 8080 && curl -f http://localhost:8080/health
🕳 Если долго смотреть в cgroup, cgroup начинает смотреть в тебя 🕳

По вашим заявкам в посте про cgroups продолжаем углубляться в кроличью нору дальше. Что ж, мои дорогие любители покопаться в кишочках, давайте приступим. 🙏🏻

🔍 Находим нужную cgroup
Ищем ID контейнера, чтобы знать в какую папку стучать
ddocker inspect test-container | grep Id


🤿 Теперь ныряем в его метрики:
💾 Метрики памяти
# Текущее использование памяти
cat /sys/fs/cgroup/memory/docker/CONTAINER_ID/memory.usage_in_bytes

# Лимит памяти контейнера
cat /sys/fs/cgroup/memory/docker/CONTAINER_ID/memory.limit_in_bytes

# Детальная статистика памяти
cat /sys/fs/cgroup/memory/docker/CONTAINER_ID/memory.stat

# Пиковое потребление памяти
cat /sys/fs/cgroup/memory/docker/CONTAINER_ID/memory.max_usage_in_bytes

# Swap использование
cat /sys/fs/cgroup/memory/docker/CONTAINER_ID/memory.memsw.usage_in_bytes


🖥 CPU метрики
# Общее время CPU в наносекундах
cat /sys/fs/cgroup/cpuacct/docker/CONTAINER_ID/cpuacct.usage

# CPU usage по ядрам
cat /sys/fs/cgroup/cpuacct/docker/CONTAINER_ID/cpuacct.usage_percpu

# Детальная статистика CPU
cat /sys/fs/cgroup/cpu/docker/CONTAINER_ID/cpu.stat

# Время в user/system mode
cat /sys/fs/cgroup/cpuacct/docker/CONTAINER_ID/cpuacct.stat

# CPU throttling статистика
cat /sys/fs/cgroup/cpu/docker/CONTAINER_ID/cpu.throttling_data


💿 Block I/O метрики
# Статистика по чтению/записи
cat /sys/fs/cgroup/blkio/docker/CONTAINER_ID/blkio.throttle.io_service_bytes

# IOPS счетчики
cat /sys/fs/cgroup/blkio/docker/CONTAINER_ID/blkio.throttle.io_serviced

# Время обслуживания I/O
cat /sys/fs/cgroup/blkio/docker/CONTAINER_ID/blkio.time


🥶Наш любимый freezer
# Текущее состояние контейнера
cat /sys/fs/cgroup/freezer/docker/CONTAINER_ID/freezer.state

# PID родительского процесса контейнера
cat /sys/fs/cgroup/freezer/docker/CONTAINER_ID/cgroup.procs

# Список всех потоков (threads), принадлежащих контейнеру (в старых версиях ядра).
cat /sys/fs/cgroup/freezer/docker/CONTAINER_ID/tasks


Как мы уже разобрали в первом посте про cgroups, docker stats и флаг --memory работают именно с этими файлами.
Но, линукс не линукс, если бы все было так просто... Данная файловая структура актуальна для cgroups v1. Поэтому, ставь 🔥 если хочешь узнать про то, как работать с файлами cgroups v2.


🥷 Docker Ninja 🥷
🔥20😁4🤣1🙈1
🧼 Моя оборона! 🧼

Я где-то слышал, что практически каждый второй Docker-образ, будь то Docker Hub или же приватные registry содержит критические уязвимости, но мы же продолжаем пулить их как ни в чем не бывало!

Проверять это утверждение я конечно же не буду, но не удивлюсь, если это окажется правдой... Да и как предлог заколлабиться с безопасниками и реализовать что-то новенькое для своего портфолио хороший!😏
Так шо сегодня разберем с вами Docker Scout - встроенный сканер безопасности докер образов aka "нет пробития"! Ага, прикиньте, есть такой. Я сам однажды офигел!!!

🔐 Запускаем сканирование
# Сканируем локальный образ
docker scout cves nginx:latest

# Получим что-то типа такого
✔️ Image stored for indexing
┌───────────────┬────────┬──────────┬───────────────┐
│ CVE │ Score │ Severity │ Package │
├───────────────┼────────┼──────────┼───────────────┤
│ CVE-2023-1234 │ 8.2 │ HIGH │ libc6 │
│ CVE-2023-5678 │ 6.5 │ MEDIUM │ openssl │
│ CVE-2023-9012 │ 4.3 │ LOW │ zlib │
└───────────────┴────────┴──────────┴───────────────┘
Summary: 15 vulnerabilities found (3 critical, 5 high, 4 medium, 3 low)

# Или прямо при сборке
docker scout cves local://my-app:v1.0


После docker login можем сканировать приватные образы:
docker scout cves registry.company.com/my-private-app:latest


📊 Детальный анализ
# Сканирование с рекомендациями по исправлению
docker scout recommendations nginx:latest

# Анализ по критичности (только HIGH и CRITICAL)
docker scout cves --severity high,critical node:18-alpine

# Сравнение двух версий образа
docker scout compare nginx:1.20 --to nginx:1.21

# Анализ конкретного слоя
docker scout cves --layer-details postgres:15

## Вывод довольно читабельный
Layer 1: base image (debian:bullseye)
├── CVE-2023-1234 (HIGH) in libc6
└── CVE-2023-5678 (MEDIUM) in openssl

Layer 3: application dependencies
├── CVE-2023-9012 (CRITICAL) in python3.9
└── CVE-2023-3456 (HIGH) in postgresql-15


💡Что еще умеет?
🔹 Scout анализирует не только OS-пакеты, но и зависимости языков (Node.js, Python, Java, а это уже вполне себе такой Software Composition Analisys)
Кстати, тул умеет выгружать эту аналитику в sbom файл, который потом можно грузануть в какую-нибудь систему аналитики уязвимостей (типа Dependency Track или DefectDojo)
🔹 Интегрируется с Docker Desktop для GUI-анализа
🔹 Поддерживает webhook-и для автоматических уведомлений


Теперь об обороне стало думать легче, тылы прикрыты, так что можно спокойно ронять мыло в общественных местах💪🏻


Ставь 😎 если уже представляешь, как твой security-отдел будет тебя благодарить!


🥷 Docker Ninja 🥷
😁7😎4👍2🤣1
Твое приложение в контейнере потребляет слишком много памяти и часто падает. Ты хочешь ограничить использование RAM до 2024 МБ. Какой флаг использовать при запуске?
Anonymous Quiz
26%
docker run --memory 2024m my-app
33%
docker run --mem-limit 2024m my-app
6%
docker run --ram 2024m my-app
34%
docker run --max-memory 2024m my-app
😁4🙈3🌚1🗿1
🛁 Keep calm and chill like it's the last time 🛁

Коллеги, думаю многие из вас пережили на этой неделе рабочую 6-дневку. Я, как и вы, не исключение. Поэтому, предлагаю хорошенько почилить и порасслабонить в доставшиеся нам за такие муки, 3 выходных дня!!! А в среду снова начнем бой во славу кровавого энтерпрайза!🤼‍♂️

С праздником всех причастных! 🎉

А не причастным "Счастливого хеллоуина" и побольше сладостей!🎃
Please open Telegram to view this post
VIEW IN TELEGRAM
3🍾2👍1
🐧Некоторым птицам не место в контейнере. У них слишком яркие перья🐧

Ну и заключительный пост про файлы cgroups (первый, второй).

Начиная с версии ядра Linux 4.5 мы взаимодействуем с cgroups v2, который стал более структурированный, чем первая версия.

Выглядит это дело так:
🎯Определяем директорию нашего контейнера:
# Запускаем контейнер
docker run -d --name test-app nginx

# Путь к cgroup контейнера
CGROUP_PATH="/sys/fs/cgroup/system.slice/docker-$(docker inspect -f '{{.Id}}' test-app).scope"


🧠Memory
# Текущее потребление памяти
cat $CGROUP_PATH/memory.current
# 52428800 (50MB в байтах)

# Максимальное потребление с момента старта
cat $CGROUP_PATH/memory.max
# max (без лимитов)

# Детальная статистика памяти
cat $CGROUP_PATH/memory.stat
# anon 12582912
# file 8388608
# kernel_stack 32768


⚡️CPU
# Статистика использования CPU
cat $CGROUP_PATH/cpu.stat
# usage_usec 1542340
# user_usec 890123
# system_usec 652217

# Помечен ли процесс контейнера как "с минимальным приоритетом"
cat $CGROUP_PATH/cpu.idle

# Текущий вес процесса
cat $CGROUP_PATH/cpu.weight
# 100


💾I/O
# Статистика ввода-вывода
cat $CGROUP_PATH/io.stat
# 8:0 rbytes=1048576 wbytes=4096 rios=64 wios=8

# Текущий I/O pressure
cat $CGROUP_PATH/io.pressure
# some avg10=0.00 avg60=0.00 avg300=0.00 total=0


🧊Freezer
# Проверяем текущее состояние
cat $CGROUP_PATH/cgroup.freeze
# 0 (разморожен)

# Замораживаем контейнер без docker cli
echo 1 > $CGROUP_PATH/cgroup.freeze
# После выполнения попробуй зайти в терминал контейнера

# Проверяем состояние
cat $CGROUP_PATH/cgroup.freeze
# 1 (заморожен)

# Размораживаем обратно
echo 0 > $CGROUP_PATH/cgroup.freeze


🚨Контроль процессов

# Список PID-ов в контейнере  
cat $CGROUP_PATH/cgroup.procs
# 1234
# 1235

# События cgroup (убийства OOM, миграции и проч.)
cat $CGROUP_PATH/cgroup.events
# populated 1
# frozen 0


В большинстве случаев, вы столкнетесь именно с cgroups v2. Поэтому полезно углубиться именно в этот вариант каталогов.

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

Но, если есть желание закопаться еще глубже, то ставьте ваши 👍🏻 на пост. 25+ 👍🏻 станут для меня знаком, что стоит копнуть еще и в линукс.

🥷 Docker Ninja 🥷
👍213😁2👎1
Твоя команда разрабатывает микросервис и хочет минимизировать размер итогового образа. У вас есть этап компиляции Go-приложения и этап создания runtime-образа. Какой подход поможет создать максимально облегчит итоговый образ?
Anonymous Quiz
7%
Использовать один большой Dockerfile с установкой всех зависимостей
20%
Добавить .dockerignore для исключения ненужных файлов
3%
Использовать базовый образ ubuntu:latest вместо alpine
70%
Применить multi-stage builds для разделения сборки и runtime