Твое приложение в контейнере потребляет слишком много памяти и часто падает. Ты хочешь ограничить использование 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
Коллеги, думаю многие из вас пережили на этой неделе рабочую 6-дневку. Я, как и вы, не исключение. Поэтому, предлагаю хорошенько почилить и порасслабонить в доставшиеся нам за такие муки, 3 выходных дня!!! А в среду снова начнем бой во славу кровавого энтерпрайза!🤼♂️
С праздником всех причастных!
А не причастным "Счастливого хеллоуина" и побольше сладостей!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🍾2👍1
🐧Некоторым птицам не место в контейнере. У них слишком яркие перья🐧
Ну и заключительный пост про файлы cgroups (первый, второй).
Начиная с версии ядра Linux 4.5 мы взаимодействуем с cgroups v2, который стал более структурированный, чем первая версия.
Выглядит это дело так:
🎯Определяем директорию нашего контейнера:
🧠Memory
⚡️CPU
💾I/O
🧊Freezer
🚨Контроль процессов
В большинстве случаев, вы столкнетесь именно с
Как видим, изменения почти не коснулись метрик памяти. Но вот по остальным есть довольно много нюансов. И если копать в эту сторону еще глубже, то мы, в любом случае, выйдем на линукс. А это уже выходит за рамки тематики данного канала. Да и сам линукс - это уж очень глубокая штука, которую надо разбирать в отдельном канале.
Но, если есть желание закопаться еще глубже, то ставьте ваши 👍🏻 на пост. 25+ 👍🏻 станут для меня знаком, что стоит копнуть еще и в линукс.
🥷 Docker Ninja 🥷
Ну и заключительный пост про файлы 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 🥷
👍21❤3😁2👎1
Твоя команда разрабатывает микросервис и хочет минимизировать размер итогового образа. У вас есть этап компиляции Go-приложения и этап создания runtime-образа. Какой подход поможет создать максимально облегчит итоговый образ?
Anonymous Quiz
7%
Использовать один большой Dockerfile с установкой всех зависимостей
20%
Добавить .dockerignore для исключения ненужных файлов
3%
Использовать базовый образ ubuntu:latest вместо alpine
70%
Применить multi-stage builds для разделения сборки и runtime
🧙🏾♂️Раньше был я Гендальф Серый. А теперь я Саша Белый 🧙♂️
Встречай, единственная и не повторимая команда
🎯 Базовое использование:
Ограничиваем прожорливый контейнер:
Можно обновлять сразу несколько контейнеров:
Зачем это нужно?
Как ты уже понял, команда идеальна для тушения пожаров на проде, когда нужно быстро отреагировать на нагрузку. Видишь, что контейнер начал тормозить — добавляешь ресурсы. Заметил утечку памяти — урезаешь лимиты до фикса. Все без простоев!
Помнишь лимиты памяти и политики рестарта? Их, к слову, тоже можно менять налету с помощью данной команды!
Как обычно, ставь свои реакты. Так я буду знать, что пост зашел, а мне стоит продолжать делиться знаниями в подобном формате!
🥷 Docker Ninja 🥷
Пятница. 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👍7❤2😁1
🙈If i ignore it, it will go away🙈
И тут самое время заюзать, возможно знакомый вам из git-а, формат ignore файлов. В нашем случае
Этот файл работает по тому же принципу, что и
Например он может выглядеть вот так:
Паттерны:
Можно юзать wildcard или более сложные паттерны
Зачем это нужно? 🤔
🔹Во-первых, размер! Build Context — это все, что Docker отправляет демону для сборки. Чем меньше мусора, тем быстрее передача и меньше итоговый образ.
🔹Во-вторых, безопасность. Никому не нужны секреты, приватные ключи или конфиги в production образе.
🔹В-третьих, кэширование слоев работает эффективнее без постоянно меняющихся логов и временных файлов.
Фиксируем,
А на сегодня у нас все и помните: игнорировать можно все что угодно, кроме отсуствия реактов на постах от любимых подписчиков!😔
Так что, обязательно ставьте!😏
🥷 Docker Ninja 🥷
Бывает, собираешь образ, а 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
©️Хорошие копируют, великие воруют🦝
пушку ракету!🚀
Правило №1: Зависимости копируем отдельно
Частный случай для следующего правила, но стоит рассмотреть его отдельно
Делаем так:
Правило №2: От редко изменяемых к часто изменяемым
Docker кэширует слои сверху вниз. Как только один слой меняется, все нижние пересобираются
Правило №3: Дружи с .dockerignore
Смотрим пост про .dockerignore и проникаемся
Правило №4: Multi-stage для чистых артефактов
Собираем в одном образе, забираем результат в другом
Зачем это нужно?
Представь: у тебя Node.js приложение, ты фиксишь баг в main.js. При правильном COPY пересоберется только один последний слой. При неправильном - весь
В реальности это означает разницу между сборкой за 10 секунд и за 10 минут. Особенно критично для CI/CD пайплайнов, где каждая секунда на счету. Да и в момент разработки дико бесит, что нужно долго ждать пересборку...
Так что, воруйте все что здесь написано и ставьте ваши реакции!!!
🥷 Docker Ninja 🥷
Мы с вами уже довольно хорошо погрузились в различные аспекты написания Dockerfile. Все может казаться просто и лаконично: захотел закинуть сорсы в контейнер - используй COPY; надо закинуть что-то из архива - втыкай ADD; слишком тяжелая сборка - пробуй multistage build.Так шо сегодня рассмотрим best practices для COPY, которые превратят твою сборку в
Но порою, меняешь одну строчку в коде, а сборка после этого идет 15 минут. Как будто Docker внезапно забыл про все свои слои и решил: "А давайте-ка пересоберем все с нуля!"
А ведь проблема часто кроется в бездумных COPY в твоем Dockerfile.
Правило №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🔥5❤2😁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
👍4❤2🆒2
😱 Игра началась 😱
Помнится, в самом начале моего девопсерского пути меня долго мучал вопрос, нафига нужен
Но как и в случае с "необязательным EXPOSE-ом", тут оказалось не так все просто...
Так что сегодня мы с вами слепим грузина с чемоданом и раз и навсегда разберемся в том, зачем нам
Exec vs Shell форма
Как и с нашим старым знакомцем CMD, у ENTRYPOINT есть две формы записи:
Комбинирование с CMD
А вот тут и начинается вся свистопляска...
Зачем это нужно?
ENTRYPOINT директива далеко не обязательная, но очень полезная. Из самых базовых кейсов можно привести следующие:
1️⃣ Нужно сделать из контейнера самостоятельную софтину.
2️⃣ Когда нужно гарантированно выполнить какой-либо скрипт.
3️⃣ Для правильной обработки сигналов ОС.
Как обычно, ставьте ваши реакты, если хочется побольше таких постов! Всем peace✌🏻 и хороших выходных.
🥷 Docker Ninja 🥷
Помнится, в самом начале моего девопсерского пути меня долго мучал вопрос, нафига нужен
ENTRYPOINT если уже есть CMD? Преимущества второго ведь на лицо - его можно изменить при запуске контейнера.Но как и в случае с "необязательным EXPOSE-ом", тут оказалось не так все просто...
Так что сегодня мы с вами слепим грузина с чемоданом и раз и навсегда разберемся в том, зачем нам
ENTRYPOINT. Но для начала мини обзорчик как это дело функционирует.Exec vs Shell форма
Как и с нашим старым знакомцем CMD, у ENTRYPOINT есть две формы записи:
# Exec форма (рекомендуемая)
ENTRYPOINT ["nginx", "-g", "daemon off;"]
# Shell форма
ENTRYPOINT nginx -g "daemon off;"
# Exec форма работает напрямую с ядром, без лишних оберток — быстрее и надежнее!
Комбинирование с CMD
А вот тут и начинается вся свистопляска...
ENTRYPOINT ["python", "app.py"]
CMD ["--help"]
# docker run myapp → выполнит python app.py --help
# docker run myapp --version → выполнит python app.py --version
# docker run myapp --config prod.conf → выполнит python app.py --config prod.conf
# ENTRYPOINT остается неизменным, а `CMD` становится аргументами по умолчанию!
Зачем это нужно?
ENTRYPOINT директива далеко не обязательная, но очень полезная. Из самых базовых кейсов можно привести следующие:
1️⃣ Нужно сделать из контейнера самостоятельную софтину.
docker run уже запускает нужный нам бинарник, а мы лишь назначаем аргументы в cmd (смотри пример выше)
2️⃣ Когда нужно гарантированно выполнить какой-либо скрипт.
Например делаем контейнер для запуска ансибла (такое практикуют если рабочи комп на винде). В `ENTRYPOINT` ставим скрипт, который грузит зависимые ansible модули из requirements, а в CMD указываем команды ансибла
3️⃣ Для правильной обработки сигналов ОС.
Для этого ставим в `ENTRYPOINT` то что мы собираемся запускать в контейнере (nginx, python, node). В `CMD` ставим его аргументы (my_app.py, server.js). В таком случае, если мы прервем работу контейнера штатными средствами (pause, stop), то сигнал получит не shell, а непосредственно то, что мы указали в `ENTRYPOINT`. А значит, мы получаем более корректное завершение работы нашего приложения.
Как обычно, ставьте ваши реакты, если хочется побольше таких постов! Всем peace✌🏻 и хороших выходных.
🥷 Docker Ninja 🥷
4🔥15👍8❤2
В пятницу вечером один из подписчиков задал вопрос к последнему посту: работает ли shell и exec формы в Distroless и From Scratch образах?
Вопрос хороший и очень интересный для разбора! Тем более, что, скорее всего, многие не знают что такое Distroless и From Scratch.
Давайте разберем этот момент в трех постах:
1️⃣ Что такое Distroless образы?
2️⃣ Что такое from scratch образы?
3️⃣ Как в данных образах запускается что либо, если они совсем пустые?
Please open Telegram to view this post
VIEW IN TELEGRAM
💊ДетралексDistroless: понедельники без тяжести💊
Distroless - это образы без дистрибутива. Звучит как сапожник без сапог, но тем не менее. Внутри только runtime-зависимости и все. Никаких shell-ов(да мы с вами об этом уже говорили - тык, брык), package manager-ов, лишних библиотек. Только то, что нужно твоему приложению для работы.
Сравни сам через docker images:
Результат: образ сжался с 72MB до 2MB! 🎯
Зачем юзать:
💊 Меньше уязвимостей - меньше головной боли с security
💊 Микроскопический размер - быстрее пуллится и стартует
💊 Невозможно зайти в контейнер через shell - дополнительная защита
💊 Отлично сочетается с multi-stage builds
Google предоставляет варианты на любой вкус:
🔹
🔹
🔹
🔹
Подобрать вариант под себя можно вот тут.
Минус только один: дебажить сложнее, так что обрадуйте своих любителей дебажить на проде - лафа закончилась😏
Попробовал Distroless? Ставь 🔥!
Этот пост лишь маленькая часть серии из 3-х постов про distroless и scratch образы. Ссылки на все части ты можешь найти в этом посте .
🥷 Docker Ninja 🥷
Сидишь ты значит, деплоишь в продакшен очередной микросервис, потирая красные от недосыпа глаза, как вдруг, ИБ-ешник присылает отчет Docker Scout с полным набором критических уязвимостей. Половина из них - в пакетах Ubuntu, которые твое приложение вообще никогда не юзает! Curl, wget, package manager - зачем это все в контейнере, если твой бинарник статически слинкован?
Первое что приходит на ум это аппнуть базовый образ - авось все уязвимые пакеты там пропатчены.
Но что, если образ уже последней версии? Будешь создавать свой образ Ubuntu в котором вырежешь все дырявые пакеты? Ну да, вариант, но до очередной уязвимости. А как будешь следить за патчами пакетов и самой ОС?
Как ты понимаешь, проблем тут возникает вагон и маленькая тележка. Но и на такой случай придумали решение
Distroless - это образы без дистрибутива. Звучит как сапожник без сапог, но тем не менее. Внутри только runtime-зависимости и все. Никаких shell-ов(да мы с вами об этом уже говорили - тык, брык), package manager-ов, лишних библиотек. Только то, что нужно твоему приложению для работы.
Сравни сам через docker images:
docker pull ubuntu:20.04
docker pull gcr.io/distroless/static-debian11
docker images
# Было (Ubuntu base)
ubuntu 20.04 b7bab04fd9aa 7 months ago 72.8MB
# Стало (Distroless)
gcr.io/distroless/static-debian12 latest e021002e4213 N/A 2.08MB
Результат: образ сжался с 72MB до 2MB! 🎯
Зачем юзать:
💊 Меньше уязвимостей - меньше головной боли с security
💊 Микроскопический размер - быстрее пуллится и стартует
💊 Невозможно зайти в контейнер через shell - дополнительная защита
💊 Отлично сочетается с multi-stage builds
Google предоставляет варианты на любой вкус:
🔹
/static (без какого-либо рантайма, хорошо подходит для go) 🔹
/java, 🔹
/python, 🔹
/nodejsПодобрать вариант под себя можно вот тут.
Минус только один: дебажить сложнее, так что обрадуйте своих любителей дебажить на проде - лафа закончилась😏
Попробовал Distroless? Ставь 🔥!
🥷 Docker Ninja 🥷
2👍10🔥6🆒3
Какой механизм Linux использует Docker для ограничения ресурсов контейнеров?
Anonymous Quiz
29%
Linux Namespaces
9%
AppArmor
53%
Linux cgroups
9%
chroot
Помните мы с вами однажды рассматривали флаг --validate? Я тут полистал свои старые посты и подумал, не порядок - как конфиг валидировать знаем, а что настроить в этом самом конфиге вообще не в курсе.По дефолту Docker работает с базовыми настройками, а файл daemon.json мы создаем сами, когда нужно что-то подкрутить в Docker Engine под свои нужды.
Таки пришло время разобрать этот момент. Слишком глубоко копать не будем, чтобы не перегреть наши светлые головки в самой середине недели!
Где искать этого неуловимого зверя?
Linux: /etc/docker/daemon.json
Windows: C:\ProgramData\docker\config\daemon.json
macOS: ~/.docker/daemon.json
Если Магомет не идет к горе, то гора не придет и подавно
Но это совсем не про нашу ситуацию, ведь мы с вами проактивные девопсеры!
Как уже говорили выше, если файла нет, смело создаем его сами:
sudo mkdir -p /etc/docker
sudo touch /etc/docker/daemon.json
Что можно настроить?
Простейший пример:
{
"storage-driver": "overlay2",
"log-driver": "json-file"
}После правок обязательно рестартуем демон:
sudo systemctl restart docker
Не забываем провалидировать конфиг - сэкономим нервы!
Зачем это надо?
В продакшене дефолтные настройки часто не катят. Нужно настроить логирование, сменить storage driver под конкретную файловую систему, добавить корпоративные registry. Без daemon.json придется делать это через флаги командной строки и после нескольких раз ты будешь молить бога релизов, чтобы он сжалился над тобой и дал умереть без мучений.
Так что обязательно юзайте и помните, что демонов боятся только те, кто не умеет ими управлять! Ставьте ваши реакты, если понравился пост! А на этом у меня все, хорошего рабочего дня!👌🏻
🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍8🔥7❤2
При работе с Docker Registry ты хочешь загрузить образ ubuntu:20.04 на локальную машину для последующего использования. Какая команда выполнит эту задачу?
Anonymous Quiz
8%
docker download ubuntu:20.04
74%
docker pull ubuntu:20.04
5%
docker fetch ubuntu:20.04
13%
docker get ubuntu:20.04
🛸Ограничиваем мыслительные ресурсы🛸
Как это работает?
В отличие от --cpu-shares (который работал по принципу "кто первый встал, того и тапки"), --cpus дает жесткий лимит в количестве ядер:
Под капотом это всеми любимые Linux cgroups крутят ручки CFS (Completely Fair Scheduler). Контейнер получает определенный time slice и не может его превысить, даже если остальные ядра простаивают!
Кейсы:
• Мультитенантность: изолируем нагрузку между клиентами
• CI/CD: ограничиваем тесты, чтобы не убить билд-агенты
• Микросервисы: гарантируем, что один сервис не захватит все ресурсы
• Debugging: воспроизводим условия слабых серверов локально
А теперь, тряхнем стариной. Если нужно изменить лимит на лету - есть docker update:
А в связке с ограничением памяти получается идеальная изоляция ресурсов!
ПыСы: используй дробные значения осознанно. CPU 0.1 - это реально мало, подходит только для совсем легких задач типа health-check-ов.
Теперь, когда ты умеешь ограничивать мыслительные ресурсы своих подопечных, задача трех тел для тебя станет нипочем, если ты понимаешь о чем я!👽
Как обычно ставь свои пальчики, сердешки и огонечки, чтобы твой покорный слуга все выходные ждал понедельника, дабы написать свой новый пост.🙇
🥷 Docker Ninja 🥷
Представь, заапускаешь ты такой на проде "безобидный" контейнер с ML-моделью, чтобы она отвечала коллегам на сообщения "Сломалось - почини", а он сжирает все 16 ядер и превращает остальные сервисы в овощи?🍆 Или когда один разработчик запустил криптомайнер... тьфу, тесты CPU-интенсивного алгоритма, и вся команда сидит без CI перед важным релизом.
И тут ты потихоньку начинаешь чувствовать мягкий металлический привкус медного тазика, которым накрывается твой пятничный трип по барам на Рубинштейна.🍺
Отставить панику! На помощь приходит флаг --cpus - надежный помощник страждущего под конец недели девопса! 💪
Как это работает?
В отличие от --cpu-shares (который работал по принципу "кто первый встал, того и тапки"), --cpus дает жесткий лимит в количестве ядер:
# Ограничиваем контейнер половиной CPU
docker run --cpus="0.5" nginx
# Даем полтора ядра для тяжелых вычислений
docker run --cpus="1.5" my-ml-model
# Четверть ядра для легких задач
docker run --cpus="0.25" redis
Под капотом это всеми любимые Linux cgroups крутят ручки CFS (Completely Fair Scheduler). Контейнер получает определенный time slice и не может его превысить, даже если остальные ядра простаивают!
Кейсы:
• Мультитенантность: изолируем нагрузку между клиентами
• CI/CD: ограничиваем тесты, чтобы не убить билд-агенты
• Микросервисы: гарантируем, что один сервис не захватит все ресурсы
• Debugging: воспроизводим условия слабых серверов локально
А теперь, тряхнем стариной. Если нужно изменить лимит на лету - есть docker update:
docker update --cpus="2.0" my_container
А в связке с ограничением памяти получается идеальная изоляция ресурсов!
ПыСы: используй дробные значения осознанно. CPU 0.1 - это реально мало, подходит только для совсем легких задач типа health-check-ов.
Теперь, когда ты умеешь ограничивать мыслительные ресурсы своих подопечных, задача трех тел для тебя станет нипочем, если ты понимаешь о чем я!👽
Как обычно ставь свои пальчики, сердешки и огонечки, чтобы твой покорный слуга все выходные ждал понедельника, дабы написать свой новый пост.🙇
🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍15❤4😁4🔥2
Кто плотно сидел на java или dotnet, тот будет приятно удивлен тому, что например в go вся наша вайб-код писанина удобно укомплектовывается в один единственный бинарный файл. И что самое интересное, никаких тебе рантаймов для работы этого бинарника не нужно - все уже положили внутрь!
После таких вот вундервафель может возникнуть закономерный вопрос. А можно в таком случае тот самый ультратонкий distroless (который, напомню, содержит в себе необходимый минимум + runtime) раздеть до самых носков? Чтобы размер нашего образа сводился лишь к размеру получившегося бинаря!
И вот, в продолжение нашей серии постов, встречайте его величество Scratch-образы! Тип образов, в котором не то что оболочки, в нем даже мокрого пятнышка не осталось!
Серьезно, это не шутка.
scratch - это спецобраз без операционной системы, без shell, без /bin/sh, без ВООБЩЕ НИЧЕГО:FROM scratch
COPY ./my-static-binary /
ENTRYPOINT ["/my-static-binary"]
Да как это вообще работает!?
Docker запускает твой бинарник напрямую как PID 1. Никакой магии, просто голый syscall к ядру хоста. Как будто бы мы запустили этот самый бинарь прямо на хосте.
Но не забывай:
ls, cat, ps, да и не нужны они раз shell-а нет😅Зато результат - образы размером в несколько мегабайт вместо гигабайт!
Зачем это нужно?
Идеально для production микросервисов на Go/Rust, которые компилируются в standalone бинарники. Меньше attack surface, быстрее пуллится, меньше места на диске.
Кстати, Scratch идеально подходит для финального образа в multi-stage builds:
# Этап сборки приложения
FROM golang:1.21-alpine AS builder
...
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o /app/main .
# Финальный этап - минимальный образ
FROM scratch
...
COPY --from=builder /app/main .
CMD ["./main"]
А на этом у меня все! Удачного начала дня! И по классике, не забывайте ставить ваши реакты, а то я буду рыдать горькими слезками
🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥16👍10❤2😁2
Ты хочешь отследить, какие файлы изменились в контейнере после его запуска для диагностики проблем. Какая команда поможет тебе увидеть все изменения в файловой системе?
Anonymous Quiz
12%
docker logs container_name
23%
docker inspect container_name
49%
docker diff container_name
17%
docker history container_name
Ох уж эта вечная дилемма: либо даешь процессу полный root и он творит что хочет с системой, либо запускаешь под обычным юзером и потом часами разбираешься, почему оно не может открыть сокет или примонтировать том.В контексте докера это реализуется через флаг
Но Linux-боги подумали об этом и придумали штуку под названием capabilities - это какталончик на краковскую колбасуVIP-пропуска в ночной клуб, только для процессов!🎫
--cap-add!Что такое capabilities?
Это набор конкретных привилегий, которые можно выдавать процессам по отдельности. Типа "можешь биндить на привилегированные порты", "можешь менять сетевые настройки", но при этом никакого доступа к дискам.
Как юзать --cap-add:
# Даем возможность биндиться на порты < 1024
docker run --cap-add NET_BIND_SERVICE nginx
# Позволяем менять сетевые настройки
docker run --cap-add NET_ADMIN my-vpn-app
# Даем права на работу с raw сокетами (для ping например)
docker run --cap-add NET_RAW alpine ping google.com
А кейсы то будут,?
NET_BIND_SERVICENET_ADMIN SYS_ADMINDAC_OVERRIDEХоба и ты умеешь гибко настраивать безопасность, а кому нужны лишние терки с коллегами из ИБ по середине рабочей недели?? Правильно - никому. Поэтому смело ставь реакт за полезняшку!
🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍14🔥6❤3🤔2
В процессе разработки ты изменил код и пересобрал образ. При запуске контейнера заметил, что приложение работает в старой директории. Какую директива Dockerfile надо использовать, чтобы установить рабочую директорию?
Anonymous Quiz
6%
RUN cd /app
75%
WORKDIR /app
13%
ENV PATH=/app
5%
COPY . /app
В мире IT существует довольно много идеалистических концепций, внедрив которые их авторы обещают золотые горы и кисельные берега. Одной из таких концепций является 12-factor app, в целом, и ее подпункт stateless, в частности. Штука очень полезная, но реальность оказывается гораздо прозаичнее, поскольку есть приложения и сервисы, которые по своей природе stateful.
Поэтому, запускаете вы контейнеры на проде или на тесте, всегда задавайте себе вопрос, а не stateful ли данное приложение. И если ответ положительный, то к контейнеру необходимо примонтировать том.
Возвращаясь к посту про типы томов, в compose, естественно, есть ручки, дергая за которые мы можем подключить тома к любому из описанных нами контейнеров.
Синтаксис:
services:
postgres:
image: postgres:15
volumes:
- pgdata:/var/lib/postgresql/data # именованный том
- ./logs:/var/log # bind mount
volumes:
pgdata: # объявляем именованный том
Кастомизируем именованный том:
services:
app:
...
volumes:
cache:
name: my_new_volume
driver: local
driver_opts:
...
Здесь мы указали:
Зачем это нужно?
Volumes - это база любого production compose-файла. А в связке с build получается полноценная среда разработки! Поэтому знать, понимать и помнить это просто необходимо!
А на сегодня у меня все. Как обычно, не забывайте ставить свои реакты и всем хороших выходных.
🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍8🍾4🔥3❤2