Лучший опыт

Возможности Docker, о которых вы не знали. Часть 2.

Первая часть статьи. Оптимизация использования кэша в сборках Эффективное использование кэша сборки Docker может значительно ускорить процесс создания образов за счет повторного применения ранее кэшированных слоев вместо их пересоздания. Это особенно важно для итеративной разработки и конвейеров непрерывной интеграции/непрерывного развертывания (CI/CD), где эффективность сборки может напрямую влиять на производительность. Что так
Возможности Docker, о которых вы не знали. Часть 2...

Первая часть статьи.

Оптимизация использования кэша в сборках

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

Что такое кэш сборки Docker?

Кэш сборки Docker  —  это механизм, сохраняющий результаты предыдущих шагов сборки для повторного использования в будущих сборках. Когда Docker собирает образ, он последовательно выполняет инструкции в Dockerfile. Если контекст шага (его команды и входные данные) не изменился с момента последней сборки, Docker использует кэшированный результат вместо повторного выполнения шага.

Как использовать кэш сборки Docker

Чтобы оптимизировать использование кэша сборки Docker, необходимо создать Dockerfile таким образом, чтобы шаги, которые меняются реже, выполнялись перед шагами, которые меняются чаще.

Пример оптимизации кэша

# Базовый образ, который редко меняется 
FROM python:3.8-slim

# Установка зависимостей, которые редко меняются
COPY requirements.txt .
RUN pip install -r requirements.txt
# Копирование исходного кода делается в последнюю очередь, так как он меняется более часто
COPY . /app

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

Случаи использования оптимизации кэша

  • Разработка: для ускорения процесса сборки во время локальной разработки при неоднократной сборке образов.
  • CI/CD-конвейеры: для сокращения времени сборки и потребления ресурсов, особенно когда сборка инициируется изменениями исходного кода, которые не влияют на зависимости или базовый образ.

Рекомендуемые практики

  • Размещение инструкций с разумной очередностью: инструкции, которые реже меняются (например, установка пакетов), размещайте перед инструкциями, которые меняются чаще (например, копирование исходного кода).
  • Минимизация изменений слоев: группируйте связанные команды, чтобы свести к минимуму количество слоев и уменьшить частоту изменений, которые приводят к аннулированию кэша.
  • Использование явных версий: для базовых образов и пакетов применяйте явные версии вместо тегов типа latest, чтобы обеспечить повторяемость и оптимизировать использование кэша.

Распространенные ошибки

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

Дополнительная информация

Ограничение ресурсов контейнера

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

Что такое ограничение ресурсов?

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

Как использовать ограничение ресурсов

Чтобы ограничить ресурсы для контейнера, можно использовать такие флаги, как --cpus, --memory (или -m), --memory-swap и другие при запуске контейнера с помощью docker run.

Пример ограничения ресурсов процессора и памяти

docker run -it --cpus="1.5" --memory="500m" myapp:latest

Эта команда ограничивает использование контейнером не более 1,5 процессора и 500 МБ памяти. Данные ограничения позволяют запретить контейнеру чрезмерно потреблять ресурсы в ущерб другим контейнерам или хост-системе.

Случаи использования ограничения ресурсов

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

Рекомендуемые практики

  • Корректное распределение ресурсов: выделяйте достаточно ресурсов, чтобы приложение работало адекватно в нормальных условиях; слишком жесткие ограничения могут привести к низкой производительности приложения.
  • Мониторинг и корректировка: постоянно отслеживайте использование ресурсов контейнерами и при необходимости корректируйте ограничения в зависимости от фактического использования и требований к производительности.
  • Использование Compose для нескольких контейнеров: при управлении несколькими контейнерами используйте Docker Compose для определения ограничений ресурсов в файле docker-compose.yml, что упрощает управление и обеспечивает согласованность.

Распространенные ошибки

  • Превышение лимита ресурсов: слишком высокие лимиты ресурсов могут свести на нет преимущества ограничения, позволяя контейнерам по-прежнему потреблять слишком много ресурсов.
  • Игнорирование свопа: будьте осторожны с настройками свопа (--memory-swap), так как слишком большой своп может привести к переполнению диска и снижению производительности.
  • Отсутствие мониторинга: отсутствие мониторинга фактического использования ресурсов может привести к плохо отрегулированным настройкам  —  либо к чрезмерному, либо к недостаточному ограничению ресурсов контейнера.

Дополнительная информация

Мониторинг с помощью Docker-событий

Docker-события (Docker events) предоставляют информацию от Docker-демона в режиме реального времени, давая представление о действиях, происходящих в среде Docker. Эта функция может быть полезна для мониторинга, отладки и автоматизации реакции на различные события жизненного цикла Docker.

Что такое Docker-события?

Docker-события  —  это поток структурированных данных, представляющих изменения состояния или действия объектов Docker, таких как контейнеры, образы, тома и сети. Каждое событие содержит информацию о типе объекта, выполненном действии и времени его выполнения. Мониторинг этих событий помогает понять, как происходит манипулирование объектами Docker с течением времени, и запустить автоматические рабочие процессы на основе определенных действий.

Как использовать Docker-события для мониторинга

Для мониторинга с использованием Docker-событий используйте команду docker events. Можете отфильтровать поток событий по типу объекта, типу события или определенным атрибутам.

Пример мониторинга событий контейнера

docker events --filter 'type=container'

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

Пример расширенных возможностей фильтрации

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

docker events --filter 'type=container' --filter 'event=start' --filter 'event=stop' --filter 'label=environment=prod'

Случаи использования Docker-событий

  • Мониторинг в реальном времени: для отслеживания происходящего в среде Docker в режиме реального времени.
  • Отладка: для диагностики проблем путем понимания последовательности событий, приведших к ошибке или неожиданному состоянию.
  • Автоматизация: запуск сценариев или уведомлений на основе определенных Docker-событий, что позволяет улучшить конвейеры CI/CD или операционные рабочие процессы.

Рекомендуемые практики

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

Распространенные ошибки

  • Постоянный мониторинг всех событий без фильтрации: будьте избирательны в том, что вы отслеживаете, чтобы не столкнуться с перерасходом производительности.
  • Чрезмерная зависимость от CLI: при длительном мониторинге или в сложных средах использование только CLI для мониторинга событий может оказаться немасштабируемым решением; рассмотрите возможность использования API Docker или специализированных инструментов мониторинга.

Дополнительная информация

Запуск контейнеров в режиме “только для чтения”

Запуск контейнеров Docker в режиме “только для чтения” (“read-only”)  —  надежная мера безопасности, которая значительно снижает риск несанкционированного изменения файловой системы контейнера. Такой подход помогает предотвратить попытки злоумышленников изменить работающее приложение или его среду и повышает устойчивость контейнеров к атакам.

Что означает режим “только для чтения” для контейнеров?

Режим “только для чтения” для контейнеров Docker означает, что файловая система контейнера смонтирована как доступная только для чтения. В этом режиме контейнер и приложения внутри него могут читать файлы, но не могут записывать или изменять файловую систему. Это позволяет обеспечить запуск приложения с минимально необходимыми разрешениями, что повышает безопасность.

Как использовать режим “только для чтения”

Чтобы запустить контейнер в режиме “только для чтения”, используйте флаг --read-only при запуске контейнера с помощью docker run. Вот простой пример:

docker run --read-only -d myimage:latest

Поддержка потребностей в записи

Некоторым приложениям может потребоваться запись в определенные каталоги для временных данных или логов. Это можно сделать путем монтирования определенных каталогов как временных файловых систем (tmpfs) или как томов, доступных для записи. Вот как монтировать tmpfs для /tmp:

docker run --read-only --tmpfs /tmp -d myimage:latest

Случаи использования режима “только для чтения”

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

Рекомендуемые практики

  • Определение требований к записи: оцените свое приложение, чтобы определить каталоги, которым действительно нужен доступ к записи; используйте тома или монтирование tmpfs для обеспечения путей, доступных для записи, где это необходимо.
  • Всестороннее тестирование: тщательно протестируйте приложение в режиме “только для чтения”, чтобы выявить проблемы или необходимые корректировки перед развертыванием в продакшн.
  • Сочетание с другими методами обеспечения безопасности: используйте режим “только для чтения” как часть комплексной стратегии безопасности, включая пользовательскую настройку non-root, минимальные базовые образы и отказ от неиспользуемых возможностей.

Распространенные ошибки

  • Неуместное использование режима “только для чтения”: приложения, не предназначенные для работы в режиме “только для чтения”, могут неожиданно выйти из строя; требуется тщательная подготовка и тестирование.
  • Отсутствие доступа к записи, где это необходимо: обеспечьте альтернативные установки логирования и механизмов кэширования, требующих доступа к записи.

Дополнительная информация

Очистка с помощью Docker Prune

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

Что такое Docker Prune?

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

Как использовать Docker Prune

Удаление контейнеров

Команда для удаления всех остановленных контейнеров:

docker container prune

Удаление образов

Команда для удаления неиспользуемых образов (как “зависших”, так и не связанных ни с одним контейнером):

docker image prune -a

Удаление томов

Команда для удаления всех неиспользуемых томов:

docker volume prune

Удаление сетей

Команда для удаления всех неиспользуемых сетей:

docker network prune

Удаление сразу всего

Команда для удаления контейнеров, образов, томов и сетей за один раз:

docker system prune -a --volumes

Случаи использования Docker Prune

  • Регулярное обслуживание: для периодического освобождения дискового пространства в средах разработки и продакшна.
  • После тестирования или разработки: для удаления временных контейнеров, образов и сетей, созданных во время разработки или тестирования.
  • В рамках работы с CI/CD-конвейерами: для обеспечения чистоты среды и минимизации требований к хранению.

Рекомендуемые практики

  • Резервное копирование важных данных: перед выполнением команд для удаления томов (volume prune) убедитесь, что для томов, содержащих важные данные, созданы резервные копии. 
  • Осторожное применение в процессе продакшна: будьте осторожны с командами prune в средах продакшна; убедитесь, что эти команды не удаляют ресурсы, используемые в данный момент или необходимые для повторного использования.
  • Автоматизация команд удаления: рассмотрите возможность автоматизации удаления в безопасных средах (например, в среде разработки), чтобы регулярно очищать неиспользуемые ресурсы.

Распространенные ошибки

  • Удаление незарезервированных томов: удаление томов может привести к безвозвратной потере данных, если важные тома не были зарезервированы или исключены.
  • Удаление редко используемых, но необходимых образов: бездумный подход к удалению образов может привести к дополнительным затратам времени на повторное извлечение или восстановление нужных образов.

Дополнительная информация

Переопределение точки входа для отладки

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

Что такое переопределение точки входа?

Указывая ENTRYPOINT (точку входа) в Dockerfile, вы определяете исполняемый файл по умолчанию для контейнера. Переопределение точки входа при запуске контейнера позволяет запустить контейнер с другим исполняемым файлом или командой, что может быть особенно полезно при изучении среды контейнера или запуска отладочных инструментов в его файловой системе.

Как использовать переопределение точки входа

Можно переопределить точку входа контейнера с помощью флага --entrypoint в команде docker run. Вот как запустить контейнер с интерактивной оболочкой, минуя точку входа по умолчанию:

docker run --entrypoint /bin/sh -it myimage:latest

Эта команда запускает контейнер с /bin/sh в качестве точки входа, предоставляя интерактивный доступ к контейнеру.

Пример отладки с помощью альтернативной точки входа

Предположим, ваше приложение “упало” вскоре после запуска, и вы подозреваете, что дело в конфигурации. Переопределение точки входа позволит вам изучить среду или файлы конфигурации до запуска приложения:

docker run --entrypoint /bin/sh -it myimage:latest -c "cat /app/config/app.conf"

Случаи использования переопределения точки входа

  • Отладка: когда требуется проверка или взаимодействие с файловой системой контейнера до запуска приложения.
  • Устранение проблем при запуске: диагностика проблем, возникающих в процессе запуска приложения.
  • Запуск утилит или тестов: выполнение утилит, сценариев или тестов, упакованных в контейнер, без запуска основного приложения.

Рекомендуемые практики

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

Дополнительная информация

Управление несколькими средами с помощью Docker-контекстов

Относительно новая функция  —  Docker-контексты (Docker contexts)  —  позволяет управлять несколькими средами Docker с помощью одного клиента. Эта функция неоценима для разработчиков и инженеров инфраструктуры непрерывной интеграции и развертывания, которые часто взаимодействуют с различными хостами Docker, включая локальные среды разработки и тестирования, а также среды продакшна различных облачных провайдеров.

Что такое контексты Docker?

Контекст Docker хранит конфигурацию конечной точки Docker (например, Docker-демона, запущенного на локальном компьютере), кластера Docker Swarm или кластера Kubernetes. Переключение между различными контекстами позволяет легко направлять Docker CLI в различные среды без изменения переменных среды или конфигурационных файлов вручную. 

Как использовать контексты Docker

Создание нового контекста

Можно создать новый контекст, указывающий на определенный Docker-демон или кластер Kubernetes, с помощью команды docker context create. Вот пример создания контекста для удаленного хоста Docker:

docker context create remote-docker --docker "host=ssh://user@remote-server"

Эта команда создает новый контекст с именем remote-docker, который взаимодействует с Docker-демоном на remote-server через SSH.

Переключение между контекстами

Чтобы переключить активный контекст Docker, используется команда docker context use:

docker context use remote-docker

После переключения контекста все последующие команды Docker будут работать в среде remote-docker.

Доступ к списку контекстов

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

docker context ls

Случаи использования контекстов Docker

  • Развертывание в нескольких средах: для управления контейнерами в нескольких средах (разработка, тестирование, продакшн) или облачных провайдерах.
  • Удаленное управление Docker: для управления движками Docker, запущенными на удаленных хостах или в облаке, непосредственно с локального терминала.
  • Сценарии с CI/CD-конвейерами: для динамического переключения между различными средами Docker с целью сборки, тестирования и развертывания приложений.

Рекомендуемые практики

  • Именование контекстов: используйте описательные имена для контекстов, чтобы легко идентифицировать целевую среду.
  • Обеспечение безопасного доступа: при настройке удаленных контекстов, особенно через SSH, убедитесь, что доступ защищен и учетные данные управляются должным образом.
  • Корректное переключения контекстов в CI/CD: при использовании контекстов Docker в сценариях CI/CD убедитесь, что переключение контекстов четко указано и понятно, чтобы избежать развертывания в неправильной среде.

Распространенные ошибки

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

Дополнительная информация