Docker слои что такое

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

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

В CenturyLink Lab мы много работали над сборкой различных docker-образов в последнее время. Когда мы начали экспериментировать с их созданием, мы обнаружили, что наши сборки очень быстро раздуваются в объеме (обычным делом было собрать образ, который весит 1 Гб или больше). Размер, конечно, не столь важен, если мы говорим про образы по два гига, лежащие на локальной машине. Но это становится проблемой, когда вы начинаете постоянно скачивать/отправлять эти образы через интернет.

Я решил, что стоит копнуть поглубже и разобраться с тем, как работает процесс создания docker-образов, чтобы понять, что можно сделать для уменьшения размера наших сборок.

Прежде, чем мы перейдем к теме уменьшения ваших образов, нужно поговорить о слоях. Концепция слоев затрагивает различные низкоуровневые технические детали о вещах вроде корневой файловой системы (rootfs), механизма копирования при записи (copy-on-write) и каскадно-объединенного монтирования (union mount). К счастью, эта тема достаточно хорошо раскрыта в другом месте, поэтому я не буду пересказывать ее здесь. Для наших целей важным является понимание того, что каждая инструкция в Dockerfile приводит к созданию нового слоя образа.

Давайте взглянем на пример Dockerfile, чтобы увидеть это в действии:

Соберем этот образ:

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

Так же, как мы выполним:
Мы легко можем запустить один из неименованных слоев:

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

Размер образа

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

Посмотрим на вывод команды docker history :

Здесь только две инструкции, которые делают что-то значимое для нашего образа: инструкция ADD (наследуемая из debian:wheezy ) и наша fallocate команда.

Давайте сохраним наш образ в tar-архив и посмотрим каков будет вес:

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

Добавим еще одну инструкцию в Dockerfile:

Если мы выполним docker build для обновленного Dockerfile и посмотрим на историю снова, мы увидим следующее:

Заметьте, что вызов rm добавил новый слой (в 0 байт), но все остальное осталось по-прежнему. Если мы сохраним наш обновленный образ, то должны увидеть, что размер практически не изменился (будет небольшая разница из-за метаданных добавленного слоя):

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

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

Выберите вашу основу

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

Список полезных баз может быть разным и зависит от ваших нужд, но вам точно стоит его проверить. Если вы используете Ubuntu, когда хватило бы и BusyBox, то вы напрасно тратите кучу места.

Хотелось бы, чтобы размер образов отображался в хранилище Docker. Но сейчас, к сожалению, чтобы узнать размер, образ нужно скачать.

Используйте вашу основу повторно

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

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

Группируйте ваши команды

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

Мы скачиваем tar-архив, распаковываем его, кое-что перемещаем и подчищаем за собой.

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

Запуск wget приводит к появлению слоя размером 55 Мб, а распаковка архива к слою в 99 Мб. Нам не нужны эти файлы, а значит мы просто тратим 150+ Мб впустую.

Мы можем исправить это, проведя небольшой рефакторинг нашего Dockerfile:

Вот, что получилось в результате:

Заметьте, что в итоге мы получили такой же образ, при этом избавившись от нескольких лишних слоев и сохранив 150 Мб свободного пространства.

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

«Схлопывайте» ваши образы

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

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

Давайте вернемся к нашему образу sample (тому, который с fallocate и rm ) и запустим его:

Обратите внимание, что история для нашего нового образа sample:flat показывает только один слой весом 85 Мб, — слой, содержащий гигабайтный файл пропал.

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

Источник

Образы и контейнеры Docker в картинках

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Перевод поста Visualizing Docker Containers and Images, от новичка к новичкам, автор на простых примерах объясняет базовые сущности и процессы в использовании docker.

Если вы не знаете, что такое Docker или не понимаете, как он соотносится с виртуальными машинами или с инструментами configuration management, то этот пост может показаться немного сложным.

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

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

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

Хорошим примером является Git. Я не мог понять Git, пока не понял его базовую модель, включая trees, blobs, commits, tags, tree-ish и прочее. Я думаю, что люди, не понимающие внутренности Git, не могут мастерски использовать этот инструмент.

Определение образа (Image)

Визуализация образа представлена ниже в двух видах. Образ можно определить как «сущность» или «общий вид» (union view) стека слоев только для чтения.

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Слева мы видим стек слоев для чтения. Они показаны только для понимания внутреннего устройства, они доступны вне запущенного контейнера на хост-системе. Важно то, что они доступны только для чтения (иммутабельны), а все изменения происходят в верхнем слое стека. Каждый слой может иметь одного родителя, родитель тоже имеет родителя и т.д. Слой верхнего уровня может быть использован как UnionFS (AUFS в моем случае с docker) и представлен в виде единой read-only файловой системы, в которой отражены все слои. Мы видим эту «сущность» образа на рисунке справа.

Если вы захотите посмотреть на эти слои в первозданном виде, вы можете найти их в файловой системе на хост-машине. Они не видны напрямую из запущенного контейнера. На моей хост-машине я могу найти образы в /var/lib/docker/aufs.

Определение контейнера (Container)

Контейнер можно назвать «сущностью» стека слоев с верхним слоем для записи.

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

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

Контейнер определяет лишь слой для записи наверху образа (стека слоев для чтения). Он не запущен.

Определение запущенного контейнера

Запущенный контейнер — это «общий вид» контейнера для чтения-записи и его изолированного пространства процессов. Ниже изображен контейнер в своем пространстве процессов.

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

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

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Чтобы проверить это, выполните команду на хост-машине:

Вы можете найти новый файл в слое для записи на хост-машине, даже если контейнер не запущен.

Определение слоя образа (Image layer)

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

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Метаданные — дополнительная информация о слое, которая позволяет докеру сохранять информацию во время выполнения и во время сборки. Оба вида слоев (для чтения и для записи) содержат метаданные.

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Кроме того, как мы уже упоминали раньше, каждый слой содержит указатель на родителя, используя id (на изображении родительские слои внизу). Если слой не указывает на родительский слой, значит он наверху стека.

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Расположение метаданных

На данный момент (я понимаю, что разработчики docker могут позже сменить реализацию), метаданные слоев образов (для чтения) находятся в файле с именем «json» в папке /var/lib/docker/graph/id_слоя:

где «e809f156dc985. » — урезанный id слоя.

Свяжем все вместе

Теперь, давайте посмотрим на команды, иллюстрированные понятными картинками.

docker create

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

docker start

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker start’ создает пространство процессов вокруг слоев контейнера. Может быть только одно пространство процессов на один контейнер.

docker run

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Один из первых вопросов, который задают люди (я тоже задавал): «В чем разница между ‘docker start’ и ‘docker run’?» Одна из первоначальных целей этого поста — объяснить эту тонкость.

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Как мы видим, команда ‘docker run’ находит образ, создает контейнер поверх него и запускает контейнер. Это сделано для удобства и скрывает детали двух команд.

Продолжая сравнение с освоением Git, я скажу, что ‘docker run’ очень похожа на ‘git pull’. Так же, как и ‘git pull’ (который объединяет ‘git fetch’ и ‘git merge’), команда ‘docker run’ объединяет две команды, которые могут использоваться и независимо. Это удобно, но поначалу может ввести в заблуждение.

docker ps

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker ps’ выводит список запущенных контейнеров на вашей хост-машине. Важно понимать, что в этот список входят только запущенные контейнеры, не запущенные контейнеры скрыты. Чтобы посмотреть список всех контейнеров, нужно использовать следующую команду.

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

docker images

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker images’ выводит список образов верхнего уровня (top-level images). Фактически, ничего особенного не отличает образ от слоя для чтения. Только те образы, которые имеют присоединенные контейнеры или те, что были получены с помощью pull, считаются образами верхнего уровня. Это различие нужно для удобства, так как за каждым образом верхнего уровня может быть множество слоев.

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

docker stop

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker stop’ посылает сигнал SIGTERM запущенному контейнеру, что мягко останавливает все процессы в пространстве процессов контейнера. В результате мы получаем не запущенный контейнер.

docker kill

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker kill’ посылает сигнал SIGKILL, что немедленно завершает все процессы в текущем контейнере. Это почти то же самое, что нажать Ctrl+\ в терминале.

docker pause

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

В отличие от ‘docker stop’ и ‘docker kill’, которые посылают настоящие UNIX сигналы процессам контейнера, команда ‘docker pause’ используют специальную возможность cgroups для заморозки запущенного пространства процессов. Подробности можно прочитать здесь, если вкратце, отправки сигнала Ctrl+Z (SIGTSTP) не достаточно, чтобы заморозить все процессы в пространстве контейнера.

docker rm

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker rm’ удаляет слой для записи, который определяет контейнер на хост-системе. Должна быть запущена на остановленном контейнерах. Удаляет файлы.

docker rmi

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

docker commit

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такоеили Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker commit’ берет верхний уровень контейнера, тот, что для записи и превращает его в слой для чтения. Это фактически превращает контейнер (вне зависимости от того, запущен ли он) в неизменяемый образ.

Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

docker build

До:
Dockerfile Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такоеи Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое
Со многими другими слоями.

Команда ‘docker build’ интересна тем, что запускает целый ряд команд:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

На изображении выше мы видим, как команда build использует значение инструкции FROM из файла Dockerfile как базовый образ после чего:

1) запускает контейнер (create и start)
2) изменяет слой для записи
3) делает commit
На каждой итерации создается новый слой. При исполнении ‘docker build’ может создаваться множество слоев.

docker exec

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker exec’ применяется к запущенному контейнеру, запускает новый процесс внутри пространства процессов контейнера.

docker inspect |

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такоеили Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker inspect’ получает метаданные верхнего слоя контейнера или образа.

docker save

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker save’ создает один файл, который может быть использован для импорта образа на другую хост-систему. В отличие от команды ‘export’, она сохраняет все слои и их метаданные. Может быть применена только к образам.

docker export

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker export’ создает tar архив с содержимым файлов контейнера, в результате получается папка, пригодная для использования вне docker. Команда убирает слои и их метаданные. Может быть применена только для контейнеров.

docker history

До:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

После:
Docker слои что такое. Смотреть фото Docker слои что такое. Смотреть картинку Docker слои что такое. Картинка про Docker слои что такое. Фото Docker слои что такое

Команда ‘docker history’ принимает и рекурсивно выводит список всех слоев-родителей образа (которые тоже могут быть образами)

Источник

Docker. Зачем и как

Есть множество прекрасных публикаций для тех, кто уже пользуется docker-ом. Есть хорошие статьи для тех, кто хочет этому научиться. Я пишу для тех, кто не только не знает, что такое docker, но и не уверен стоит ли ему это знать.

Я сознательно опускаю некоторые технические подробности, а кое где допускаю упрощения. Если вы увидите, что docker – то, что вам нужно, вы легко найдете более полную и точную информацию в других статьях.

Начну я с описания нескольких типичных проблем.

Проблемы

Первая проблема — как передать продукт клиенту.

Предположим у вас есть серверный проект, который вы закончили и теперь его необходимо передать пользователю. Вы готовите много разных файликов, скриптов и пишите инструкцию по установке. А потом тратите уйму времени на решения проблем клиента вроде: «у меня ничего не работает», «ваш скрипт упал на середине — что теперь делать», «я перепутал порядок шагов в инструкции и теперь не могу идти дальше» и т. п.

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

Вторая проблема — тиражируемость. Пусть вам нужно поднять 5 (или 50) почти одинаковых серверов. Делать это вручную долго, дорого и подвержено ошибкам.

Наконец, третья проблема — переиспользуемость. Предположим у вас есть отдел, который делает браузерные игры. Предположим, что их у вас уже несколько. И все они используют один и тот же технологический стэк (например — java-tomcat-nginx-postgre). Но при этом, чтобы поставить новую игру вы вынуждены заново подготавливать на новом сервере почти одинаковую конфигурацию. Вы не можете просто так взять и сказать — «хочу сервер, как в игре странники но только с другим веб архивом»

Обычные решения

Как обычно решаются эти проблемы.

Установочный скрипт

Первый подход я уже упомянул — вы можете написать скрипт, который установит всё, что вам нужно и запускать его на всех нужных серверах. ( Скрипт может быть как простым sh файлом, так и чем-то сложным, созданным с использованием специальных инструментов).

Недостатки этого подхода — хрупкость и неустойчивость к ошибкам. Как бы хорошо не был написан скрипт, рано или поздно на какой-то машине он упадёт. И после этого падения машина фактически окажется «испорченной» — просто так «откатить» те действия, которые скрипт успел выполнить, у вашего клиента не получится.

Облачные сервисы

Второй подход — использование облачных сервисов. Вы вручную устанавливаете на виртуальный сервер всё, что вам нужно. Затем делаете его image. И далее клонируете его столько раз, сколько вам надо.

Недостатка здесь два. Во-первых, vendor-lock-in. Вы не можете запускать свое решение вне выбранного облака, что не всегда удобно и может привести к потерям несогласных с этим выбором клиентов. Во-вторых, облака медленны. Виртуальные (и даже «bare-metal») сервера предоставляемые облаками на сегодняшний день сильно уступают по производительности dedicated серверам.

Виртуальные машины

Третий подход — использование виртуальных машин. Здесь тоже есть недостатки:

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

Сложное управление совместным использованием серверных ресурсов — не все виртуальные машины вообще поддерживают совместное использование памяти или CPU. Те что поддерживают, требуют тонкой настройки.

Подход докера — контейнеризация

И вот тут появляется docker, в котором

Как работает docker

Создание образа

Сначала создается docker image (или образ). Он создается при помощи скрипта, который вы для этого пишете.
Образы наследуются и, обычно, для создания своего первого образа мы берём готовый образ и наследуемся от него.
Чаще всего мы берем образ в котором содержится та или иная версия linux. Скрипт тогда начинается как-то так:

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

Докер поддерживает гораздо больше различных директив. Например, директива USER roman говорит докеру что все следующие директивы нужно выполнять из под пользователя roman. А директива ENTRYPOINT [“/opt/tomcat/catalina.sh”] задает исполняемый файл, который будет запускаться при старте.

Я не буду перечислять все остальные директивы — в этом нет смысла. Здесь главное — принцип: вы создаёте вот такой скрипт, называете его Dockerfile и запускаете команду docker build, docker выполняет скрипт и создает image.

Если в процессе возникают какие-то ошибки, докер о них сообщает и вы их исправляете. То есть исправление скрипта происходит на этапе создания image. На этапе установки скрипт уже не используется.

Создание контейнера

Когда у вас уже есть docker image вы можете создать из него контейнер на любом физическом сервере, где установлен докер. Если image – это тиражируемый образ некоторой «машины», то container это уже сама «машина», которую можно запускать и останавливать.

Важный момент — при создании контейнера из image, его можно параметризовать. Вы можете передавать докеру переменные окружения, которые он использует при создании контейнера из image. Так вы сможете создавать немного разные машины из одного образа. Например, передать образу web-сервера его доменное имя.

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

Union filesystem

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

На самом деле в докере это не так. Если вы используете 100500 контейнеров, основанных на одном и том же образе операционной системы, то файлы этой системы будут скачаны докером ровно один раз. Это достигается за счёт использования докером union file system.

Union file system состоит из слоёв (layers). Слои как бы наложены друг на друга. Некоторые слои защищены от записи. Например, все наши контейнеры используют общие защищенные от записи слои, в которых находятся неизменяемые файлы операционной системы.

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

Container registry

Получается, что docker image состоит из слоёв. И хорошо было бы уметь скачивать на наш сервер только те слои, которых на нём пока нет. Иначе для установки 100 контейнеров, основанных на Ubuntu мы скачаем Ubuntu внутри их образов 100 раз. Зачем?

Хорошая новость в том, что докер решает эту проблему. Докер предоставляет специальный сервис, называемый docker registry. Docker registry предназначен для хранения и дистрибуции готовых образов. Собрав новый образ (или новую версию образа) вы можете закачать его в docker registry. Соответственно, потом его можно скачать оттуда на любой сервер. Главная фишка здесь в том, что физически качаться будут только те слои, которые нужны.

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

Аналогично, если сервер качает из registry какой-то образ, скачаны будут только слои, отсутствующие на сервере.
Docker registry существует и как общедоступный сервис и как open source проект, доступный для скачивания и установки на собственной инфрастуктуре.

Использование контейнеров

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

Взаимодействие между контейнерами

Если контейнеров на сервере несколько, управлять ими вручную становится проблематично. Для этого есть технология docker compose. Она существует поверх докера и просто позволяет управлять контейнерами на основе единого конфигурационного файла, в котором описаны контейнеры, их параметры и их взаимосвязи (например контейнер A имеет право соединяться с портом 5432 контейнера B)

Выводы

Таким образом докер очень хорошо подходит для решения перечисленных выше задач:

Источник

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

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