Легковесная виртуализация или невесомая изоляция взгляд на реализацию Docker
Давайте взглянем на историю появления предпосылок появления Docker, именно предпосылок, так как сам Docker не реализует ни изоляции, ни тем более виртуализации, а организует работу с ней с первой. В отличии от виртуализации напоминающей ангар со своим миром и своим фундаментом, на который можно наложить, что душе пожелает, например, выдаём и лужайку, то для изоляции можно провести аналогию с забором. Изоляция появлялась в ядре Linux постепенно, частями, отвечающих за разные уровни, а параллельно появлялись программы обеспечивающие интерфейс и концепцию применения этой изоляции в реальных проектах. Изоляция состоит из 6 типов ограничения ресурсов.
Первым в ядро была изоляция файловой системы, позволяющий создать песочницу с помощью команды chroot ещё в 1979 году, из вне песочница видна полностью, но при переходе внутрь папка, над которой выполнена команда становится корневой, и вернуться уже не удастся. Следующий было разграничение процессов, так песочница существует и хостовая система, пока существует процесс с pid (номером) 1. Для песочницы он свой, вне песочницы он обычный процесс. Далее подтянулись стальные разграничения CGroups: групп пользователей, памяти и другие. Всё это существует в ядре любого Linux, независимо от того, установлен Docker или нет у вас. На всём протяжении истории принимались попытки, OpenSource и коммерческие, создавать контейнера, разрабатывая функционал самими и подобные решения находили своих пользователей, но они не проникли в широкие массы. Docker в начале своего существования использовал довольно стабильное, но сложное в использовании решение контейнеризации LXC. Постепенно он заменил LXC на нативные CGroup. Также Docker поддерживает солёность своего образа (об этом далее), но сам её не реализует, а использует UnuonFS (UFS).
Docker и дисковое пространство
Поскольку Docker не реализует функционал, а использует заложенный в ядро Linux, и не имеет под капотом графического интерфейса, сам он занимает очень мало места.
Поскольку контейнер использует ядро хостовой ОС, то в базовом образе (обычно ОС) содержатся только дополняющие его пакеты. Так Docker образ Debian занимает 125Mb, а ISO образ 290Mb. Для проверки, что используется одно ядро в контейнере выведем о нём информацию: uname -a или cat /proc/version, а информацию о самом окружении контейнера cat /etc/ussue
Docker создаёт образ на основе инструкции в файле Dockerfile, который может находиться удалённо или локально, и по нему может быть создан в любой момент. Поэтому, если вы не используете образ в данный момент, то можно удалить его. Исключением является образ, созданный на основе контейнера командой Docker commit, но так создавать не очень правильно, и всегда можно выделить из образа Dockerfile командой Docker history и удалить образ. Преимуществом хранения образов является то, что не требуется ожидать, пока он создаётся: скачивается ОС и библиотеки.
Сам Docker использует образ под названием Image, который создаётся на основе инструкций в файле Dockerfile. При создании нескольких контейнеров на его основе место практически не увеличивается, так как контейнер всего лишь процесс и конфиг настроек. При изменении файлов в контейнере сами файлы не сохраняются, а сохраняются внесённые изменения, который будут удалены после переброски контейнера. Это гарантирует в 99% случаев полностью идентичное окружение, и как следствие не важно помещать подготовительные операции, общие для всех контейнеров по установке специфичных программ в образ, побочным эффектом, которого является отсутствии их дублирования. Чтобы иметь возможность сохранять данные используется монтирование папок и файлов к хостовой (родительской) системе. Поэтому вы можете на обычном компьютере запустить сто и более контейнеров, при этом не увидите изменения в свободном местное на диске. При этом, если разработчики пользуются гит, а как же без него, и часто копятся, то может отпасть необходимость в монтировании папок с исходным кодом.
Образ докеров не представляет из себя монолитный образ вашего продукта, а слоёный пирог образов, слои которого кэшируется. Это позволяет значительно сэкономить время на создание образа. Кэширование можно отключить ключом команды build no-cache=true, если Docker не распознаёт, что данные изменяемы. Докер может увидеть изменения в инструкции ADD, добавляющий файл из хостовой системы в контейнер по хэшу файла. Так, если вы создадите два контейнера, один с NGINX, а другой с MySQL, оба которых основаны на ОС Ubuntu 14.04, то будет существовать три слоя образа: MySQL, NGINX и Ubuntu. Сдали образа можно посмотреть командой Docker history. Также это работает и для ваших проектов при копировании в Ваш образ 2 версий кода командой ADD с вашим продуктом, у вас будет 3 слоя и два образа: базовый, с кодом первой версии и кодом второй версии, независимо от количества контейнеров. Количество слоёв ограниченно 127. Важно заметить, что при клонировании проекта нужно указать версию, а не просто git clone, а git clone branch v1 и git clone branch v2, иначе Docker закэширует слой, создаваемый командой Git Clone и при создании второго образа мы получим тоже самое.