Docker Ninja – Telegram
Docker Ninja
1.05K subscribers
30 photos
91 links
По всем вопросам обращаться к @nesudimov_eu
Download Telegram
🎮 Первому игроку приготовиться 🎮

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

Один из таких способов не делать лишних движений - команда docker init.


docker init инициализирует docker проект со всеми необходимыми для запуска контейнера файлами, да ещё может делать это из специальных шаблонов под конкретный язык 😝

Находясь в папке с нашим проектом запускаем:
docker init

Welcome to the Docker Init CLI!

This utility will walk you through creating the following files with sensible defaults for your project:
- .dockerignore
- Dockerfile
- compose.yaml
- README.Docker.md

Let's get started!

? What application platform does your project use? [Use arrows to move, type to filter]
PHP with Apache - (detected) suitable for a PHP web application
Go - suitable for a Go server application
Java - suitable for a Java application that uses Maven and packages as an uber jar
Python - suitable for a Python server application
Node - suitable for a Node server application
Rust - suitable for a Rust server application
ASP.NET Core - suitable for an ASP.NET Core application
Other - general purpose starting point for containerizing your application
Don't see something you need? Let us know!
Quit

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

После её запуска в папке с проектом обнаружим следующие файлы:
- .dockerignore
- Dockerfile
- compose.yaml
- README.Docker.md

Если какой-то из указанных файлов уже имеется в папке (или в случае с compose, там будет docker-compose.yml) то команда спросит надо ли перезаписать существующий файл.

Лёгким движением руки экономим себе драгоценные минуты на более полезные задачи 🪄


🥷 Docker Ninja 🥷
1👍10🔥1
💰 No cash, no trash 🗑

Сегодня поговорим о флаге --no-cache в команде docker build. Этот флаг незаменим, когда необходимо гарантировать, что все шаги сборки выполняются с нуля, игнорируя кэш.

А начерта нам игнорить кэш, когда у него сплошные плюсы? - спросите вы и будете правы. Но, лишь от части.

Самый базированный кейс для этого флага, это сборка образа через CI систему. Например, если мы в своем dockerfile указали тэг для базового образа latest, то всегда держим в уме, что тэг это всего-то строка, которая не всегда отражает реальную версию образа. И, чтобы гарантировать, что при сборке у нас будет использован наисвежайший свежак, мы ставим флаг —no-cache

Пример использования команды:
docker build --no-cache -t my_app_image:latest .



🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥2
📌 Раздаём ярлыки 📌


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

Директива LABEL в Dockerfile позволяет добавлять метаданные к вашим образам. Это может быть особенно полезно, когда вы работаете в команде или с большой инфраструктурой, где необходимо быстро идентифицировать назначения и особенности каждого образа.

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

# Добавляем метаданные
LABEL maintainer="Senpai <senpai@devops.com>"
LABEL version="1.0"
LABEL denoscription="Это образ для веб-приложения на базе Ubuntu 20.04"

# Установка необходимых пакетов
RUN apt-get update && apt-get install -y nginx

# Копируем файл конфигурации
COPY nginx.conf /etc/nginx/nginx.conf

# Запускаем Nginx
CMD ["nginx", "-g", "daemon off;"]


Теперь ваш образ содержит метаданные, которые помогут быстро понять его назначение и версию/ А так же, вы теперь знаете кому дать в лоб за косяки в образе😈


🥷 Docker Ninja 🥷
1👍15🔥1
🔮Видишь терминал? А его нет 🔮

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

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

docker run -it nginx /bin/bash


Этот самый режим есть как для команды run, так и для exec:
docker exec -it my_container /bin/bash


Как видим, флаг -t используется у нас в связке с -i. И, если последний и возможно хоть как-то применить в одиночку, то вот -t без интерактивного режима ничем нам не поможет. А все потому, что для работы с терминалом нам, как ни крути, нужен доступный stdin. Без него мы просто не сможем ничего написать в терминале.

Так что запоминаем как "Отче наш": нужен терминал, смело ставь -it!

🥷 Docker Ninja 🥷
👌6👍3
Ты готовишь контейнер с Nginx к релизу и хочешь убедиться, что все процессы внутри контейнера работают корректно. Какая команда поможет тебе быстро увидеть список процессов и их идентификаторы внутри запущенного контейнера?
Anonymous Quiz
23%
docker inspect my_container
21%
docker top my_container
43%
docker exec my_container ps aux
12%
docker ps -a
👍6👎3🔥1👏1
🐳 Гнездо кита 🐳

Как все мы с вами помним, Docker Engine архитектурно состоит из трех компонентов: dockerd, docker API и клиент в виде cli командлета. И сегодня мы поговорим о том, через какие механизмы осуществляется связь клиента с API. Тут есть в чем разобраться, поехали!

Взаимодействие может происходит через различные механизмы. Всего их три: UNIX сокеты, TCP и FD.

🔹 UNIX Сокеты:
Это наиболее распространенный способ взаимодействия Docker клиента с демоном Docker на одной и той же машине. UNIX сокеты обеспечивают быструю и безопасную связь, так как они не требуют сети и защищены атрибутами файловой системы. По умолчанию Docker использует UNIX сокет /var/run/docker.sock. И, частенько, этот файлик надо прокидывать в контейнеры, которым необходима информация о других контейнерах. Например, когда ставим Traefik

🔹 TCP Сокеты:
Когда ты работаешь с удалёнными Docker демонами, на помощь приходят TCP сокеты. Они позволяют взаимодействовать с Docker API через сеть. Это удобно для управления Docker на удалённых серверах, но стоит помнить о безопасности и использовать TLS для шифрования данных.

🔹 File Denoscriptor (FD):
Этот способ менее распространён, но иногда используется в специфичных сценариях, когда необходимо передать сокет напрямую в уже открытый дескриптор файла. Это может быть полезно для интеграций с другими системами, где передача через файловый дескриптор предпочтительнее.

Более подробно каждый из них мы рассмотри в последующих постах, а сейчас пока можно просто запомнить их, чтобы в случайной беседе с коллегами блеснуть своими глубочайшими познаниями😎


🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍9🔥1
⚖️ Вокруг одна политика 📜

Все мы знаем как запускать контейнеры и перезапускать их вручную, но не менее важно иметь возможность перезапускать их автоматически. То есть полезно было бы иметь возможность настраивать какие-то политики перезапуска контейнеров в случае их падения. И тут нам поможет флаг —-restart у команды docker run.

Начнем с базового использования:
# Запускаем контейнер с политикой перезапуска
docker run --restart=always mywebserver


В этом примере контейнер будет автоматически перезапущен в случае остановки или перезагрузки системы.

Всего же у нас имеется 4 вида restart-policy:
- no: контейнер не будет перезапускаться (это значение по умолчанию).
- always: контейнер будет перезапускаться всегда. В случае ручной остановки контейнера, он будет запущен только после ручного запуска или после рестарта dockerd.
- unless-stopped: похож на always, но после ручной остановки контейнера с такой политикой, стартануть его можно только через ручной запуск.
- on-failure[:max-retries]: контейнер будет перезапущен только в случае ошибки, и можно указать максимальное количество перезапусков.

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


🥷 Docker Ninja 🥷
👍12
🔪 Псс, парень, есть контейнеры? 🔪

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

Сегодня я расскажу вам о том. как же мы можем посмотреть существующие на хосте контейнеры.

Выглядит это так:
# Запускаем команду
docker ps

# Получаем вывод
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d1f2e3c4b5f6 nginx:latest "nginx -g 'daemon of…" 3 hours ago Up 3 hours 0.0.0.0:80->80/tcp web_server
a7b8c9d0e1f2 mysql:5.7 "docker-entrypoint.s…" 2 days ago Up 2 days 3306/tcp, 33060/tcp db_server


Как видим, команда показывает нам табличку со следующими данными:
- CONTAINER ID - уникальный ID контейнера, присваеваемый при его создании. По этому id так же можно найти папку с данными конкретного контейнера в файловой системе хоста, на котором он запущен.
- IMAGE - используемый образ для создания контейнера
- COMMAND - cli команда, которая по-умолчанию запускается при старте контейнера (та самая CMD)
- CREATED - время создания контейнера
- STATUS - статус, по которому можно отследить состояние контейнера. Если юзать команду без флагов, то мы увидим только работающие контейнеры, а как увидеть все, расскажу в следующих постах
- PORTS - пара host/container port, которая назначена при старте контейнера
- NAMES - имя контейнера, назначенное с помощью флага или сгенерированное автоматически

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

🥷 Docker Ninja 🥷
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍9
В Dockerfile твоего приложения указан базовый образ с тегом latest. Какой подход позволит гарантировать, что при каждой сборке через CI систему будет использована самая актуальная версия базового образа?
Anonymous Quiz
16%
Использовать команду docker build -t my_app_image:tag .
40%
Использовать команду docker build --no-cache -t my_app_image:tag .
9%
Добавить в Dockerfile строку RUN apt-get update
35%
Перед сборкой каждый раз пуллить latest версию базового образа docker pull base_image:latest
👍4
🤘 Гоп-стоп, мы подошли из-за угла 🤘

Понедельник...
Контейнер упал после очередного наплыва пользователей в выходные дни. Прод горит, в кофемашине образовался чайный гриб, а PM орет что-то про дедлайны...
А все потому, что кто-то забыл ограничить память для своего "легкого" сервиса, который внезапно сожрал всю RAM на хосте!

И тут на помощь приходит флаг --memory (или -m для ленивых).

Этот флажок позволяет установить лимит потребления оперативной памяти для контейнера:

docker run -m 512m nginx
docker run --memory=2g my_heavy_app


Как можно понять из листинга команд, мы тут предлагаем каждому контейнеру не брать на грудь более 512 Мб и 2 Гб соответственно. А помогает нам в этом Linux cgroups.

А что будет, если контейнер попытается съесть больше дозволенного? В таком случае, на сцену выходит OOM Killer с предложением посмотреть на звезды, небо с этим морем, потому что контейнер увидит это в последний раз.💀

Зачем это нужно?
Где еще можем встретить:
- У вас микросервис с утечкой памяти (особенно часто такое можно встретить в Java коде - привет финтеху👋🏻) — ограничили 1GB и спите спокойно
- Тестовое окружение на одном сервере — каждому контейнеру свой кусочек пирога и никто никому не мешает.

Помните: железо не резиновое, а память — самый дорогой ресурс в дата-центре!


Ставь 🔥, если пост спас твой прод от внезапного OOM!

🥷 Docker Ninja 🥷
🔥9👍3👌2
Please open Telegram to view this post
VIEW IN TELEGRAM
🤞 Last hope 🤞

Бывало так. Приходишь в офис, наливаешь себе спокойно кофе и думаешь:
- Ну, вчерашний релиз мы успешно пережили. Сегодня будет хороший день!

Но тут залетает PO и говорит, что какой-то умник ломает наше приложение. Id сессии можно увидеть лишь только в логах.

- Отлично, - думаешь ты, - сейчас глянем вывод docker logs. Если только...
Да, именно так - любимый коллега забыл прокинуть логирование в stdout.

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

А вот и нет! В базовом образе контейнера не завезли оболочку. Да, и такое бывает - оптимизация, мать ее за ногу!
И вот, ты уже совсем поник и не знаешь что делать, как вдруг О великий и могучий чатгпт stackoverflow рассказывает нам про команду docker cp, которая позволяет дешево и сердито копировать файлы туда-сюда между контейнером и хостом!

Синтаксис простой как три копейки:
# Из контейнера на хост
docker cp my_container:/path/to/file ./local_path

# С хоста в контейнер
docker cp ./local_file my_container:/path/inside


И да, копировать можно даже целые папки:
docker cp my_container:/app/logs ./debug_logs


Ну и самое интересно, что команда работает независимо от того, запущен контейнер или висит мертвым грузом. Главное — узнать его ID или имя, например с помощью docker ps! Ай, хорошо...!!!

Зачем это нужно?
Реальные кейсы из окопов DevOps-а:
- Приложение легло, а тебе нужно вытащить дамп памяти или логи для анализа
- Срочно подкинуть исправленный конфиг без пересборки образа
- Забэкапить данные перед обновлением
- Вытащить артефакты сборки из билд-контейнера


Ставь 👍, если спас твой стул от следов возгорания!


🥷 Docker Ninja 🥷
👍172
Новый разработчки вручную настроил рабочую среду внутри контейнера и хочет сохранить все изменения в новый образ. Какая команда поможет создать образ из текущего состояния запущенного контейнера?
Anonymous Quiz
22%
docker save my_container my_new_image:v1
27%
docker commit my_container my_new_image:v1
21%
docker export my_container > my_new_image:v1
30%
docker build -t my_new_image:v1 my_container
🔬 Проникаем в СИЗО🔬

Мы уже не раз задавались вопросом, как Docker умудряется так ловко изолировать контейнеры друг от друга? И уже дошли до того, что все эти контейнеры — обычные процессы в хостовой системе, так почему же они не видят друг друга?

Внимание! За кулисами работают механизмы Системной ИЗОляции - Linux Namespaces 🕵️

В команду великих комбинаторов входят:
🔹 PID namespace — каждый контейнер видит только свои процессы. Твой nginx думает, что он единственный на свете!
🔹 Mount namespace — файловая система контейнера изолирована от хоста. Можешь крушить что угодно внутри — хост останется цел!
🔹 Network namespace — вот почему порты контейнеров не конфликтуют с хостом! У каждого свой сетевой стек!
🔹 IPC namespace — изоляция межпроцессного взаимодействия. Никто не подслушает твои сообщения!
🔹 UTS namespace — каждый контейнер может иметь свой hostname, не мешая соседям.
🔹 User namespace — мапинг пользователей между контейнером и хостом.

Зная это становится понятно, что Docker это вовсе не чорное колдунство, а просто виртуозное использование совсем не новых возможностей Linux ядра для создания изолированных процессов! 🧙‍♂️

Ставь 👌, если тайны изоляции стали чуточку понятнее!

🥷 Docker Ninja 🥷
👌10👎1🔥1
💊Игра на нервах💊

Сегодня поговорим о высоком - о тонком искусстве заставить ваших коллег тихо плакать в туалетной кабинке после каждого PR важих докерфайлов! Я говорю об искусстве наговнокодить в Dockerfile.

И первый наш кейс - контекст выполнения команд внутри контейнера во время сборки.

Для примера, посмотрим на код.
FROM ubuntu:20.04

RUN cd /app && mkdir logs
COPY . /app/

RUN cd /app && npm install
CMD cd /app && npm start


Почему же это плохо?

1. На каждый RUN необходимо указывать контекст исполнения - cd /app &&.... Привет принципы DRY.
2. В случае использвания других директив, наподобие COPY, необходимо будет прописать полный путь до нужной папки. То есть поведение остальных инструкций совсем не явная история.
3. Из предыдущих двух пунктов вытекает 3 - сопровождать такой Dockerfile неудобно от слова "горите в Оду, авторы этого чуда".

А вот, правильный вариант:
FROM ubuntu:20.04

WORKDIR /app
RUN mkdir logs
COPY . .
RUN npm install
CMD npm start


И чем это лучше?

1) Получаем постоянство контекста. Установив раз рабочую директорию в /app мы будем производить все действий только в ней, то тех пор пока не переназначим. А это минус cd /app в каждом блоке команд, да и самих таких блоков станет гораздо меньше.
2) Не нужны лишние RUN-ы чтобы создавать папку. Если папки нет, то WORKDIR создает ее автоматически
3) Такой код более читаемый и предсказуемый
4) Так мы можем использовать относительные пути для других дирректив файла
...
WORKDIR /app
COPY . ./subdir/
...



Так что, берите на заметку и ваши коллеги вам скажут спасибо👌🏻
А впереди у нас выходнульки, значит дружно ставим 🔥


🥷 Docker Ninja 🥷
🔥15
🆘 Спасите наши push-и 🆘

Представь:
Ты геройски настроил все, что хотел твой тимлид, на уже запущенном контейнере. Но тут, посреди бела дня у тебя вырубает электричество (ты конечно же сидишь на удаленке - понедельник же!!!).
И вот, интернета нет, комп отсчитывает последние 10 минут оставшиеся на бесперебойнике. Весь фронт работ отразить в Dockerfile или compose не успеешь, а хорошо бы было сохранить все каким-то образом и донести до офисного компа. И ты начинаешь тихо материться под нос...

Но погоди паниковать! У нас есть старый добрый docker save - команда, которая упакует твой образ в tar-архив быстрее, чем ты скажешь "надо было читать канал Docker Ninja, там точно был ответ!".

🎯 Как это работает:

Базовый синтаксис не замысловатый:
docker save -o nginx.tar nginx:latest


Или через перенаправление, как истинный пигвин из Мадагаскара🐧:
docker save nginx:latest > nginx.tar


Хочешь сохранить сразу несколько образов? Не вопрос:
docker save -o my_stack.tar nginx:latest postgres:13 redis:alpine


🤔 Шо та такое ты уже рассказывал!...

🔹О да! Давным давно, в посте про команду docker export, которая создает архив файловой системы контейнера. В отличие от него, docker save сохраняет полный образ со всеми его слоями, метаданными и историей. Это как разница между копированием папки и созданием полноценной резервной копии диска.

🔹Кстати, у docker save есть команда антоним, как docker import для экспорта. Но это уже история для другого поста!

🔹А еще мы можем вспомнить docker commit, который вместо пушей, спасает наши нервы, путем сохранения всех изменений из работающего контейнера в образ.🤡


Теперь то ты точно сохранишь свои труды в целости! Поставь реакцию, если сразу захотел записать образ на дискету!


🥷 Docker Ninja 🥷
1👍6🔥3
Зачем оно вообще нужно!?

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

Но есть несколько щепетильных ситуаций...⬇️
👍8
Ты работаешь с legacy приложением в контейнере. Необходимо создать backup всей файловой системы контейнера в tar-архив для миграции на другой сервер. Какую команду использовать?
Anonymous Quiz
29%
docker save container_name > backup.tar
44%
docker export container_name > backup.tar
12%
docker commit container_name backup_image
15%
docker cp container_name:/ backup.tar
🐶 На вайбах Хатико 🐶

На днях коллега спрашивает: "Слушай, как мне подключиться к контейнеру, который уже запущен? docker exec же только новые процессы создает!" И тут я понял - настало это время!!! Пора рассказать про команду, которая может как спасти твой день, так и безжалостно убить весь контейнер одним неосторожным Ctrl+C!

Речь пойдет о docker attach. Команде для подключения к основному процессу уже запущенного контейнера.

Базовый синтаксис прост как валенок:
docker attach richard_gere:2009


Например, запустили контейнер в фоне:
docker run -d --name professor parker:wilson
docker attach professor


И хоба! Ты видишь логи процесса в реальном времени, можешь взаимодействовать с основным процессом. Но фишка тут в том, что attach подключает тебя именно к процессу с PID 1 (тому самому, что указан в CMD/ENTRYPOINT), а не создает новую сессию как docker exec!

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

1. Дебаг интерактивных приложений - основной процесс ждем, что ты ему введешь какие-то данные.
2. Работа с legacy-контейнерами - где нету встроенной терминальной оболочки
3. Мониторинг в реальном времени - например контейнер постоянно падает и через docker logs ты не успеваешь увидеть его логи

⚠️ Главная ловушка: нажал Ctrl+C в attach-сессии = отправил SIGINT основному процессу! Это может его убить и завалить весь контейнер. Чтобы безопасно отключиться, используй Ctrl+P, Ctrl+Q.


Помни: attach = привязка к существующему процессу, exec = новый процесс. Выбирай с умом!


🥷 Docker Ninja 🥷
👍6🔥42