Docker Ninja – Telegram
Docker Ninja
1.05K subscribers
30 photos
91 links
По всем вопросам обращаться к @nesudimov_eu
Download Telegram
📚 Все дороги ведут в 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
🧙🏾‍♂️Раньше был я Гендальф Серый. А теперь я Саша Белый 🧙‍♂️

Пятница. 18:00. Ты уже одной ногой в уличном ботинке. Но тут в телегу предательски прилетает алерт - одному из сервисов в контейнере не хватает памяти...

Заходишь на хост. Видишь, что свободной памяти еще выше крыши. Но метрики показывают другое.

Смотришь в inspect контейнера и видишь, что при запуске дали ограничение в половину всей памяти хоста. Ребутать(пык, мык) или стопать контейнер не вариант - инстанс сервиса только один, так что прод сразу встанет, а ты ляжешь под обильными плевками коллег, решивших расслабиться в вечер пятницы.

Что же делать? Как расширить память запущенного контейнера?

Встречай, единственная и не повторимая команда docker update! Она позволяет менять ресурсы работающих контейнеров без их остановки.

🎯 Базовое использование:
Ограничиваем прожорливый контейнер:
# Урезаем память до 512MB
docker update --memory=512m my-app


Можно обновлять сразу несколько контейнеров:
# Апдейтим все контейнеры с префиксом web
docker update --memory=256m web-app-1 web-app-2 web-app-3


Зачем это нужно?
Как ты уже понял, команда идеальна для тушения пожаров на проде, когда нужно быстро отреагировать на нагрузку. Видишь, что контейнер начал тормозить — добавляешь ресурсы. Заметил утечку памяти — урезаешь лимиты до фикса. Все без простоев!

Помнишь лимиты памяти и политики рестарта? Их, к слову, тоже можно менять налету с помощью данной команды!

Как обычно, ставь свои реакты. Так я буду знать, что пост зашел, а мне стоит продолжать делиться знаниями в подобном формате!

🥷 Docker Ninja 🥷
🔥33👍72😁1
🙈If i ignore it, it will go away🙈

Бывает, собираешь образ, а Docker берет и тащит в контейнер все что видит в рамках контекста. Node_modules на 300 МБ, .git со всей историей коммитов, IDE конфиги, логи разработки, личную коллекцию мемов из папки dicks_pics/🍌...

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

Конечно, для кого-то это может быть преимуществом, но мы то с вами ответственные работники, правда ведь?!😏

И тут самое время заюзать, возможно знакомый вам из git-а, формат ignore файлов. В нашем случае .dockerignore.

Этот файл работает по тому же принципу, что и .gitignore, только вместо исключения файлов из репозитория, он исключает их из контекста сборки Docker. Создаешь файл .dockerignore в корне проекта рядом с Dockerfile (руками или через init) и прописываешь паттерны того, что Docker должен проигнорировать.

Например он может выглядеть вот так:
node_modules/
*.log
.git
.env


Паттерны:
Можно юзать wildcard или более сложные паттерны
# Исключить все .md файлы, кроме README.md
*.md
!README.md

# Исключить все временные файлы
**/temp/
**/*.tmp

Зачем это нужно? 🤔
🔹Во-первых, размер! Build Context — это все, что Docker отправляет демону для сборки. Чем меньше мусора, тем быстрее передача и меньше итоговый образ.
🔹Во-вторых, безопасность. Никому не нужны секреты, приватные ключи или конфиги в production образе.
🔹В-третьих, кэширование слоев работает эффективнее без постоянно меняющихся логов и временных файлов.

Фиксируем,.dockerignore проверяется относительно Build Context, который вы указываете в docker build!

А на сегодня у нас все и помните: игнорировать можно все что угодно, кроме отсуствия реактов на постах от любимых подписчиков!😔
Так что, обязательно ставьте!😏

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥3👏2🤯1
Ты работаешь с микросервисной архитектурой и хочешь мониторить потребление ресурсов всех запущенных контейнеров в реальном времени. Какая команда покажет CPU, память и сетевую активность?
Anonymous Quiz
12%
docker ps --format table
47%
docker stats
35%
docker top --all
6%
docker system df
©️Хорошие копируют, великие воруют🦝

Мы с вами уже довольно хорошо погрузились в различные аспекты написания Dockerfile. Все может казаться просто и лаконично: захотел закинуть сорсы в контейнер - используй COPY; надо закинуть что-то из архива - втыкай ADD; слишком тяжелая сборка - пробуй multistage build.

Но порою, меняешь одну строчку в коде, а сборка после этого идет 15 минут. Как будто Docker внезапно забыл про все свои слои и решил: "А давайте-ка пересоберем все с нуля!"

А ведь проблема часто кроется в бездумных COPY в твоем Dockerfile.

Так шо сегодня рассмотрим best practices для COPY, которые превратят твою сборку в пушку ракету!🚀

Правило №1: Зависимости копируем отдельно
Частный случай для следующего правила, но стоит рассмотреть его отдельно
#  Плохо - весь контекст копируется сразу  
COPY . /app
RUN npm install


Делаем так:
#  Хорошо - сначала только package.json
COPY package*.json /app/
RUN npm install
COPY . /app/


Правило №2: От редко изменяемых к часто изменяемым
Docker кэширует слои сверху вниз. Как только один слой меняется, все нижние пересобираются
COPY requirements.txt /app/    # Меняется редко
RUN pip install -r requirements.txt
COPY some_noscript.sh /noscripts/ # Меняется средне
COPY src/ /app/src/ # Меняется средне
COPY main.py /app/ # Меняется часто


Правило №3: Дружи с .dockerignore
Смотрим пост про .dockerignore и проникаемся
#  Опасно - копируем весь мусор, а в довесок и секреты 
COPY . /app

# Безопасно - фильтруем через .dockerignore
## Создай .dockerignore рядом с Dockerfile:
node_modules
.git
*.log
.env
.idea
.vscode
dist
Dockerfile
.dockerignore


Правило №4: Multi-stage для чистых артефактов
Собираем в одном образе, забираем результат в другом
FROM golang:1.23 AS sdk
...
RUN go build -o /bin/hello ./main.go

FROM scratch
COPY /app/some_file.txt /app/file.txt
COPY --from=sdk /bin/hello /bin/hello
CMD ["/bin/hello"]


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

Представь: у тебя Node.js приложение, ты фиксишь баг в main.js. При правильном COPY пересоберется только один последний слой. При неправильном - весь npm install заново, а это могут быть гигабайты зависимостей!

В реальности это означает разницу между сборкой за 10 секунд и за 10 минут. Особенно критично для CI/CD пайплайнов, где каждая секунда на счету. Да и в момент разработки дико бесит, что нужно долго ждать пересборку...

Так что, воруйте все что здесь написано и ставьте ваши реакции!!!

🥷 Docker Ninja 🥷
2👍13🔥52😁2
Твое приложение собирается через multi-stage build. На финальной стадии нужно скопировать только скомпилированные бинарные файлы из промежуточной стадии. Какая директива Dockerfile правильно выполнит эту задачу?
Anonymous Quiz
7%
ADD --from=builder /app/bin /usr/local/bin
10%
RUN cp --from=builder /app/bin /usr/local/bin
9%
WORKDIR --from=builder /app/bin
74%
COPY --from=builder /app/bin /usr/local/bin
👍42🆒2