Docker Ninja – Telegram
Docker Ninja
1.05K subscribers
30 photos
91 links
По всем вопросам обращаться к @nesudimov_eu
Download Telegram
🎮 Никакой личной жизни... 🎮

Порою, для понимания того, из-за чего твой контейнер ведет себя неадекватно, недостаточно увидеть логи. В некоторых ситуациях важно понимать, что происходит с файловой системой сразу же после запуска контейнера. И тут на помощь приходит команда docker diff. С ее помощью мы всегда можем выяснить, какие файлы были добавлены, изменены или удалены во время работы контейнера. Идеально, когда тебе нужно понять, что же всё-таки натворил тот гениальный скрипт, который ты писал перед корпоративом уже знатно приняв на грудь.

Работает это так:
# Запускаем контейнер
docker run -d --name test nginx

# И сразу же смотрим, куда nginx запустил свои грязные руки
docker diff test

# И получаем список изменений:
A /path/to/file/or/dir # добавлен файл или папка.
C /path/to/file/or/dir # изменен файл или папка.
D /path/to/file/or/dir # удалён файл или папка.


Если копать глубже, то мы поймем, что виноват в наличии данной команды наш любимый LFS. А если точнее, то те самые image layer и writable layer, разницу между которыми мы и смотрим.
Таким вот не хитрым, но вместе с тем гениальным решением получаем дополнительный инструмент для дебага контейнеров.🤗

Если было полезно, то обязательно реагируем пальчиками - 👍🏻


🥷 Docker Ninja 🥷
👍14
🐲 Великий китайский фаервол 🐲

По умолчанию, после установки Docker Engine, в хостовой системе создаётся сетевой интерфес docker0. Тип такого интерфейса bridge (подробнее о типах сетей в docker поговорим в следующих постах). Это значит, что контейнеры внутри такой сети будут изолированны от трафика внутри хостовой сети, а для доступа внутрь контейнера придется прокидывать порты.

Для тестовых нужд вполне достаточно и docker0, но вот на проде нам может понадобится большая изоляция контейнеров друг от друга или какие-то специфические настройки. Значит, нам важно иметь возможность создавать новые интерфейсы и такой функционал, конечно же, предусмотрен:
docker network create network_name


Вжух, и лёгким движением пальцев предотвращаем любые сливы🥭 в сети. А что там происходит внутри, можно подсмотреть вот тут.


🥷 Docker Ninja 🥷
🔥5👍1
А что там с compose?

С единичными контейнерами понятно. Если сеть не создана, то весь трафик идёт через интерфейс docker0.

Но неужели контейнеры компоуза так же по умолчанию общаются через этот интерфейс?
👍5
😷 Регулярная диспансеризация 🤒

Работа в ИТ хороша тем, что большую часть рутинных задач можно автоматизировать. Эта участь не обошла и периодическую проверку контейнеров на жизнеспособность.

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

Разработчики docker так же предусмотрели возможность держать руку на пульсе своего контейнера с помощью директивы HEALTHCHECK.

Она имеет две формы:
# проверяет состояние контейнера выполняя внутри него команду
HEALTHCHECK [OPTIONS] CMD command

#отключает любые проверки состояния из базового образа
HEALTHCHECK NONE


Настроить его мы можем вот так:
FROM nginx:latest

# Добавляем директиву
HEALTHCHECK \
CMD curl -f http://localhost/ || exit 1

# Остальная магия
...


После сборки мы получаем контейнер, который с определённой периодичностью (по умолчанию 30 секунд) запускает скрипт из CMD. Если несколько (по умолчанию 3) таких проверок вернут код ошибки 1, то контейнер получит статус unhealthy.

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

Ставь 🔥, если было полезно!

🥷 Docker Ninja 🥷
🔥9👍6
🐢 А что если сервис не успеет? 🐢

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

Чтобы этого избежать, мы конечно можем увеличить тайминги проверок, но это не совсем правильное решение, потому что они могут быть основаны на каких-нибудь бизнес требованиях (наподобие SLI/SLO/SLA).
🔥3👍2
Недавно безопасники нашли уязвимость в базовом образе, который ты используешь в Dockerfile.
Тебе поручили обновить образ до последней безопасной версии, при этом сохранив
остальные слои неизменными. Как это сделать?
Anonymous Quiz
8%
Изменить директиву CMD в Dockerfile и перестроить образ.
21%
Использовать команду docker commit на существующем контейнере.
61%
Обновить директиву FROM в Dockerfile и выполнить docker build заново.
10%
Удалить текущий образ с помощью docker rmi и создать новый.
🔥4
🤡 Пятничный troubleshoot-очный 🤡

Юзаю на работе docker stats,
Решаю все проблемы как Борецкий Стас!


Ты только что развернул новый сервис, а сервер уже кричит от боли. Логи молчат, у контейнера статус healthy? Кто виноват, а главное, что с этим делать?
Пора устраивать ревизию! Команда docker stats поможет быстро выяснить, кто из контейнеров потребляет больше ресурсов на хосте.

Пора действовать! Набирай:
docker stats

# Получим постоянно обновляющийся вывод, наподобие этого
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
b415e06e97ee one 0.00% 15.86MiB / 31.31GiB 0.05% 53MB / 242MB 27.6MB / 41kB 9


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

Забирайте команду к себе в копилку и пользуйтесь на здоровье!🤗


🥷 Docker Ninja 🥷
👍10🔥2
😈 Not today, Satan! 😈

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

Поскольку, в Docker изоляция чисто номинальная, то по факту root доступ в контейнере имеет все шансы стать root-ом на хостовой системе. Малейшая уязвимость или баг — и вся ваша безопасность идет коту под хвост. Но если ты используешь директиву USER, твое приложение работает от имени непривилегированного пользователя, и нежелательные гости остаются за воротами.

Пример использования:
# Берем базовый образ
FROM ubuntu:20.04

# Создаем пользователя и группу
RUN groupadd -r appgroup && useradd -r -g appgroup appuser

# Назначаем пользователя для выполнения команд внутри контейнера
USER appuser

# Запускаем приложение
CMD ["my_app"]


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

1:0 в пользу воинов света!
Ставь 😇, если пост был полезным.


🥷 Docker Ninja 🥷
😇13👍1
1️⃣ Но есть один нюанс 1️⃣

Как вы наверняка знаете, у пользователей и групп в линуксе есть не только их названия, но и id ( uid и gid).

И вот как раз с ними может возникнуть неловкий нюанс, который сведет все ваши старания по обеспечению безопасности на нет...
👍5
🙅‍♂ Oh, don't touch my tralala 🙅‍♂

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

И, наверняка, ни для кого не является секретом, что есть такой волшебный флаг -d или --detach.

Используем мы его так:
docker run -d -p 80:80 my_image


Интересно тут то, как это дело работает изнутри.

Как мы уже говорили, когда контейнер запускается без флага -d, терминал остается привязанным к стандартному вводу/выводу контейнера. Это значит, что весь вывод контейнера (stdout и stderr) будет отображаться в терминале.

Detach же работает по аналогии с линуксовым оператором &, который переводит процесс в фоновый режим.

Конечно, системные вызовы это не тема нашего поста и в них мы погрузимся в будущих постах, но, если копать detach ещё глубже, то выйдем на системный вызов setsid(), который отделяет наш контейнер (процесс) от управляющего терминала, делая его независимым.

А на этом я с вами прощаюсь и конечно же ставьте 👍, если пост был полезен!


🥷 Docker Ninja 🥷
👍10
🧤Война без конечностей 🧤

Ранним утром в четверг коллеги из разработки отдали свою новую поделку со словами: "Сразу в прод под нашу ответственность".

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

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

Пора применять более радикальные меры! Здесь на сцену выходит наш герой — docker kill. Эта команда без лишних вопросов отправляет контейнер в вечный отпуск не ждя никаких gracefull shutdown.
docker container kill [OPTIONS] CONTAINER [CONTAINER...]


А теперь поиграем в Таноса:
docker kill dr_strange
docker kill star-lord
docker kill spidy

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

🥷 Docker Ninja 🥷
😁7🔥3
😱 К нам едет ревизор! 😱

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

Возможности эти не такие большие и по большей части они позволяют нам менять какое-то поле конфига dockerd. Но есть довольно полезные экземпляры, например флаг —validate.

Из названия сразу понятно, что с его помощью можно что-то провалидировать и в нашем случае это будет конфиг dockerd. Таким образом, запуская dockerd с этим флагом, мы просто получаем ответ о валидности конфига.
$ dockerd --validate
configuration OK

# Для верности посмотрим код последней команды
$ echo $?
0


И вот теперь вопрос, зачем, а главное когда оно нам понадобится?

Тут все просто!
Когда вам необходимо с помощью какого-то IaC инструмента поднять докер на множестве хостов и при этом заменить дефолтный конфиг на свой. Еще интереснее, когда этот самый конфиг уникальный для некоторых групп хостов.

Просто ставите докер, закидываете свой конфиг и запускаете dockerd --validate с последующей обработкой кода ответа команды. И теперь вы всегда знаете, зашел ли ваш конфиг демону докера!

Ставь 👍🏻, если было полезно!


🥷 Docker Ninja 🥷
👍12🔥2
Через какой механизм докер управляет доступом и маршрутизацией трафика при создании сети?
Anonymous Quiz
9%
SELinux
68%
iptables
14%
UFW
9%
firewalld
👍4
🐈 На словах ты tar простой, а на деле img Толстой 🦁

Помнишь, как мы с тобой создавали свой первый образ из архива с помощью команды docker import? Но что, если нам понадобится наоборот из существующего контейнера сделать архив?! Сегодняшняя тема — команда docker export, которая позволяет это сделать.

Сама команда выглядит следующим образом:
docker container export [OPTIONS] CONTAINER


В живую это будет выглядеть примерно так:
docker export mycontainer > mycontainer_backup.tar


Хоба! И теперь у нас в руках есть копия файловой системы контейнера в виде архива, который можно позже развернуть с помощью docker import, как мы делали это раньше.

Используй docker export, чтобы сохранить свои шедевры и всегда быть на шаг впереди! 🧙🏼


🥷 Docker Ninja 🥷
👍10🔥2
⁉️ Да на кой это нам черт ⁉️

Команда docker export довольно специфичная и, с первого взгляда, применения ей можно и не найти. Тогда на кой черт она сдалась нам?!

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

Вперед!👇🏻
👍6👌1
🌐 Дурной devops - дурные сети. Сломал релиз - голодны дети 🦑

Docker Network Drivers, наверное, самая сложная часть этого инструмента, и одна из самых важных! Так что, сегодня давайте рассмотрим основные типы драйверов и их особенности.

1. Bridge 🛠
- По умолчанию используется для контейнеров на одном хосте.
- Создает частную сеть, изолированную от внешнего мира, но позволяет контейнерам на одном хосте "общаться" между собой.
- Отлично подходит для локальных разработок и тестирования.
- Вариант по умолчанию при создании сети

2. Host 🌍
- Контейнер использует сетевой стек хоста напрямую
- Полезен для приложений, которым требуется высокая производительность, но получаем дебафф в виде полного остутсвия сетевой изоляции.

3. Overlay 🕸
- Позволяет контейнерам на разных хостах общаться друг с другом. По факту соединяет в сеть несколько докер демонов.
- Используется для создания распределенных систем и кластеризации, например, в Docker Swarm.

4. Macvlan 🔌
- Позволяет контейнеру иметь собственный MAC-адрес, как полноценное сетевое устройство.
- Полезен для интеграции с сетевыми устройствами или когда требуется точная настройка сетевого интерфейса.

5. IPvlan 📡
- Позволяет контейнеру иметь собственный IP-адрес в сети, используя один физический интерфейс.
- Работает в режимах L2 и L3, обеспечивая гибкость в управлении трафиком.
- Отлично подходит для высокой плотности контейнеров и минимальной конфигурации сети.

6. None 🚫
- Отключает сеть для контейнера.
- Полностью изолирует контейнер от сетей. Полезно, когда контейнер творит такую дичь, что лучше его никому не видеть и не слышать.

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


🥷 Docker Ninja 🥷
1👍15🔥3
🐺 И волки целы и овцы сыты 🐑

Зачастую, чтобы собрать простейший образ с вашим приложением, приходится использовать массивные базовые образы со всем сопутствующим обвязом (sdk, сертификаты и прочие прелести из мира CI). В конечном итоге, мы можем получить монструозный многослойный образ, при запуске которого сразу и не скажешь, что деплоишь легкий контейнер.

Эту проблему отлично решает multi-stage build. Stage тут, это все, что идет после диррективы FROM до следующей такой диррективы.
Концептуально, это работает так:
1. Берем за основу образ с необходимым CI софтом
2. Собираем проект внутри него
3. Берем минимально необходимый образ, в котором наша аппликуха будет работать полноценно
4. Копируем в него собранный проект из второго шага

Фича может быть реализована разными способами, но сегодня рассмотрим один из самых распространенных.
FROM golang:1.23
...
RUN go build -o /bin/hello ./main.go

FROM scratch
COPY --from=0 /bin/hello /bin/hello
CMD ["/bin/hello"]


Как видим, здесь мы собираем бинарник в образе с golang sdk от версии 1.23, а далее берем минимальный образ scratch и копируем в него тот самый бинарь. Таким образом, получаем легкий образ без лишних файлов.


🥷 Docker Ninja 🥷
1👍15🔥1
💃🏻 Хороший тамада и конкурсы интерактивные!🕺🏼

Мы с вами уже знаем, что логи приложения внутри контейнера можно смотреть через команду docker logs. Все благодаря тому, что данная команда считывает stdout внутри контейнера. Но что делать, если мы хотим иметь возможность что-то передать внутрь контейнера? Как открыть stdin контейнера?

На такой случай предусмотрен флаг --interactive (или -i), который оставляет поток ввода контейнера открытым, позволяя отправлять данные в контейнер через стандартный ввод.
echo hello | docker run --rm -i busybox cat

# Ответ команды
hello


Скорее всего, многие из вас уже пользовались им в связке с другим флагом (-t), о котором мы поговорим в других постах. Но это не единственный кейс использования интерактивного режима на практике.

Использование флага -i позволяет создавать линуксовые пайпы через несколько вызовов различных контейнеров:
docker run --rm -i busybox echo "foo bar baz" \
| docker run --rm -i busybox awk '{ print $2 }' \
| docker run --rm -i busybox rev

# Ответ команды
rab


Эта фишка особенно помогает, когда нам нужно выполнить пайплайн на хосте, где нету какого-либо пакета, а установлен только docker. Например, мы имеем один мощный билд агент и не хотим морочить себе голову установкой чего-либо.

И, кстати, прошу заметить, что данный флаг присутствует не только в команде docker run, но и для docker exec!

🥷 Docker Ninja 🥷
1👍9🔥2
Ты столкнулся с ситуацией, когда контейнер в продакшене перестал отвечать, но статус у него UP. Разработчики уже выпустили хотфикс, и тебе нужно срочно остановить залипший контейнер для заливки фикса. Какой твой следующий шаг?
Anonymous Quiz
7%
Перезапустить сервер, на котором находится контейнер, чтобы устранить зомби процесс.
65%
Использовать docker kill, чтобы остановить проблемный контейнер без ожидания graceful shutdown.
1%
Попросить разработчиков еще раз проверить код и подождать, пока они устранят проблему.
26%
Перезапустить контейнер с помощью команды docker restart. 7 бед - 1 ресет.
👍6🔥1