Привет, Хабр! На момент написания статьи я занимаюсь надёжностью (SRE) в компании Workday, а ещё помогаю студентам в Практикуме осваивать курс по DevOps. Сейчас виртуализация стала фундаментальной технологией для оптимизации работы серверов, упрощения процессов разработки и развёртывания приложений. Однако до появления Docker она оставалась относительно сложным и медленным процессом.  В последние 10 лет Docker перевернул мир виртуализации и стал незаменимым инструментом для DevOps-практик. За это время контейнеризация стала настолько распространённой и привычной, что многие даже не задумываются, как она устроена изнутри. Из моего опыта интервьюирования вопрос «Что такое Docker?» нередко ставит людей в тупик. Я считаю, что полезно досконально разбираться в вещах, чтобы эффективно решать проблемы и понимать, на каком из слоев системы что-то идёт не так. В этой статье я поделюсь кратким обзором истории Docker, его ключевыми концепциями и мисконцепциями. Надеюсь, это будет полезно для новичков и студентов, изучающих DevOps-практики и виртуализацию. Прежде чем Docker появился на свет, существовали другие технологии контейнеризации, такие как LXC (Linux Containers) и OpenVZ. Существовали и проекты изоляций процессов на уровне файловой системы вроде jails и chroot, но это совсем другая история. Эти проекты также предоставляли средства для создания изолированных сред, но они не обладали такой же степенью простоты и переносимости, как Docker. Docker взял вдохновение из этих ранних технологий. Он использовал LXC как один из своих первых бэкендов для управления контейнерами. Однако Docker добавил уровень абстракции и упростил процесс создания и управления контейнерами, что сделало его более доступным для широкой аудитории разработчиков и системных администраторов. Таким образом Docker не только усовершенствовал концепцию контейнеризации, но и сделал её более доступной и широко применимой. Эта комбинация удобства использования и эффективности через какое-то время сделала Docker доминирующей технологией в мире контейнеризации и DevOps. Дело в том, что разработчики и администраторы всегда сталкивались с рядом сложных задач по созданию, контролю консистентности сред и масштабированию сервисов. Традиционные виртуальные машины требовали больших ресурсов и времени для запуска. Управление приложениями и их зависимостями было и до сих пор является нетривиальной задачей.  Docker появился как ответ на вызовы того времени, от людей, которые не понаслышке знали всю боль и проблемы индустрии. Этот проект был запущен компанией dotCloud и его основателем Соломоном Хайксом в 2013 году и достаточно быстро стал эффективным решением для контейнеризации приложений. Но так было не всегда и, конечно же, получилось не сразу. До первого публичного релиза прототип Docker представлял собой набор shell-скриптов. Позже проект перешел с Python на Golang, заодно и внеся вклад в популяризацию молодого языка программирования. Docker решил многие проблемы благодаря следующим особенностям: Изоляция: Docker позволяет запускать приложения в изолированных контейнерах, что обеспечивает уровень изоляции, сравнимый с виртуальными машинами, но с гораздо меньшими накладными расходами. Портативность: Docker-контейнеры могут быть запущены на любой платформе, где установлен Docker. Это делает разработку и развёртывание приложений более удобными и предсказуемыми. Управление зависимостями: Docker позволяет упаковать приложение и его зависимости в один контейнер, обеспечивая надёжное управление зависимостями и версиями. Сразу после выпуска Docker быстро завоевал популярность среди разработчиков и системных администраторов. Сообщество внимательно следило за проектом, создавая множество инструментов и решений, основанных на Docker. Стоит отметить, что Docker появился в тот момент, когда технологии виртуализации вроде Xen, KVM и VMWare были стандартом, а создание и контроль ВМ для запуска сервисов и разработческих сред управлялись инструментами оркестрации типа Puppet и Chef. Это было стандартом индустрии достаточно долгое время. На рынке была масса сертифицированных специалистов разных мастей, и далеко не все из них — включая автора статьи — сразу поняли и приняли новый инструмент. Пожалуй, это послужило появлению множества мисконцепций использования контейнеризации и привело к незаслуженной критике. Ряд разработчиков и администраторов использовали Docker не по назначению, рассматривая его как более удобную и легковесную замену ВМ. При этом они запускали в нём множество процессов как в полноценной ОС. Например, я лично видел, как люди запускали внутри supervisor, через него своё приложение, ssh-демон и, например, Zabbix-агент (тогда Zabbix ещё был весьма популярен).  Несмотря на свой впечатляющий успех и внимание со стороны сообщества, Docker также столкнулся с конструктивной критикой на начальных этапах своего развития. Замечания чаще всего были направлены на такие аспекты: Изоляция процессов: Docker не обеспечивает такую же степень изоляции, как традиционные виртуальные машины. Это означает, что контейнеры могут влиять друг на друга, что вызывает опасения с точки зрения безопасности и стабильности. Сложность сетевой конфигурации: настройка сети для контейнеров в Docker может быть сложной задачей, особенно при работе с множеством контейнеров и микросервисными архитектурами. Монолитность приложений: на начальных этапах Docker-контейнеры иногда использовались для запуска монолитных приложений, что не всегда было наилучшей практикой для микросервисных архитектур. Стоит отметить, что сообщество Docker активно работало над улучшением и разрешением этих проблем. В последующих версиях Docker были внедрены множество улучшений в области безопасности, изоляции и управления сетью. Критика стала движущей силой для развития Docker, и он сильно усовершенствовался с течением времени. Был ещё странный момент в истории, когда в один день, без предупреждения и особых объяснений, Docker переименовали в Moby. Это вызвало у всех как минимум недоумение. Смена имени на GitHub и, соответственно, смена всех путей в коде была не очень тепло встречена сообществом и особенно контрибьюторами проекта. Начиная с этой точки коммерческая компания Docker стала активно искать пути, как заработать на своём продукте, не отказываясь от Open Source корней.Подробнее о событии в историческом пулл‑реквесте в репозитории Moby на GitHub'е, англ.   Docker — это инструмент, который используется для автоматизации развёртывания приложений в лёгких контейнерах, чтобы приложения могли эффективно работать в разных средах изолированно. Docker состоит из нескольких ключевых компонентов: Docker Engine: ядро (демон) Docker, управляющее контейнерами; Docker Containers: изолированные среды, в которых работают приложения; Docker Images: шаблоны для создания контейнеров; Docker Registry: репозиторий для хранения и обмена Docker Images; Docker CLI: консольная утилита для взаимодействия с вышеперечисленными компонентами. Вокруг Docker сформировалась обширная экосистема инструментов и продуктов. Сервис Docker Hub стал настолько популярен среди разработчиков, что компании Docker в какой-то момент пришлось вводить лимиты на скачивание публичных образов — суммарное месячное количество скачиваний давно перевалило за 10 миллиардов.  Docker Desktop даёт возможность запускать и использовать компоненты Docker на системах, отличных от Linux, практически с тем же удобством, что в нативной среде. Он позволяет разработчикам и администраторам быстро разворачивать любые сервисы, делать сборку и тестирование единообразным способом вне зависимости от их рабочей ОС: будь то MacOS или Windows. Также, например, Docker Compose позволяет определить и запустить множество контейнеров одновременно, в т.ч. и на множестве хостов, с помощью Docker Swarm. Kubernetes (который не так давно отказался от среды исполнения контейнеров Docker Engine в пользу Containerd) обеспечивает оркестрацию контейнеров в крупных и малых (привет Minikube!) кластерах. Помимо Golang, который вместе с сообществом внёс немалый вклад в успех проекта, Docker стоит на мощных плечах Linux. Он полагается на ряд ключевых технологий ядра операционной системы Linux для обеспечения изоляции и управления контейнерами: Namespaces: технология ядра Linux, разработанная в достаточно далёком 2002 году. Docker использует namespaces, такие как PID (Process ID), Network и Mount, для создания изолированных пространств имён. Например, с использованием PID namespaces каждый контейнер видит только свои процессы, что обеспечивает изоляцию процессов между контейнерами. Cgroups (Control Groups): технология, разработанная внутри компании Google еще в 2006 году. Контрольные группы используются Docker для ограничения ресурсов, доступных контейнеру: CPU, памяти и дискового пространства. Это позволяет предотвратить «голодание» ресурсов и обеспечить справедливое распределение мощностей между контейнерами. Union File Systems: Docker использует «слоистые» файловые системы, такие как AUFS, OverlayFS и Overlay2, чтобы создавать легковесные и эффективные образы контейнеров. Это возможно благодаря тому, что они разделяют общие файлы между собой, экономя дисковое пространство. Seccomp (Secure Computing Mode): для повышения безопасности Docker может использовать Seccomp. Он ограничивает доступ контейнера к системным вызовам, что позволяет уменьшить поверхность атаки и предотвратить выполнение опасных операций. Capabilities: ядро Linux предоставляет разные возможности (capabilities) для выполнения привилегированных действий. Docker позволяет настраивать набор возможностей, доступных контейнеру, для более тонкой настройки безопасности. Все эти технологии позволяют Docker создавать изолированные и легковесные контейнеры, работающие на одном ядре операционной системы, но при этом с высоким уровнем изоляции между собой. Docker обеспечивает среду, в которой приложения могут работать независимо друг от друга, при этом обеспечивается эффективное использование ресурсов и упрощение управления контейнерами. Для максимальной эффективности и безопасности использования Docker соблюдайте следующие практики: Изолируйте зависимости: каждый контейнер должен содержать только необходимые зависимости для запуска приложения. Используйте multistage-сборку, не оставляйте временные файлы или пакеты в образе. Следуйте принципу одного процесса: каждый контейнер должен запускать только один процесс. Это облегчает отслеживание и управление контейнерами. Обновляйте образы регулярно: регулярно обновляйте образы, чтобы получать последние обновления безопасности и исправления ошибок. Практикуйте мониторинг и журналирование: используйте инструменты мониторинга и журналирования для отслеживания работы контейнеров и выявления проблем. Не забывайте о безопасности: не игнорируйте базовые принципы безопасности, такие как ограничение доступа к хосту и контроль доступа к ресурсам. Не запускайте контейнеры с привилегированными правами: избегайте использования флага --privileged, который предоставляет контейнеру полный (привилегированный) доступ к хосту. Не храните секретные данные в образах: не включайте секретные ключи или пароли в Docker-образы. Используйте механизмы секретного хранения, такие как Vault или Docker Secrets. Docker изменил ландшафт виртуализации и стал незаменимым инструментом для DevOps-практик. Его легкость использования, эффективность и широкая экосистема делают его первым выбором для контейнеризации приложений. Унификация процессов сборки и доставки кода оказала значительное влияние на индустрию в целом, в конечном итоге позволив сэкономить огромное количество как человеко-часов, так и машинного (вычислительного) времени и — как следствие — денег.  Появление и популяризация Docker послужили толчком созданию множества новых технологий, таких как rkt, Podman, Kubernetes, kind, Rancher, Dokku. Также появилось много новых сервисов: начиная с публичных Container Registry от quay.io до gcr.io, заканчивая Serverless-сервисами — ECS, Cloud Run и так далее.  Спустя 10 лет огромный вклад Docker в развитие индустрии сложно переоценить, ещё сложнее сказать, что этот импульс принесёт нам в дальнейшем. Только одно можно с уверенностью сказать: «Революция действительно свершилась!» Документация Docker; Docker на GitHub; Доклад Сергея Задорожного «Docker. Кому, зачем и как?»; Telegram-канал DevOps | Яндекс Практикум.  Systems Engineer, DevOps/SRE Advocate