Docker Ninja – Telegram
Docker Ninja
1.05K subscribers
30 photos
91 links
По всем вопросам обращаться к @nesudimov_eu
Download Telegram
🤚Фэйсконтроль ты не пройдешь🤚

Ох уж эта вечная дилемма: либо даешь процессу полный 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


А кейсы то будут,?
➡️ Nginx/Apache часто нужно биндиться на 80/443 порт → NET_BIND_SERVICE
➡️ VPN-приложения ковыряются в маршрутизации → NET_ADMIN
➡️ Мониторинг-тулзы читают системную инфу → SYS_ADMIN
➡️ Бекапы работают с файловыми атрибутами → DAC_OVERRIDE

Хоба и ты умеешь гибко настраивать безопасность, а кому нужны лишние терки с коллегами из ИБ по середине рабочей недели?? Правильно - никому. Поэтому смело ставь реакт за полезняшку!🤑

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍14🔥63🤔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:
...


Здесь мы указали:
Имя, с которым будет создан новый том. В компоузе будем обращаться по имени cache
Тип драйвера
Различные опции для этого драйвера

Зачем это нужно?
➡️ Базы данных: данные переживут пересоздание контейнера
➡️ Development: bind mount для live reload кода
➡️ Логи: складываем на хост для мониторинга
➡️ Кэши: если используем build в компоузе, то сваливаем в том кэш загруженных зависимостей

Volumes - это база любого production compose-файла. А в связке с build получается полноценная среда разработки! Поэтому знать, понимать и помнить это просто необходимо!

А на сегодня у меня все. Как обычно, не забывайте ставить свои реакты и всем хороших выходных.🍺

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍8🍾4🔥32
🍋 Easy peasy lemon squeezy 🍋

Однажды составлял Dockerfile для приложения с distroless образом. Конечно же я не был подписан на ваш любимый и неповторимый Docker Ninja, поэтому, по незнанию воткнул там вот такое CMD go run main.go. И конечно же, контейнер не поднялся...

Ну что может пойти не так?

И тут я могу вам сказать, что мы наконец докопались до самой сути серии постов, отвечающих на вопрос подписчика. Напомню, вопрос звучал так: работает ли shell и exec формы в Distroless и From Scratch образах?

Давайте проникнемся shell и exec формами команд!
Когда ты пишешь CMD go run main.go (shell форма), Docker пытается выполнить это через /bin/sh -c "go run main.go". А тк в distroless и FROM scratch образах нет ни shell, ни /bin/sh, то запускаться это дело не будет.
#  Факапится в distroless
FROM gcr.io/distroless/static
COPY myapp /
CMD myapp --config prod.yaml

# Получаем:
exec /bin/sh: no such file or directory


Что же с exec формой?
#  А она работает как часы
FROM gcr.io/distroless/static
COPY myapp /
CMD ["/myapp", "--config", "prod.yaml"]


То же самое касается ENTRYPOINT:
#  Провал
ENTRYPOINT ./start.sh

# Успех
ENTRYPOINT ["./start.sh"]


Так же и с RUN. Если вы вдруг удумали собирать что-то в distroless/scratch образах (господь вам в помощь, отчаянные) его так же пишем в exec форме.

Но как же тогда работает exec?
Если что distroless, что scratch гол-ы, как сокол-ы, то как же вообще в нем запускается хоть что либо??
Тут все просто! Настолько просто что мы аж растянули это на 3 поста!😐 Так как контейнер это всего лишь процесс, то exec форма работает изнутри как системный вызов execve.

Запомни правило:
В минималистичных образах всегда используй exec форму ["команда", "аргумент1", "аргумент2"] вместо shell формы команда аргумент1 аргумент2.

Теперь твои контейнеры будут стартовать с загадочными ошибками, а не падать! 😄

Ставь свои реакты, если уже тоже наступал на эти грабли! Если не наступал тоже ставь! А на этом я откланяюсь и хорошей вам рабочей недели!

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍15🔥62
В твоем проекте есть Docker Compose файл с несколькими сервисами. Ты хочешь проверить, корректно ли составлен файл перед запуском. Какую команду использовать?
Anonymous Quiz
26%
docker compose validate
32%
docker compose check
22%
docker compose config
20%
docker compose verify
👍6🔥3
🧙‍♀️Берём укропу, потом кошачью... 25 картошек, 17 ... ведро воды и ..., охапку дров - компоуз готов 🧙‍♀️

Все совпадения случайны! Ни один ПМ-м ни капли не похож на демогоргона. В среду все девопсы думают исключительно о работе и только о работе!

Среда Маленькая пятница. Неделя подошла к своей медиане, а ты уже душой на даче в Лосево, смотришь с котом под пледом новый сезон Очень странных дел... Но тут тебя затягивает в Изнанку очередной звонок Димы Горгина - PM-а: 'Слушай, а можешь быстренько поднять staging версию приложения? Только там порты другие нужны, и базу отдельную, и логи в другое место... А две?!'

А потом еще и продакшн со своими капризами подтянется! 😅

Хорошая новость - не нужно плодить docker-compose файлы! На такой случай юзаем override файлы для гибкого слияния конфигураций.


ДА, Docker Compose умеет накладывать конфигурации друг на друга не привлекая внимания санитаров:
# docker-compose.yml (база)
version: '3.8'
services:
app:
image: myapp:latest
ports:
- "3000:3000"

# docker-compose.override.yml (автоматом подхватывается)
version: '3.8'
services:
app:
ports:
- "8080:3000" # перезапишет базовый порт
environment:
- NODE_ENV=development


Для прода создаем отдельный файл:
# docker-compose.prod.yml
version: '3.8'
services:
app:
environment:
- NODE_ENV=production
deploy:
replicas: 3


Зачем заморачиваться?
Потому что без дублирования кода ты получаешь элегантное управление окружениями! Одна база, куча вариаций.
➡️Dev-у нужны дебаг порты? - Пжалста.
➡️Staging-у отдельная БД? - Легко.
➡️Проду кластер из трёх реплик? - Да не вопрос!

🍲А теперь заряжаем наш котел всеми нужными ингредиентами:🍲
docker compose -f docker-compose.yml -f docker-compose.prod.yml up

Хоба, и видишь финальный результат слияния!

Кстати, помнишь наши посты про depends_on и volumes? Все эти секции тоже отлично переопределяются через override файлы!

Теперь у тебя есть конфиг на все случаи жизни, а у меня твой реакт, репост и хорошее настроение! 🎉

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥15👍8😁42
В production среде твой контейнер потребляет слишком много RAM и влияет на другие сервисы. Контейнер уже запущен. Как ограничить память без остановки?
Anonymous Quiz
70%
Использовать команду docker update --memory
15%
Перезапустить контейнер с флагом --memory
11%
Изменить файлы в /sys/fs/cgroup/ вручную
5%
Остановить контейнер и пересобрать образ
🚽Метим территорию правильно🚽

Вчера копался в старом legacy-проекте и наткнулся на докерфайл с директивой MAINTAINER. А звучит то как мейн-тей-нер! Сразу вспомнил школу, как классе эдак в пятом все друг друга спрашивали, а какая у тебя роспись и ты как маститый райтер достаешь маркер и портишь школьное иммущество свои личным тэгом.

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


FROM ubuntu:14.04
MAINTAINER "Вася Пупкин <vasya@example.com>"
RUN apt-get update


Бац, и все подумали, что мы теперь настоящие DevOps-ы!

Но Docker давно похоронил эту директиву и пометил как deprecated еще в версии 1.13. Почему? А цимес в том, что MAINTAINER была слишком специфичной — только для автора, и всё. А что если нужно добавить версию, описание, ссылки на документацию?

Тут на смену приходит LABEL 📝
Правильный современный подход использовать LABEL:
FROM ubuntu:22.04
LABEL maintainer="vasya@example.com"
LABEL version="1.0.0"
LABEL denoscription="Мой крутой микросервис"
LABEL org.opencontainers.image.source="https://github.com/vasya/my-app"


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

Когда у тебя в продакшне крутится сотня контейнеров, а в 3 утра что-то упало — метаданные твой спаситель! Быстро понять, кто автор, какая версия, где исходники. Плюс, многие CI/CD системы парсят эти лейблы для автоматизации.
Ну а уж если ты на досуге что-то разрабатываешь, публикуя на гитхаб, то сам бог велел пометить, что именно ты придумал очердной экстравагантный способ поднимать дженкинс в контейнере.

Ставь свой бесценный реакт, если не метишь там, где не положено и делаешь это всегда только по ветру!

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
👍175🔥3
📋 Это мой кандидатский сценарий. Слушай devops, слушай пролетарий 📋

Однажды мы с вам касались вопроса, как работают docker registry и там я вкинул парочку слов о неких манифестах и что мол это как инструкция к тому, как из слоев собрать полноценный образ.

Сегодня же хочу рассказать вам об этих самых манифестах чуточку подробнее, ведь если задуматься, то именно этот механизм, помимо прочих его фич, позволяет нам при пулле образа собрать все слои воедино, хотя мы качаем их по сети, где может случиться все что угодно!


Что это за зверь такой?
Manifest — это метаданные образа в JSON формате (этакий паспорт).
Когда ты делаешь docker pull, сначала качается именно манифест, а потом уже слои по списку.
# Можно даже посмотреть на структуру
docker manifest inspect nginx:latest


Хлобысь и ты видишь всю подноготную: архитектуру, размеры слоев, их SHA256 хеши и порядок восстановоения слоев.
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
...,
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 841,
"digest": "sha256:af320b2df7e2bde33bd04165a7cad0b510f6ce6461d8f2e9c906fc77f99a8d21",
"platform": {
"architecture": "unknown",
"os": "unknown"
}
},
...
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 2292,
"digest": "sha256:7de350c1fbb1f7b119a1d08f69fef5c92624cb01e03bc25c0ae11072b8969712",
"platform": {
"architecture": "arm64",
"os": "linux",
"variant": "v8"
}
},
...
]
}


Нафига тут SHA256?
Выше я уже упоминал про некие хэши в формате SHA256. Вся соль в том, что каждый слой образа идентифицируется по SHA256 хешу его содержимого. То есть, на основе изменений высчитывается хэш. Изменился файл - изменился хеш - новый слой! По такому же принципу работает git.
Далее мы обращаемся при push-е/pull-e через Registry API v2. Он, в свою очередь использует Content Addressable Storage, чтобы разрулить все вопросики с образами.

При push/pull операциях:
1. 📤 Клиент шлет манифест в registry
2. 🔍 Registry проверяет целостность по хешам
3. 📦 Качаются только недостающие слои
4. Проверка SHA256 на каждом шаге

Ну они и напридумывали! А зачем это все?
➡️ Безопасность: невозможно подменить слой незаметно
➡️ Эффективность: дедупликация слоев между образами
➡️ Целостность: гарантия, что скачанное = загруженному
➡️ Версионирование: каждый образ — уникальная комбинация слоев

Теперь понимаешь, почему твой nginx всегда одинаковый на dev и prod!? 🎯

Все, больше не гружу ваши понедельничные головушки сложной информацией. Перевариваем и до встречи в следующих постах!

А ты ставь реакт, если тоже любишь копаться в архитектурных деталях! Пиши свои вопросы в директ канала! И продуктивного тебе рабочего/учебного дня!!!

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12👏3🔥2
🍰 Тысча 🍰

Коллеги, в предновогодней суете совсем не успел отметить с вами здоровский факт! В четверг 04.12.25 количество подписчиков канала перевалило за отметку в 1000!!!

Для меня это не только знаменательное событие, но и сигнал к действию. Так что, я с еще большим рвением буду работать над полезным контентом. Более того, я готовлю для всех читателей небольшой подарочек на Новогодние праздники. Чтобы новый год для вас начался не только с оливьешки и Голубого огонька, но и с ударной дозы полезных знаний, которые позволят достичь новых карьерных горизонтов!

Конечно, нет худа без добра, и наоборот, добра без худа. Новые горизонты открываются и для меня. И хоть тема docker довольно обширная, но уже сейчас, я чувствую, что хотелось бы поведать и о других гранях devops ремесла. И сейчас у меня уже есть наметки новых идей. Осталось только научиться работать со всем объемом задуманного. Поэтому не серчайте сильно, если пара-тройка постов окажется не такой качественной как прежде. Ваше ожидание и вера в мои силы будет лучше наградой и окупится, как говорится, сторицей!

Что касается этого канала. Работа продолжается в том же темпе. Концепция канала меняться не будет. Но я со всей дури думаю о новых рубриках и ваши предложения по этому поводу будут как нельзя кстати! Озвучить их вы можете так же в директ канала или мне в личку - @nesudimov_eu.

На этом я откланяюсь и еще раз, плодотворной вам недели!💪🏻
Please open Telegram to view this post
VIEW IN TELEGRAM
3🎉17🔥5🏆3😁1
🚜 Едут, едут комбайнеры, едут, едут на поля 🚜

Помнишь те славные времена, когда твоя любимая компания "Рога и копыта" была маленьким стартапом из 5-ти человек. Тогда и трава была зеленее, и снег в Питере выпадал в декабре, а блейзер казался напитком богов. Но прогресс не стоит на месте и теперь уже в вашем штате больше бухгалтеров, чем ИТ-шников. А вместо 10 контейнеров, статусы которых ты можешь посмотреть введя docker ps, тебе приходится лезть в Service Mesh.

Такие масштабы усложняют не только твою жизнь, но и подходы к организации таких базовых вещей как сборка и хранение логов, авторизация, сети со всем их вланами и политиками, системы хранения данных. А Docker хоть и мощный инструмент, но его возможности все равно не резиновые. Да и процессы в компании могут требовать гораздо больше, чем хранение данных в локальных volumes или bridge сети.

И теперь стоишь ты такой перед выбором: либо костылить интеграцию через жепу левое колено, либо отказываться от Docker совсем в пользу "проверенных дедовских методов".

Фрустрация реальная! Особенно когда вся команда смотрит на тебя глазами "ну что, твой любимый Docker справится с нашим железом?"


И тут на арену выходят Docker Engine plugins - модульная система расширения функциональности, которая превращает Docker из швейцарского ножика в полноценный комбайн! 🚀

По сути, эта штука позволяет Docker интегрироваться с внешними системами без хирургического вмешательства в сам движок. Это как расширения для браузера, только для контейнеров - хочешь новую функцию? Подключил плагин и вперед!

Типы плагинов
🗄 Volume plugins - интеграция с внешними системами хранения (NetApp, AWS EBS, Ceph)
🌐 Network plugins - кастомные сетевые драйверы (Weave, Calico, Flannel)
🔐 Authorization plugins - контроль доступа к Docker API
📝 Log plugins - отправка логов в внешние системы (Splunk, Fluentd)

Работаем с ними так:
# Посмотрим, что уже установлено:
docker plugin ls

# Устанавливаем NFS plugin
docker plugin install trajano/nfs-volume-plugin:latest


Как г-рится, не так уж и страшен черт, как его молюют.

Теперыча, прокачиваем наш контейнер для работы с NFS
# Создаем volume с использованием плагина
docker volume create -d trajano/nfs-volume-plugin \
--opt device=192.168.1.1:/mnt/routerdrive/nfs \
--opt nfsopts=hard,proto=tcp,nfsvers=4,intr,nolock \
nfsmountvolume

# Используем в контейнере
docker run -it --name my_nfs_container \
-v nfsmountvolume:/mnt/data \
alpine sh

Хоба, и твой контейнер теперь работает с сетевым хранилищем! 📦

Преимущества этого решения
➡️ Enterprise интеграция: подключаешься к существующим уже инфраструктурным решениям без костылей
➡️ Гибкость: расширяешь Docker под свои нужды, а не наоборот
➡️ Совместимость: используешь корпоративные системы хранения и сети
➡️ Масштабируемость: один раз настроил плагин - используешь везде

Короче, плагины - это способ сделать Docker действительно enterprise-ready без переписывания всего с нуля! В production среде без них часто просто никуда - стандартных драйверов не хватает для серьезных задач.

ПыСы: помни, что плагины работают с правами хоста, так что не качай левые сборки из интернетов - потом не говори, что не предупреждал! 😏

Ставь реакт, если было интересно! А то я буду думать Да ниче не буду думать, просто буду тихо рыдать под душем, чтобы не было видно слез.😭 Потому что истинные комбайнеры не плачут, истинные комбайнеры ссу.. принимают гигиенические процедуры для лица посредством ресурсов собственного тела!💪

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍51🗿1
🔄СтопуемСтаруем!🔄

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

На этот раз к тебе подходит некий Аркадий Рукожопов (совсем не говорящая фамилия, неет), который отвечал за последнюю релизнутую фичу, со словами: "Ты знаешь, я забыл проверить кое какую штуковину в конфиге. Так то все работает, но в некоторые моменты может сильно нагрузить систему. Можем сейчас подредачить на бою и перезапустить. Заодно и проверим, на выходных как оно работает."

Ух... отлично, потестить на проде... Вариант ответа "Отправить пососировать бибоний" для тебя заблокирован из-за недостаточно развитого красноречия, поэтому ты стоически берешся за эту задачу. Bсе было бы просто если бы не важные данные, которые во славу time-to-market, были успешно непрокинуты в volume.

О да! Вечер перестает быть томным...


Но не зря ты носишь хоть и виртуальный, но все же статус Довакина! Давным давно ты изучил секретный туум docker stop/start!

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

Базовый синтаксис:
docker stop [OPTIONS] CONTAINER [CONTAINER...]
docker start [OPTIONS] CONTAINER [CONTAINER...]


Вот как ты выйдешь из этой ситуации сухим:
# Заходим в контейнер
docker exec -it my_container /bin/sh

# Шурудим в конфиге

# Остановка контейнера по имени
docker stop my_container

# Запуск остановленного контейнера по имени
docker start my_container

Оп-ля и изменения применились.

А как так, мы же остановили контейнер?
Остановили, но не убили! Все изменения в запущенном контейнере пишутся в writable layer по всем заветам Layered FS. Когда мы стопаем контейнер, они остаются там же. При перезапуске через docker start или же через docker restart мы перезапускаем и процесс нашего приложения. А приложение уже перечитывает конфиг.

И кстати, если на вашем пути попался такой же новичок, но контенеров у него уже несколько, можем провернуть то же самое и со всей партией.
# Запуск нескольких контейнеров одновременно
docker start container1 container2 container3


Видишь? Никаких новых контейнеров, никаких потерянных данных. Просто берешь и продолжаешь с того места, где остановился!

Зачем это нужно в реальной жизни?
➡️ Сохранение состояния приложения: разрабатываешь веб-приложение с базой данных внутри контейнера? Start позволяет сохранить все данные между перезапусками
➡️ Экономия ресурсов в CI/CD: переиспользование контейнеров с предустановленными зависимостями сокращает время инициализации тестовых сред
➡️ Отладка production-инцидентов: можно остановить проблемный контейнер для анализа логов, затем запустить снова без пересоздания
➡️ Управление ресурсами сервера: в средах с ограниченными ресурсами позволяет временно останавливать неиспользуемые сервисы и запускать по требованию

Не забывай юзать docker ps для просмотра статуса контейнеров и docker rm для окончательного удаления остановленных контейнеров.

ПыСы: помни — docker start работает только с контейнерами, которые уже существуют. Если контейнер удален через rm, то никакой магии не будет, придется создавать заново.

А на этом я раскланяюсь, до встречи на следующей неделе и хороших вам выходных!

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥7👌2
🕸Сети не путать! Сети изучать!🕸

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

docker run -d my_container - и вот я уже потираю ручки от того, какой же я DEVOPS! Но тут мне прилетает сообщение от разраба: "Не робит... Как будто этот сервис не может достучаться до другого внутреннего сервиса". А они то на одном хосте!!!

Все мои тщетные потуги решить проблему самостоятельно не оправдались. Поэтому пришлось вызывать моего личного DevOps Сенпая. Недолго думая, он написал одну единственную команду и все стало ясно - какой же я балбес...


Той командой был docker network ls. И проблема была в том, что для connectivity сервисов нужно было добавить их в единую docker сеть (если мы конечно хотим сделать все правильно с точки зрения безопасности и лучших практик).

По сути, это ни что иное как docker network list. То есть она показывает нам ID, имя, тип драйвера и область видимости каждой сети.

Вот как это выглядит в деле:
# Просмотр всех сетей на хосте
docker network ls
# Выводит NETWORK ID, NAME, DRIVER, SCOPE для каждой сети


Можем фильтрануть вывод по нужным нам данным:
# Форматированный вывод только имен сетей
docker network ls --format "table {{.Name}}\t{{.Driver}}\t{{.Scope}}"
# Кастомная таблица для focused analysis определенных атрибутов


Видишь? Как помнишь по умолчанию у тебя всегда есть три системные сети: bridge (дефолтная), host (прямой доступ к сети хоста) и none (полная изоляция). А дальше - все что создал сам или Docker Compose.

А вот тут становится интересно! Если видишь кучу кастомных bridge networks - значит, у тебя микросервисная архитектура с сегментацией или с чьей-то забывчивостью. Overlay networks - это multi-host deployment, скорее всего Swarm. А если только дефолтный bridge - то либо все просто, либо кто-то не подумал о безопасности.

Зачем это нужно?
➡️ Диагностика connectivity проблем - быстро видишь доступные сети для troubleshooting межсервисного взаимодействия
➡️ Аудит сетевой безопасности - проверяешь изоляцию между разными tenant networks и ловишь потенциальные дыры
➡️ Планирование архитектурных изменений - анализируешь текущую топологию перед scaling и оптимизацией
➡️ Автоматизация мониторинга - интегрируешь в скрипты для контроля соответствия корпоративным политикам

Так что теперь, когда тебе приходит коллега с вопросом "почему сервисы друг друга не видят?", ты знаешь с чего начать! Первым делом - docker network ls, а потом уже разбираться в деталях. Ставь свои сердечки и огонечки, если зашло, и спокойного тебе прода! И не забывай писать свои вопрсы в директ канала или мне в личку - @nesudimov_eu.🔥

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥12👍3💯2
📦VOLUME me baby one more time📦

Ремесло девопса заключается не только в автоматизации, но и в выпрямлении и упрощении кривых рабочих процессов. Упростить для нас, это значит сделать настолько элементарным, что даже самый неподготовленный тестировщик специалист справится с работой используя только документацию.

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

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


Сегодня у нас директива VOLUME в Dockerfile, которая дает нам возможность прямо в образе указать, что и куда монтировать.

Синтаксис простой как тыква:
VOLUME /path/to/directory/inside/container

# Или можем указать сразу несколько точке
VOLUME ["/path1", "/path2"]


Вот как это выглядит в деле:
# Создает точку монтирования для логов веб-сервера
FROM nginx:alpine
VOLUME /var/log/nginx


# Создает две точки монтирования для пользовательских файлов и кеша
FROM node:16
WORKDIR /app
VOLUME ["/app/uploads", "/app/cache"]


Видишь? Ты этой директивой говоришь Docker создать анонимный том с уникальным ID и автоматически примонтировать его к указанному пути. Данные в таком томе переживут смерть и воскрешение контейнера!

Но тут есть один хитрый момент! VOLUME работает не как bind mount через -v[], где ты сам указываешь, что куда монтировать. Здесь Docker создает анонимные тома и сам ими управляет. Это удобно для стандартизации, но может удивить новичков.

Зачем это нужно?
➡️ Автоматическая персистентность данных - шобы никто при запуске контейнера не забыл указать сохранять логи в отдельную папочку
➡️ Стандартизация точек монтирования - очень полезно, когда у вас множество однотипных сервисов (логи сюда, конфиги туда, картинки с мемасиками в images)
➡️ Упрощение оркестрации - все как и для первого пункта, только в контексте Docker Compose (забыл прописать в файле тома, а они все равно создались)
➡️ Изоляция данных от container layer - если бэкапим стейт контейнера через docker export

Директива VOLUME тесно связана с типами томов в Docker, секцией volumes в Docker Compose, директивой COPY для копирования данных в образ.

В общем директива VOLUME отлично подходит, как "защита от дурака" - меньше флагов или инструкций в docker compose, спокойнее вечера! Юзай на здоровье! Но есть у для нее кейсы и по-веселее. А на этом я с тобой прощаюсь, хорошего дня!

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
8👍5🔥3
Ты запустил контейнер с флагом --restart=always, но заметил, что он постоянно перезапускается из-за ошибки в приложении. Какая команда поможет временно остановить автоматические перезапуски?
Anonymous Quiz
21%
docker stop container_name
23%
docker pause container_name
2%
docker kill container_name
54%
docker update --restart=no container_name
👍6
🧶 Все переплетено 🧶

Бывает вылизываешь до кровавых пятен daemon.json на проде, а контейнеры все равно стартуют по 30 секунд каждый. Смотришь в логи. Видишь кучу ошибок от каких-то runc, containerd и dockerd. И понимаешь - ты понятия не имеешь, кто это и почему! Начинаешь рестартить docker, но проблема то возвращается, то исчезает.

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

Поэтому сегодня рассмотрим с вами что это за звери такие runc, containerd и как они связаны с dockerd.


По сути, когда ты пишешь docker run, запускается целый пайп различных операций:
🔹 Docker Engine (dockerd) - главный босс, который принимает твои команды через REST API
🔹 containerd - менеджер среднего звена, управляет образами и снапшотами
🔹 runc - низкоуровневый работяга, создает изоляцию на уровне ядра
🔹 Linux kernel - предоставляет примитивы namespaces и cgroups

Вот как это выглядит в деле:
docker run -d nginx:latest


Что происходит под капотом:
1. Docker CLI стучится к dockerd через Unix socket
2. dockerd дергает containerd через gRPC API
3. containerd загружает образ, создает снапшот и вызывает runc
4. runc создает namespaces (PID, Network, Mount) и запускает процесс

А вся эта магия описывается в OCI спецификации:
{
"ociVersion": "1.0.0",
"process": {
"args": ["nginx", "-g", "daemon off;"]
},
"linux": {
"namespaces": [
{"type": "pid"},
{"type": "network"},
{"type": "mount"}
]
}
}


runc использует эту конфигурацию для настройки изоляции процессов!

Зачем это знать:
➡️ Отладка проблем - понимаешь, на каком уровне сломалось (dockerd, containerd или runc)
➡️ Оптимизация производительности - настраиваешь containerd snapshotter под свою нагрузку
➡️ Глубокий мониторинг - собираешь метрики на уровне containerd для анализа
➡️ Enterprise безопасность - настраиваешь изоляцию на уровне runc для compliance

Теперь когда в очередной раз контейнер откажется стартовать, ты будешь знать где искать проблему! А не тыкать рестарт docker-а в надежде на чудо.

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

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
110🔥6👍2🙈1
🧘‍♀️Работа с осознанными🧘‍♀️

Тот кто хоть раз пытался заделать весь обвяз для интеграционных тестов отлично знает, что дело это гиблое и ресурсоемкое. Тут тебе надо и хосты найти свободные, и связность для них настроить, а если тесты слишком долгие, то и вторую такую пачку хостов. А если вы сидите в облаке и терраформ с ансиблой покурить. Хорошо, если вы со своей командой успели пересесть на кубер. Но такое, увы, встретишь не всегда. А если тесты вы запускаете раз в день? Все остальное время твоя инфраструктура будет простаивать? Цены то на оперативу видел??

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

А что если я скажу, что такой инструмент есть? И имя ему Docker!

Чиво бл...? Предлагаешь поднять контейнеры внутри контейнера? Linux никогда такого не разрешит - упремся в безопасность!


И тут на помощь приходит флаг --privileged - оружие массового поражения для изоляции контейнеров!

По сути, эта штука превращает твой контейнер в полного властелина хост-системы. Docker при использовании --privileged отключает большую часть своей защиты со словами: "Это все твое, Симба".

Вот как это выглядит в деле:
# Контейнер получает доступ ко всем устройствам хоста
docker run --privileged -it ubuntu:20.04 /bin/bash


А вот сравнение обычного и привилегированного контейнера:
# Обычный контейнер - ограниченный список устройств
docker run -it ubuntu:20.04 ls /dev
console core fd full mqueue null ptmx pts random shm stderr stdin stdout tty urandom zero

# Привилегированный контейнер - полный доступ к /dev хоста
docker run --privileged -it ubuntu:20.04 ls /dev
autofs core fd hvc2 hvc7 loop1 loop6 net ptp0 ram11 ram2 ram7 sda sg0 shm tty0 tty13 tty18 tty22 tty27 tty31 tty36 tty40 tty45 tty5 tty54 tty59 tty63 ttyS1 vcs1 vfio zero
bsg cpu_dma_latency full hvc3 kmsg loop2 loop7 null pts ram12 ram3 ram8 sdb sg1 stderr tty1 tty14 tty19 tty23 tty28 tty32 tty37 tty41 tty46 tty50 tty55 tty6 tty7 ttyS2 vcsa vhost-net
btrfs-control cuse fuse hvc4 kvm loop3 mapper nvram ram0 ram13 ram4 ram9 sdc sg2 stdin tty10 tty15 tty2 tty24 tty29 tty33 tty38 tty42 tty47 tty51 tty56 tty60 tty8 ttyS3 vcsa1 vport0p0
bus dri hvc0 hvc5 loop-control loop4 mem ppp ram1 ram14 ram5 random sdd sg3 stdout tty11 tty16 tty20 tty25 tty3 tty34 tty39 tty43 tty48 tty52 tty57 tty61 tty9 urandom vcsu vport0p1
console dxg hvc1 hvc6 loop0 loop5 mqueue ptmx ram10 ram15 ram6 rtc0 sde sg4 tty tty12 tty17 tty21 tty26 tty30 tty35 tty4 tty44 tty49 tty53 tty58 tty62 ttyS0 vcs vcsu1 vsock


При запуске контейнера с этим ключем внутри происходит следующее:
🔹 Контейнер получает все 40+ Linux capabilities - от CAP_SYS_ADMIN до CAP_NET_ADMIN
🔹 Доступ ко всем устройствам в /dev (а их там немало!)
🔹 AppArmor и SELinux профили идут лесом
🔹 Seccomp фильтры тоже отдыхают

Кейсы использования:
➡️ Docker-in-Docker для CI/CD пайплайнов (классика жанра!)
➡️ Работа с блочными устройствами - монтирование дисков, LVM
➡️ Системное администрирование из контейнера
➡️ Отладка и мониторинг системных ресурсов

Чтобы не раскуривать capabilities и namespaces, просто юзаем этот флаг и получаем троянского коня полнофункциональный linux процесс, который и швец, и жнец, и коня на скаку, и козу на возу!

Но помни, такой сетап юзаем только во внутренней сети и очень осознанно! Пусть твои контейнеры будут мощными, но управляемыми! А то потом будешь разбираться, кто тебе всю систему перелопатил 😅

Попробовал в деле? Ставь 🔥! А если есть вопросы - пиши в директ или личку, разберем!

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍2🔥2
В твоем проекте есть docker-compose.yml для разработки и docker-compose.prod.yml для продакшена. Как правильно объединить эти конфигурации при деплое?
Anonymous Quiz
29%
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
25%
docker compose --override docker-compose.prod.yml up
36%
docker compose merge docker-compose.yml docker-compose.prod.yml
10%
docker compose --config docker-compose.prod.yml up
🔥2
📖Смотришь в книгу, видишь фигу👎

Бывает сидишь такой, никого не трогаешь, спокойно доживаешь последнюю недельку на работе и тут бац - прилетает алерт, что супер важный микросервис на проде упал. Лезешь в docker logs, но ничего не можешь увидеть, потому что контейнер лежит. Лезешь за ними в заведомо настроенный ELK/Opensearch и ничего не понимаешь. Никакой ошибки или баги не было. Сервис как будто просто вырубили руками.

И тут до тебя доходит, а вдруг кто-то еще не успел оклематься после новогоднего корпоратива и случайно удалил тот самый супер важный сервис? А что если это диверсия!??!?!?! Ужас!😱

В такие моменты хорошо бы узнать какие именно операции проводили с dockerd за последнее время. Какой контейнер падает, какой образ пуллится, какая сеть создается?


И тут на помощь приходит docker events! Эта команда подключается напрямую к потоку событий и показывает в реальном времени каждый чих происходящий на хосте с dockerd.

По сути, эта штука как логгер всех операций Docker daemon-а. Создал контейнер - событие. Остановил - событие. Скачал образ - тоже событие. Весь lifecycle твоих контейнеров как на ладони!

Базовый синтаксис такой:
# Мониторинг всех событий в реальном времени
docker events

2025-12-21T21:48:54.964163622+03:00 container kill f0770ec141f769b7330e1ff5fd206096c5ccc50a215803e75920a2cdc62bd080 (image=nginx, maintainer=NGINX Docker Maintainers <docker-maint@nginx.com>, name=elated_jepsen, signal=9)
2025-12-21T21:48:55.465756543+03:00 network disconnect 0a0d7305d434379c8336fc51f51e2a1bacd1065b0a24c18ec65eb53c1e061c63 (container=f0770ec141f769b7330e1ff5fd206096c5ccc50a215803e75920a2cdc62bd080, name=bridge, type=bridge)
2025-12-21T21:48:55.499566110+03:00 container die f0770ec141f769b7330e1ff5fd206096c5ccc50a215803e75920a2cdc62bd080 (execDuration=12, exitCode=137, image=nginx, maintainer=NGINX Docker Maintainers <docker-maint@nginx.com>, name=elated_jepsen)

Хоба! Кто-то из любимых коллекг кильнул этот контейнер!

А вот как это выглядит в деле:
# События за последний час = perfect для дебага
docker events --since "1h"

# События конкретного контейнера
docker events --filter container=webapp --filter type=container


Что умеет фильтровать:
Событий у докера может быть много и в них легко закопаться до следующего года. Так что полезно знать, что конкретно можно там увидеть.
⚙️ Типы объектов: container, image, network, volume - каждый тип живет своей жизнью
⚙️ События контейнеров: create, start, restart, stop, die, destroy, pause, unpause, kill, oom
⚙️ События образов: pull, push, delete, import, load, save, tag, untag
⚙️ По времени: устанавливаем интересующий нас диапазон


Зачем это надо?
➡️ Дебаг падающих сервисов - отслеживаешь последовательность start/die и понимаешь, где все пошло по причинному месту
➡️ Аудит в shared-окружении - видишь кто что делает через события create/destroy/pull, полезно для соблюдения политик ИБ
➡️ Автоматизация реакций - запускаешь скрипты или уведомления при определенных событиях
➡️ Отладка Docker Compose - смотришь порядок создания сетей и томов при сложных multi-service развертываниях
➡️ Мониторинг ресурсных проблем - ловишь OOM events раньше чем они убьют продакшен

Теперь ты можешь читать Docker daemon как открытую книгу без всяких фиг! Больше никаких тыканий пальцем в небо при дебаге. Попробовал docker events в деле? Ставь реакт!

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍3🔥3