Docker тормозит на windows

Обновлено: 07.07.2024

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

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

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

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

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

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

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

  • Неполадки внутри ядра ОС Linux, связанные с особенностью структуры кэша-объектов;
  • Проведение отладки внутри ядра с помощью команды perf.

Немного о команде perf. Как ни странно, мало кто использует данное решение, сталкиваясь с проблемой в Docker. Оно было создано с появлением версии 2.6.31, а представляет из себя достаточно универсальный инструмент для диагностики ядра системы.

С помощью perf можно провести диагностику системы, а также составить профиль для использования конкретным пользователем. Все предусмотренные ОС счетчики будут перестроены с учетом введения нужного профиля.

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

Запустив perf, вы можете столкнуться с весьма неожиданной для себя картиной. На скриншоте вы можете увидеть, как команда отработала на протяжении 10 секунд и представила данные в виде таблицы: слева находится информация о работе на железе, а справа – непосредственно в контейнере.


Обратите внимание, что начальные обращения в правой части направлены к ядру системы, то есть на распределение пространства. Все остальное, что отчетливо видно в левой стороне, используется для исполнения процессов в пользовательском пространстве. С первого взгляда, все нормально. А теперь посмотрите на вызов posix_fadvise. Как видите, существенную долю времени занимает именно он.

posix_fadvise() – это запрос, который составляет шаблон для дальнейшего обращения к одному и тому же файлу системы. С точки зрения быстродействия и повышения производительности, это очень выгодное решение.

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




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

Чтобы не допустить банальную ошибку, с которой мы столкнулись в данном примере, стоит помнить о простых правилах во время использования Docker. Во-первых, все контейнеры потребляют ресурсы всей аппаратной части, включая ресурсы ядра. А значит, нужно регулярно проводить диагностику именно этой части. И тут мы переходим к второму правилу: чтобы упростить себе жизнь используйте для отладки «perf»!

Начал изучать докер. После суток мучений я запустил проект в полном стеке с использованием докера. Но теперь я вижу увеличение времени ответа от сервера. App работало моментально на локальной машине на стандартном стеке nginx + php-fpm 7 + mysql. После настройки подобного стека на докере все работает заметно медленнее. Как можно это пофиксить?

  • Вопрос задан более трёх лет назад
  • 3183 просмотра

DevMan

a хостовая система какая?
следует понимать, что везде кроме пингвина докер - это виртуализация и, соответственно, дополнительный оверхед и/или неожиданные тормоза (например, в макоси "виртуальный" докер работает быстрее "нативного"). У меня MacOSX, что значит "виртуальный докер" быстрее "нативного"?
Я поставил то что предоставили на оф сайте.) Запустил через docker-compose и вижу таймауты в ответах.

DevMan

Правильно ли я понял, что нужно поставить допустим в virtualbox ubuntu server, пробросить порты на хостовую систему, поставить на ubuntu docker и там же запускать docker-compose?

DevMan

Сделал как вы сказали, запустилась виртуалка, запустил docker compose up
Все собралось.

В хост машине прописал

Не удается получить доступ к сайту

Что не так сделал?

DevMan

markmoskalenko, да, это я тупанул (вернее подсветка парсера сбила с толку, лучше выхлопы оборачивать в тег code).

DevMan

markmoskalenko, сорян, я сейчас занят. смогу плотнее посмотреть только вечером.

/Documens/www и все ок стало.

DevMan

Я бы сказал что даже очень не плохо. Уже нет желания вернуться к локальному серверу.
Правда теперь другая проблема.. не понятно почему но у сервера нет прав на запись в директорию, хотя chmod -R 777 uploads На всякий случай и решение оставлю.
При сборке php нужно добавить в Dockerfile
RUN usermod -u 1000 www-data Если у вас Linux, то накладные расходы там мизерные, вы и не заметите без тестов специальных
Если у вас MacOSX или Windows - то используется полноценная виртуализация. Для отладки это годится. Но в реальности Docker будет развернут на сервере Linux. И тормозить перестанет.

Docker - это средство контейнеризации исключительно Linux (хотя и FreeBSD можно там взвести внутри).
Таким образом, изнчально нам нужно РАБОТАЮЩЕЕ ядро Linux.
Если вы используете Docker под Linux - проблем с этим нет. Запуск контейнера почти мгновенный.
Если вы используете Docker под Windows или MacOSX, то нужно сначала загрузить сам Linux для того, чтобы уже там загружать контейнеры.
В реальных системах боевых - Docker запускают ТОЛЬКО на Linux серверах. Но для отладки вы можете делать это где угодно. Только смиритесь с тем, что если это будет не под Linux, то запуск будет долгим.

Под Linux запуск приложения в Docker - это всего лишь контейнер, то есть всего лишь изоляция вызовов API операционной системы.

Под не-Linux запуск приложения в Docker требует изначально запуска самого Linux в виртуальной машине.

Прочитав об улучшениях производительности при запуске Docker на wsl2, я ждал официального выпуска Windows 10, поддерживающего wsl2. Я обновил Windows и Docker и включил флаг Docker для использования wsl2 и надеялся на некоторый прирост производительности моей базы данных Oracle, работающей в контейнере Docker, но, к сожалению, это изменение резко замедлило работу контейнера и моего ноутбука. Производительность контейнера примерно в 10 раз ниже, и мой ноутбук в значительной степени зависает при запуске контейнера. Кажется, что потребление памяти полностью израсходовало бы мои 8 ГБ, и началась интенсивная подкачка памяти. Могу ли я что-нибудь сделать, чтобы улучшить производительность Docker на wsl2 или, по крайней мере, лучше понять, что не так в моей настройке?

  • Процессор Intel (R) Core (TM) i7-2620M CPU @ 2,70 ГГц, 2 ядра (а)
  • Установленная физическая память (RAM) 8,00 ГБ
  • Microsoft Windows 10 Pro, версия 10.0.19041, сборка 19041
  • Докер версия 19.03.8, сборка afacb8b

Это происходит от "vmmem", который потребляет столько ресурсов, сколько может. Чтобы решить эту проблему, просто перейдите в свой пользовательский файл для меня в

В этом каталоге создайте файл с именем « .wslconfig », в котором вы настроите, сколько ресурсов может потреблять WSL2:

Теперь закройте докер и дождитесь закрытия vmmem в диспетчере задач.

Затем вы можете перезапустить докер, и обычно "vmmem" не превысит установленный вами предел (здесь 900 МБ). Если не работает, перезагрузите компьютер.

Надеюсь, это вам помогло.

Вероятно, у вас есть код на машине с Windows, как в

Но вы используете докер на WSL 2, который затем находится в другой файловой системе. Итак, если вы выполняете сборку докера, вы получаете весь код / ​​контекст, скопированный из файловой системы Windows в файловую систему Linux, а затем оттуда в контейнер докера. Это занимает большую часть времени и происходит невероятно медленно.

Попробуйте вложить свой проект в

Это должно значительно повысить производительность.

Контейнер wsl имеет надлежащую файловую систему, изолированную от файловой системы Windows. Основная идея - скопировать исходный код из файловой системы Windows в файловую систему wsl.

Из окна вы можете получить доступ к контейнеру wsl и скопировать свой проект в контейнер стены:

С помощью проводника перейдите к \\wsl$

Перестройте контейнер из этого места, это поможет!

Если данные для фактического контейнера докеров хранятся в файловой системе Windows (например, NTFS), а не в собственной файловой системе Linux (независимо от содержимого контейнера докеров, которое, вероятно, уже основано на Linux), то я думаю, что вы вы увидите низкую производительность, потому что вы запускаете WSL и используете контейнер докеров из смонтированной файловой системы WINDOWS (например, / c / mnt / . ).

Если вы скопируете свой док-контейнер в что-то вроде / usr / local или / home // docker на WSL, вы можете увидеть 10-кратное увеличение производительности. Попробовать и посмотреть, работает ли?

Если вы используете VS Code, есть команда «Удаленные контейнеры: клонировать репозиторий в том контейнера . », которая гарантирует, что у вас есть доступ к файлам на полной скорости.

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

Процесс сборки Docker и получаемые образы Docker можно оптимизировать несколькими способами. В этой статье объясняется, как происходит процесс сборки Docker и как оптимально создавать образы для контейнеров Windows.

Слои образов в сборке Docker

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

Вам может показаться, что файл Dockerfile создаст образ с двумя слоями: один для образа ОС контейнера, а второй — для служб IIS и веб-сайта. Однако фактический образ состоит из нескольких слоев, и каждый из них зависит от предыдущего.

Чтобы лучше это понять, давайте применим команду docker history к образу, созданному с помощью нашего примера файла Dockerfile.

Выходные данные свидетельствуют о том, что в этом образе есть четыре слоя: базовый и три дополнительных, сопоставленных с каждой инструкцией в Dockerfile. Нижний слой (в этом примере — 6801d964fda5 ) представляет базовый образ ОС. Одним слоем выше находится установка служб IIS. Следующий слой включает новый веб-сайт и т. д.

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

Оптимизация размера образа

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

Группирование связанных действий

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

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

В следующем примере несгруппированный файл Dockerfile скачивает Python для Windows, устанавливает его и удаляет скачанный файл установки после завершения установки. В этом файле Dockerfile для каждого действия предусмотрена отдельная инструкция RUN .

Полученный образ имеет три дополнительных слоя — по одному для каждой инструкции RUN .

Второй пример — это фал Dockerfile, выполняющий точно такую же операцию. Однако все связанные действия сгруппированы в одной инструкции RUN . Каждый шаг в инструкции RUN начинается с новой строки в файле Dockerfile, при этом для переноса строки используется символ "\".

Полученный образ имеет один дополнительный слой для инструкции RUN .

Удаление лишних файлов

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

В следующем примере файла Dockerfile пакет Python загружается, выполняется, а затем удаляется. Все это выполняется в рамках одной операции RUN и создает всего один слой образа.

Оптимизация скорости сборки

Несколько строк

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

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

Итоговый образ имеет два слоя — один для базового образа ОС, а второй для всех операций из одной инструкции RUN .

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

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

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

Порядок инструкций

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

Следующие примеры демонстрируют, как порядок инструкций в файле Dockerfile влияет на эффективность кэширования. В этом простом файле Dockerfile имеется четыре нумерованных папки.

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

Следующий файл Dockerfile теперь немного изменился (в качестве третьей инструкции RUN используется новый файл). При запуске сборки Docker для этого файла Dockerfile три первых инструкции, которые идентичны инструкциям з прошлого примера, используют кэшированные слои образа. Однако поскольку измененная инструкция RUN не кэшируется, для нее и всех последующих инструкций создается новый слой.

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

Косметическая оптимизация

Регистр инструкций

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

Ниже приведен файл Dockerfile с инструкциями в нижнем регистре:

Далее приведен тот же Dockerfile, но с инструкциями в верхнем регистре:

Перенос строк

Длинные и сложные операции можно разделить на несколько строк с помощью символа обратной косой черты \ . Следующий файл Dockerfile устанавливает распространяемый пакет Visual Studio, удаляет файлы установщика и затем создает файл конфигурации. Все эти три операции указаны на одной строке.

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

Читайте также: