Оптимизация образа Docker и лучшие практики

задняя часть Docker

Резюме:В 41-м выпуске Yunqi TechDay Мисака, старший инженер по исследованиям и разработкам Alibaba Cloud, рассказала об оптимизации образа Docker и передовом опыте. Начиная с принципа хранения образов Docker, для хранения образов и передачи по сети, в нем рассказывается, как оптимизировать эти ключевые моменты во время построения. И представьте новейшую функцию многоэтапной сборки Docker, чтобы решить проблему промежуточных продуктов, зависящих от сборки.

Вот основные моменты:

концепция зеркала


Что такое зеркалирование? С более конкретной точки зрения образ представляет собой многоуровневый файл хранилища.По сравнению с обычными образами системы ISO, многоуровневое хранилище дает два преимущества.Во-первых, образы многоуровневого хранилища легче расширять.Например, мы можем создать наш Nginx образ на основе образа Ubuntu, так что нам нужно только выполнить некоторые работы по установке и настройке Nginx на основе образа Ubuntu.Даже если образ Nginx завершен, нам не нужно начинать с нуля.зеркало. Еще один момент, мы можем оптимизировать пространство для хранения изображений, если у нас есть два изображения, изображение Tag1.0 и изображение Tag2.0, если мы передаем эти два изображения традиционным способом, каждое изображение составляет около 130 МБ, но если мы используем To хранить два изображения в многоуровневом режиме, мы можем поделиться ими через следующие два фиолетовых, что может сэкономить много места.Для двух изображений вместе требуется только более 140 мегабайт места для сохранения. Это экономит место на диске и снижает нагрузку на сеть. Например, мы загрузили изображение ниже. Когда мы хотим загрузить изображение выше, нам нужно загрузить только часть 10M.

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

Основные операции с изображением и метод хранения


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

Во-первых, нам нужно войти в систему. Мы будем использовать первую команду для входа в систему. Затем, когда мы подготавливаем изображение локально и хотим его загрузить, мы должны сначала пометить изображение и изменить его координаты на наши текущие. Нам нужно загрузить координаты изображения, а затем выполнить некоторые действия push и pull.Наконец, есть две дополнительные команды для Docker для доставки образа.Если мы находимся в специальной среде и нет возможности подключиться к сети, мы можем передать изображение в изображение.Упаковано в обычный файл для передачи. Например, когда мы сотрудничаем со службой безопасности, у них нет возможности загрузить образ через наш Реестр, мы можем сделать его в общий файл, а затем доставить в виде U-диска.

Сведения о хранилище изображений


Образы Docker имеют совместную файловую систему, и каждый образ фактически хранится в слоях.Например, мы добавили три новых файла в первый слой, а затем в этот слой добавили еще один слой и добавили файл. чтобы внести некоторые изменения. Мы внесли изменения в файл 3 и переместили его наверх, а затем удалили файл 4. Это введет механизм копирования при записи в объединенной файловой системе. Когда мы хотим изменить файл Когда используется файл , нижний слой зависимости изображения доступен только для чтения, и мы не можем изменить его напрямую. Например, если мы хотим изменить File3, мы не можем изменить этот файл напрямую. Нам нужно скопировать файл на текущий слой при изменении, например, слой Say L3, а затем перейдите и измените его.

Когда образ завершен, когда мы хотим знать, какой контент содержится в образе, у нас фактически есть концепция представления. Когда мы смотрим на образ с точки зрения объединенной файловой системы, мы на самом деле не видим L1 и L2. L3, мы наконец-то увидим результат, File1, File2, File3, File4 не будет видно, а потом после того, как мы поймем принцип, мы сможем понять, что за контейнер работает. Работа контейнера аналогична описанной выше.Нижняя часть рисунка также представляет собой трехслойное изображение L1, L2 и L3.Когда контейнер запущен, демон Docker динамически генерирует доступный для записи слой как работающий уровень контейнера. , а затем, когда некоторые файлы в контейнере необходимо изменить, например File2, механизм копирования при записи также копирует файлы, а затем вносит некоторые изменения. То же самое верно при добавлении файлов, и тогда контейнер также будет иметь представление, когда он работает.Когда мы останавливаем контейнер, слой представления исчезает, он будет уничтожен, но слой чтения-записи слоя контейнера останется, поэтому, когда мы остановим контейнер и запустим его снова, мы все равно увидим, что у нас было в контейнере раньше, какие-то операции внутри.

Общие драйвера хранения в основном включают AUFS, OverlayFS и Device Mapper. Первые два драйвера основаны на файлы. Ее принцип заключается в том, чтобы скопировать весь файл для модификации , когда файл должны быть изменен. Устройство Mapper более низкий уровень. Это основанный на блочных устройствах. Его преимущество заключается в том, что , когда я хочу , чтобы изменить файл, я не буду копировать весь файл. Я скопирует некоторые блоки хранения измененных с помощью файла , чтобы сделать некоторые изменения. когда у меня есть некоторые большие файлы если вы хотите Modify, Device Mapper намного лучше, чем AUFS и OverlayFS. Поэтому AUFS и OverlayFS больше подходит для традиционных веб-приложений. Это не имеет много операций с файлами, но он может иметь некоторые требования к скорости запуска наших приложений. Например, я могу опубликовать часто, и я надеюсь быть в состоянии начать быстрее, но я не забочусь об эффективности модификации файла. мы можем использовать драйвера , основанные на файлы. Когда мы несколько вычислительно интенсивных приложений, мы можем выбрать устройство Mapper. Хотя запуск медленно, его операционная эффективность относительно лучше..

Автоматическая сборка изображения


Когда мы создаем образ, Docker фактически предоставляет стандартизированный набор инструкций по сборке. Когда мы используем эти инструкции по сборке для написания сценариев, подобных тем, которые мы называем DockerFile, Docker может автоматически анализировать DockerFile и создавать его как зеркало, так что вы можете просто думать о это как стандартизированный сценарий. Что делает DockerFile? Прежде всего, первая строка инструкции FROM указывает, какой образ использовать в качестве базового образа для сборки.Мы использовали официальный образ openJDK, и на основе среды JAVA мы собираемся запустить приложение JAVA на образе, а затем следующие два LABLE предназначены для образа, отмечены версия образа и дата сборки, а затем следующие шесть RUN должны выполнить установку maven, maven - это инструмент управления жизненным циклом для JAVA, а затем добавить некоторый источник код из внешней среды в образ.Внутри две команды RUN сделали упаковку и, наконец, написали команду запуска.


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

Мы можем уменьшить количество слоев образа.У Docker есть определенные требования к количеству слоев образа Docker.За исключением самого верхнего слоя чтения-записи, когда контейнер запущен, мы можем иметь максимум 127 слоев в одном изображение. Если он превышает количество слоев, может появиться проблема, поэтому вторая строка команды LABLE может синтезировать его в один слой и уменьшить количество слоев. Следующие шесть команд RUN выполняют работу по установке maven, мы также можем сделать его в один слой, соедините эти команды вместе, а затем мы также можем синтезировать его в один слой, чтобы мы могли уменьшить количество зеркальных слоев с 14 слоев до 7 слоев за один раз, что сокращается вдвое.

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


Далее продолжаем оптимизировать изображение, что мы можем сделать? При установке maven build tool добавили еще одну строчку, удалили установочный пакет и директорию расширения, подчистили промежуточные продукты сборки, надо обратить внимание на выполнение каждой инструкции сборки, пробуйте подчищать фигня, мы при установке какого-то софта через apt-get мы тоже можем сделать такую ​​работу по очистке, то есть мы можем удалить софт после его упаковки, чтобы максимально уменьшить место.Добавив строчку команд , можно поставить Размер образа уменьшился со 137М до 119М.

Установка программного обеспечения или команд через apt-get в основном написана всеми, кто пишет DockerFile, поэтому официалы добавили Hack в образы склада Debian и Ubuntu по умолчанию, это поможет вам автоматически установить исходный код при установке и удалении.


Мы можем использовать встроенный кеш.Docker строит кеш по умолчанию.Есть три ключевых момента,чтобы кеш заработал.Родительский слой образа не изменился,инструкции по сборке остались без изменений,и контрольная сумма добавленного файла непротиворечива. Пока инструкция сборки удовлетворяет этим трем условиям, этот уровень построения образа не будет выполняться снова. Он будет напрямую использовать результаты предыдущей сборки. В соответствии с функцией кэша сборки мы можем добавить строку RUN. Вот пример приложения JAVA. Как правило, файлы pom приложений JAVA описывают некоторые зависимости JAVA. В нашем обычном процессе разработки частота изменений этих зависимостей относительно низка, тогда мы можем добавить POM и подготовить все зависимости POM, а затем перейдите к исходному коду, а затем выполните сборку.Пока мы не отключаем кеш, нам не нужно повторно загружать установочный пакет каждый раз, когда мы собираем, что может сэкономить много времени и сетевого трафика.


Теперь служба образов контейнеров Alibaba Cloud фактически обеспечила функцию построения. Когда мы подсчитаем случаи сбоев пользователей, мы обнаружим, что сбои, вызванные сетевыми причинами, составляют 90%. Например, если пользователи разрабатывают NPM через узел, они часто устанавливают некоторые программные пакеты. , застрял в середине. Поэтому мы рекомендуем добавить источник программного обеспечения.Мы добавляем к нему адрес maven Alibaba Cloud, мы добавляем элементы конфигурации к адресу программного обеспечения Alibaba Cloud и добавляем источник maven Alibaba Cloud в качестве цели загрузки пакета программного обеспечения.Время непосредственно уменьшается на 40%, что также полезно для успеха сборки образа.

многоступенчатая сборка


Конечный продукт, который должен получить DockerFile, на самом деле является приложением JAVA. Мы не заботимся о сборке, компиляции, упаковке или установке этих вещей. На самом деле нам нужен конечный продукт. Таким образом, мы можем использовать пошаговый подход к построению образа.Во-первых, мы превращаем все проблемы, с которыми мы сталкивались ранее, в базовый образ.На самом деле образ FROM выше был изменен, и адрес источника программного обеспечения был изменен. на изображении С Maven кеш готов. Мы будем использовать кэш, затем добавим исходный код, предыдущую конструкцию сделаем зеркалом, пусть зеркало завершит построение, а затем завершим копирование JAVA-пакета и начнем работу, но два DockerFile на самом деле два Это зеркальное изображение, поэтому нам нужен сценарий, чтобы помочь ему. Сценарий оболочки в первой строке является первой инструкцией по сборке. Мы указываем DockerFile Bulid, чтобы начать сборку, а затем генерируем образ APP Bulid. Следующие две строчки скрипта — Генерируется образ, копируются продукты сборки внутри, а затем мы его строим, и, наконец, строим нужное нам JAVA-приложение, чтобы наш DockerFile был чище, чем раньше, и шаги были очень простыми.


Докер официально поддерживает многостадийную сборку после 17.05.Мы убрали следующий скрипт.Вспомогательный скрипт нам не нужен.Нам нужно только отметить место,где базовый образ объявляется позже.Как называется наша сборка первого этапа Вы можете использовать продукт первой фазы сборки на второй фазе сборки. Например, мы собираем JAVA-приложение на первом этапе, копируем стоечный пакет JAVA под таргетом в пакете Maven в новый образ, а затем, после выполнения всех оптимизаций, эффект такой, как показано на рисунке. в первый раз оптимизируем Первые 102 секунды были выполнены за 55 секунд после оптимизации сборки Docker, и основная оптимизация была в сети. Когда мы модифицировали файл JAVA и пересобрали его, вторая сборка заняла 86 секунд, потому что установка Maven была закэширована, а мы использовали кеш сборки, поэтому она потеряла более 20 секунд, а после оптимизации заняла всего 8 секунд, т.к. загрузки пакетов перед всем исходным кодом все кэшируются, мы напрямую извлекаем новый образ, а затем зависимости остаются неизменными, и сборка выполняется напрямую, поэтому 8 секунд — это в основном полное время сборки.

Давайте посмотрим на оптимизацию дискового пространства.Для первой сборки мы набрали образ до 137M перед оптимизацией, но после всей нашей оптимизации это было только 81M.Базовый образ здесь был изменен с JDK на JRE.Почему ? Потому что перед тем, как засунуть все процессы в один образ, нам нужно сделать сборку, и при сборке нужно зайти в RUN Maven. сборка передается образу Maven, а реальная работа передается новому образу. Нет необходимости использовать JDK. Мы напрямую используем JRE. После оптимизации образ уменьшается почти на 50%. Когда мы изменили исходный код и пересобрали, из-за общего зеркального образа вторая сборка фактически добавила два-три слоя перед оптимизацией, всего 9M, но вторая сборка после оптимизации увеличилась только на 1,93 КБ, поэтому наша оптимизация для DockerFile было сделано.

Каковы важные моменты оптимизации изображения? Подробности следующие:

1. Уменьшите количество слоев зеркальных изображений и попробуйте объединить некоторые унифицированные команды с функциями;

2. Обратите внимание на очистку промежуточных продуктов построения образа, например, некоторые инсталляционные пакеты удаляются после их установки;

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

4. Пробуем использовать кеш сборки, стараемся какие-то неизменяемые вещи или вещи, которые меняются меньше, впереди, потому что неизмененные вещи можно кешировать;

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

Служба образов контейнеров

Наконец, мы представим службу образов облачных контейнеров Alibaba. Этот сервис был в публичной бета-версии в течение года. Теперь наша публичная бета-версия сервиса бесплатна. Сейчас наш сервис развернут в 12 регионах по всему миру. В каждом регионе фактически есть интранет-сервисы и сетевые сервисы VPC. того же региона, то его обслуживание очень быстрое. Затем также были запущены функции управления командой и учетной записи организации.Покупка и создание зеркала и уведомление о сообщении зеркала на самом деле являются некоторыми возможностями DevOps.Для некоторой оптимизации зеркала мы предоставляем некоторые функции просмотра информации зеркального слоя.Мы также предоставим анализ в будущем и запустить зеркальную защиту.Сканировать,зеркальную синхронизацию.