Alpine docker что это

Alpine собирает Docker билды под Python в 50 раз медленней, а образы в 2 раза тяжелей

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

Alpine Linux — часто рекомендованный как базовый образ для Docker`а. Вам говорят, что использование Alpine сделает ваши билды меньше, а процесс сборки быстрей.

Но если вы используете Alpine Linux для Python приложений, то он:

Почему люди рекомендуют Alpine?

Давайте предположим, что нам необходим gcc как часть нашего образа и мы хотим сравнить Alpine Linux vs Ubuntu 18.04, по скорости сборки и конечному размеру образа.

Для начала, скачаем два образа и сравним их размер:

Как вы видите, базовый образ для Alpine намного меньше. Давайте теперь попробуем установить gcc и начнем с Ubuntu:

Написание идеальных Dockerfile выходит за рамки этой статьи

Замерим скорость сборки:

Повторяем все то же самое для Alpine (Dockerfile):

Собираем, смотрим на время и размер сборки:

Как и обещано, образы на базе Alpine собираются быстрей и сами по себе меньше: 15 секунда вместо 30 и размер образа 105MB против 150MB. Это довольно хорошо!

Но если мы переключимся на сборку Python приложения, то все не так радужно.

Python образ

Python приложения часто используют pandas и matplotlib. Поэтому, один из вариантов взять официальный образ на базе Debian, используя такой Dockerfile:

Получаем образ размером в 363MB.
Получится у нас лучше с Alpine? Давайте попробуем:

Alpine не поддерживает wheels

Если вы посмотрите на билд, который базируется на Debian, то вы увидите, что он скачивает matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.whl.

Это бинарник для wheel. Alpine же скачивает исходники `matplotlib-3.1.2.tar.gz`, так как он не поддерживает стандартный wheels.

Почему? Большинство Linux дистрибутивов используют GNU версию (glibc) стандартной библиотеки C, который по факту необходим каждой программе написанной на C, включая Python. Но Alpine использует `musl`, а так как те бинарники предназначены для `glibc`, они попросту не вариант.

Поэтому, если вы используете Alpine, вам необходимо компилировать весь код, написанный на C, в каждом пакете Python.

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

И время билда занимает…

… 25 минут 57 секунд! А размер образа 851MB.

Образы на базе Alpine собираются намного дольше, сами по себе они большего размера и вам еще нужно искать все зависимости. Можно конечно уменьшить размер сборки используя multi-stage builds но это означает, что нужно проделать еще больше работы.

Alpine может быть причиной неожиданных багов в рантайме

Источник

Эволюция Docker. Часть 1

Вступление

20 марта 2013 года на конференции PyCon 2013, Соломон Хайкс (CEO компании dotCloud) выступил с пятиминутной презентацией The future of Linux Containers. В ней широкой общественности впервые была представлена внутренняя разработка компании dotCloud под названием Docker, а спустя несколько дней ее исходный код был выложен в открытый доступ. Хотя технологии LXC и Aufs, на которых была основана первая версия Docker существовали и активно использовались уже порядка пяти лет, но именно появление Docker послужило началом стремительного роста и эволюции систем контейнеризации, что кардинально преобразило многие процессы разработки и деплоймента программного обеспечения.

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

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

Исходный код

Для запуска я буду использовать Windows 10 c Vagrant и Ubuntu 20.04. Сразу хочу предупредить, что WSL2 не подойдет, так как используемое ядро не поддерживает aufs, требуемую в ранних версиях.

На момент создания репозитория (18 января 2013 года), код Docker состоял всего из 6 файлов общим объемом в 624 строки и как мы увидим далее, представлял собой лишь обертку и удобное api для утилит lxc и mount.

Итак, приступим к изучению самого кода, отправной точкой будет служить файл docker.go, в котором объявлены функции New и NewFromDirectory:

New является фасадом, который просто вызывает NewFromDirectory с дефолтным путем /var/lib/docker. Функция NewFromDirectory производит инициализацию структуры Docker, создает директорию для контейнеров (если она не существует) и возвращает структуру Docker (перед чем вызывается метод restore):

В методе restore происходит попытка загрузки и инициализации существующих контейнеров из папки containers вызовом функции loadContainer. При первом запуске данная папка будет пуста, так что ничего не произойдет. Мы рассмотрим данный функционал немного позже, когда перейдем к файлу container.go.

Следующие интересующие нас методы из файла docker.go это Create и Destroy:

Аналогично ему метод Destroy останавливает контейнер, удаляет корневую директорию контейнера, а затем удаляет его из списка containers.

Остальное содержимое файла docker.go составляют лишь несколько хелпер методов:

Следующей точкой будет файл container.go и метод createContainer, который собственно и занимается реальным созданием контейнеров:

В начале метода происходит инициализация структуры Container, создание директории и сохранение в ней экспортированного файла конфигурации контейнера, а также конфигурационного файла для утилиты lxc-start. В функции newFilesystem из файла filesystem.go просто инициализируется и возвращается структура Filesystem. Чуть позже мы рассмотрим filesystem.go подробнее.

Функция newState находится в state.go и инициализирует структуру содержащую pid, exitcode, а так же мьютекс для коммуникации.

Функция newWriteBroadcaster() из utils.go возвращают структуру writeBroadcaster (broadcast pattern) использующуюся для работы с потоками stdout и stderr.

Метод save экспортирует структуру Container в json формат и сохраняет в файл, по которому в дальнейшем происходит загрузка контейнеров в методе restore и loadContainer, о чем было указано ранее.

Как видим, в нем используется переменная LxcTemplateCompiled. Чтобы разобраться с ней, нам нужно взглянуть на файл lxc_template.go, в котором находится шаблон для конфигурационного файла lxc:

Он компилируется на этапе инициализации модуля, а в методе generateLXCConfig после подстановки значений сохраняется на диск в файле config.lxc.

Подведем итог: в методе createContainer выполняется инициализация структуры Container и вспомогательных структур Filesystem, State и writeBroadcaster. Далее в папке containers создается директория с именем контейнера, в которую сохраняется структура Container после экспорта в json. На последнем этапе на основе параметров контейнера генерируется и сохраняется конфигурационный файл для lxc-start.

Далее перейдем к запуску контейнера, который происходит в методе Start из файла container.go

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

Как видим, это всего лишь обертка над утилитой mount. Метод createMountPoints создает две директории:

Метод Mount формирует строку параметров и вызывает утилиту mount с типом aufs. Метод Umount соответственно размонтирует файловую систему.

Все слои образа (Layers) представляют собой пути к директориям, которые монтируются с правами read only в объединенную файловую систему в точке RootFS, а все изменения происходят в директории RWPath и сохраняются даже после размонтирования. Файловая система Aufs имеет механизм copy-on-write, это означает, что когда происходит попытка изменения файла находящегося в read-only слое, он будет автоматически скопирован в RWPath.

Теперь вернемся к функции Start из container.go. После монтирования файловой системы она подготавливает параметры и запускает утилиту lxc-start, перед этим перенаправляя потоки stdout и stderr. В качестве параметров ей передается имя запускаемого контейнера и путь к конфигурационному файлу config.lxc, который был сгенерирован ранее на этапе создания контейнера. После запуска процесса его pid сохраняется в структуре State:

Далее запускается горутина monitor, которая ждет завершения процесса, закрывает потоки stdout и stderr и сохраняет exitcode контейнера через метод setStopped:

Осталось разобрать метод Stop, который предназначен для остановки контейнеров:

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

Запуск контейнеров

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

Перед продолжением нужно установить golang и lxc, а так же скачать rootfs для образа (я буду использовать alpine linux).

Проверим что rootfs на месте:

Теперь нужно сделать небольшие изменения, так как некоторые опции lxc поменялись в новой версии, а так же поправим метод restore в docker.go. Ниже приведен патч:

Далее выполним go mod init docker и остается лишь написать простую cli программу для управления контейнерами. Создадим папку cli c файлом docker.go и подобным контентом:

Теперь скомпилируем программу и запустим контейнер:

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

Запустим еще один контейнер и создадим в нем файл:

Запустим /bin/sh в созданном контейнере:

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

Теперь попробуем удалить контейнер:

Как видим, все файлы контейнера test2 были успешно удалены.

Заключение

Вот приблизительно так выглядел весь функционал Docker на момент его зарождения.

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

Источник

Изучаем Docker, часть 3: файлы Dockerfile

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

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

Образы Docker

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

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

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

Каждый слой, на самом деле, это всего лишь файл, который описывает изменение состояния образа в сравнении с тем состоянием, в котором он пребывал после добавления предыдущего слоя. В Unix, кстати, практически всё что угодно — это файл.

Базовый образ — это то, что является исходным слоем (или слоями) создаваемого образа. Базовый образ ещё называют родительским образом.

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

Базовый образ — это то, с чего начинается образ Docker

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

Файлы Dockerfile

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

Здесь мы исходим из предположения, в соответствии с которым используется образ Docker, основанный на Unix-подобной ОС. Конечно, тут можно воспользоваться и образом, основанным на Windows, но использование Windows — это менее распространённая практика, работать с такими образами сложнее. В результате, если у вас есть такая возможность, пользуйтесь Unix.

Для начала приведём список инструкций Dockerfile с краткими комментариями.

Дюжина инструкций Dockerfile

Инструкции и примеры их использования

▍Простой Dockerfile

Dockerfile может быть чрезвычайно простым и коротким. Например — таким:

▍Инструкция FROM

Ключевое слово FROM сообщает Docker о том, чтобы при сборке образа использовался бы базовый образ, который соответствует предоставленному имени и тегу. Базовый образ, кроме того, ещё называют родительским образом.

В этом примере базовый образ хранится в репозитории ubuntu. Ubuntu — это название официального репозитория Docker, предоставляющего базовую версию популярной ОС семейства Linux, которая называется Ubuntu.

При создании контейнера слой, в который можно вносить изменения, добавляется поверх всех остальных слоёв. Данные, находящиеся в остальных слоях, можно только читать.

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

Структура контейнера (взято из документации)

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

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

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

▍Более сложный Dockerfile

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

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

Базой этого образа является официальный образ Python с тегом 3.7.2-alpine3.8. Проанализировав этот код можно увидеть, что данный базовый образ включает в себя Linux, Python, и, по большому счёту, этим его состав и ограничивается. Образы ОС Alpine весьма популярны в мире Docker. Дело в том, что они отличаются маленькими размерами, высокой скоростью работы и безопасностью. Однако образы Alpine не отличаются широкими возможностями, характерными для обычных операционных систем. Поэтому для того, чтобы собрать на основе такого образа что-то полезное, создателю образа нужно установить в него необходимые ему пакеты.

▍Инструкция LABEL

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

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

▍Инструкция ENV

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

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

▍Инструкция RUN

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

▍Инструкция COPY

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

▍Инструкция ADD

Кроме того, документация предлагает везде, где это возможно, вместо инструкции ADD использовать инструкцию COPY для того, чтобы сделать файлы Dockerfile понятнее. Полагаю, команде разработчиков Docker стоило бы объединить ADD и COPY в одну инструкцию для того, чтобы тем, кто создаёт образы, не приходилось бы помнить слишком много инструкций.

▍Инструкция CMD

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

Инструкция CMD предоставляет Docker команду, которую нужно выполнить при запуске контейнера. Результаты выполнения этой команды не добавляются в образ во время его сборки. В нашем примере с помощью этой команды запускается скрипт my_script.py во время выполнения контейнера.

Вот ещё кое-что, что нужно знать об инструкции CMD :

▍Ещё более сложный Dockerfile

Рассмотрим ещё один файл Dockerfile, в котором будут использованы некоторые новые команды.

Кроме того, пакеты Python в образ можно устанавливать с помощью pip, wheel и conda. Если речь идёт не о Python, а о других языках программирования, то при подготовке соответствующих образов могут использоваться и другие менеджеры пакетов.

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

▍Инструкция WORKDIR

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

▍Инструкция ARG

▍Инструкция ENTRYPOINT

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

Пункт перехода в какое-то место

▍Инструкция EXPOSE

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

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

▍Инструкция VOLUME

Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

Инструкция VOLUME позволяет указать место, которое контейнер будет использовать для постоянного хранения файлов и для работы с такими файлами. Об этом мы ещё поговорим.

Итоги

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

Уважаемые читатели! Если вы пользуетесь Docker на практике, просим рассказать о том, как вы пишете Docker-файлы.

Источник

Так ли мал Alpine 3.8 Docker для Python 3 runtime

Совсем недавно произошёл релиз минималистичного Alpine Linux 3.8. Очень часто данный linux образ используют в докере, собирая очень компактные окружения для runtime.

Сегодняшняя статья будет рассмотрена в срезе использования runtime системы в докере для Python 3.6.X версий, с различным составом пакетов pip. А так же мы соберём самый новый Python 3.7 в Alpine.

Итак, результирующие файлы для Debian и Fedora будут выглядеть у нас так:
Debian

А вот с Alpine 3.8 пока заминка. Официально на момент написания статьи он ещё на вышел, а посмотреть, то хочется:-). Поэтому нам понадобиться их образ системы:
dl-cdn.alpinelinux.org/alpine/v3.8/releases/x86_64
И мы соберём свой Alpine from Sratch:
github.com/gliderlabs/docker-alpine/tree/master/versions/library-3.8/x86_64

Создаём свой докер файл:

Затем копипастим и добавляем в этот файл борку Python 3.6 со страницы github.com/docker-library/python/blob/master/3.6/alpine3.7/Dockerfile
не забыв удалить или закомментировать строку FROM alpine:3.7

И пробуем создать образ с Alpine 3.8 и Python на борту:

Шаг 2. Установка cython и tornado

Начинаем добавлять пакеты pip. Первым установим cython и tornado. Для Debian и Fedora пакеты ставятся без ошибок, а вот Alpine падает с ошибкой:

Придется гуглить и потом уже добавлять библиотеки сборки в Alpine, чтобы pip успешно собрал их из исходного текста. Затем запускать сборку докера снова, затем опять искать зависимости, читать форумы stackoverflow и issues в github и ждать и ждать и ждать.
Alpine docker что это. Смотреть фото Alpine docker что это. Смотреть картинку Alpine docker что это. Картинка про Alpine docker что это. Фото Alpine docker что это

Поскольку в следующих шагах мы начнём добавлять математические и графические библиотеки в наш образ runtime Python, и чтобы слишком не увеличивать текст данной статьи, я приведу финальные зависимости для Alpine linux:

Шаг 3. Добавляем математику numpy scipy

Шаг 4. Добавляем графический стек websocket-client pytest pandas bokeh pillow

В качестве бонуса, попробуем в Alpine 3.8 скомпилировать ещё не вышедший для докера Python 3.7.
Новая версия Python 3.7 представлена 27 июня 2018 года

Размер Alpine 3.8 с Python 3.7 с текущим списком пакетов pip 656 MB

Итоги

При большом количестве графических пакетов, оптимальнее выбрать дистрибутив Fedora, чем заниматься компиляцией пакетов в Alpine (компиляция может длиться 1-2 часа), и в результате получить экономию в один или два десятка процентов места на жёстком диске.

UPDATE1: Тестирование проводилось на Fedora Atomic Host: release 28 (Twenty Eight), Version: 2018.5

Источник

Docker

Contents

Installation

The Docker package is in the ‘Community’ repository. See Alpine_Linux_package_management how to add a repository.

Connecting to the Docker daemon through its socket requires you to add yourself to the `docker` group.

To start the Docker daemon at boot, see Alpine_Linux_Init_System.

For more information, have a look at the corresponding Github issue.

This weakening of security is not necessary to do with Alpine 3.4.x and Docker 1.12 as of August 2016.

Docker Compose

‘docker-compose’ is in the ‘Community’ repository starting with Alpine Linux 3.10.

For older releases:

To install docker-compose, first install pip:

Isolate containers with a user namespace

add to /etc/docker/daemon.json

You may also consider these options : ‘

You’ll find all possible configurations here[1].

Example: How to install docker from Arch

«WARNING: No limit support»

Alpine 3.8

It may not have been the case before, but with Alpine 3.8, you must config cgroups properly

Warning: This seems not to work with Alpine 3.9 and Docker 18.06. Follow the instructions for grub or extlinux below instead.

Extlinux

With Extlinux, you add the cgroup condition, but inside of /etc/update-extlinux.conf

then update the config and reboot

How to use docker

The best documentation on using Docker and creating containers is at the main docker site. Adding anything to it here would be redundant.

If you create an account at docker.com, you can browse through user images and learn from the syntax in contributed dockerfiles.

Official Docker image files are denoted on the website by a blue ribbon.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *