Привет, Хабр! На момент написания статьи я занимаюсь надёжностью (SRE) в компании Workday, а ещё помогаю студентам в Практикуме осваивать курс по DevOps.

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

В последние 10 лет Docker перевернул мир виртуализации и стал незаменимым инструментом для DevOps-практик. За это время контейнеризация стала настолько распространённой и привычной, что многие даже не задумываются, как она устроена изнутри. Из моего опыта интервьюирования вопрос «Что такое Docker?» нередко ставит людей в тупик. Я считаю, что полезно досконально разбираться в вещах, чтобы эффективно решать проблемы и понимать, на каком из слоев системы что-то идёт не так.

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

Появление Docker

Официальный анонс Docker 1.0 в блоге компании (из веб-архива)
Официальный анонс Docker 1.0 в блоге компании (из веб-архива)

Прежде чем Docker появился на свет, существовали другие технологии контейнеризации, такие как LXC (Linux Containers) и OpenVZ. Существовали и проекты изоляций процессов на уровне файловой системы вроде jails и chroot, но это совсем другая история. Эти проекты также предоставляли средства для создания изолированных сред, но они не обладали такой же степенью простоты и переносимости, как Docker.

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

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

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

Docker появился как ответ на вызовы того времени, от людей, которые не понаслышке знали всю боль и проблемы индустрии. Этот проект был запущен компанией dotCloud и его основателем Соломоном Хайксом в 2013 году и достаточно быстро стал эффективным решением для контейнеризации приложений. Но так было не всегда и, конечно же, получилось не сразу.

Твит Соломона Хайкса, перевод: «Немного истории. Первый прототип Docker был написан на Python. Мы решили перейти на Go по следующим причинам...»
Твит Соломона Хайкса, перевод: «Немного истории. Первый прототип Docker был написан на Python. Мы решили перейти на Go по следующим причинам...»

До первого публичного релиза прототип Docker представлял собой набор shell-скриптов. Позже проект перешел с Python на Golang, заодно и внеся вклад в популяризацию молодого языка программирования.

Себастьян ван Стейн (Runtime lead, Staff Software Engineer, Docker) и Фредерик Каутц (бывший инженер команды Docker) об истории создания Docker
Себастьян ван Стейн (Runtime lead, Staff Software Engineer, Docker) и Фредерик Каутц (бывший инженер команды Docker) об истории создания Docker

Docker решил многие проблемы благодаря следующим особенностям:

  • Изоляция: 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 состоит из нескольких ключевых компонентов:

  • 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!) кластерах.

Технологии ядра, используемые Docker

Помимо 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

Для максимальной эффективности и безопасности использования Docker соблюдайте следующие практики:

  • Изолируйте зависимости: каждый контейнер должен содержать только необходимые зависимости для запуска приложения. Используйте multistage-сборку, не оставляйте временные файлы или пакеты в образе.

  • Следуйте принципу одного процесса: каждый контейнер должен запускать только один процесс. Это облегчает отслеживание и управление контейнерами.

  • Обновляйте образы регулярно: регулярно обновляйте образы, чтобы получать последние обновления безопасности и исправления ошибок.

  • Практикуйте мониторинг и журналирование: используйте инструменты мониторинга и журналирования для отслеживания работы контейнеров и выявления проблем.

  • Не забывайте о безопасности: не игнорируйте базовые принципы безопасности, такие как ограничение доступа к хосту и контроль доступа к ресурсам.

  • Не запускайте контейнеры с привилегированными правами: избегайте использования флага --privileged, который предоставляет контейнеру полный (привилегированный) доступ к хосту.

  • Не храните секретные данные в образах: не включайте секретные ключи или пароли в Docker-образы. Используйте механизмы секретного хранения, такие как Vault или Docker Secrets.

Почему Docker совершил революцию

Docker изменил ландшафт виртуализации и стал незаменимым инструментом для DevOps-практик. Его легкость использования, эффективность и широкая экосистема делают его первым выбором для контейнеризации приложений. Унификация процессов сборки и доставки кода оказала значительное влияние на индустрию в целом, в конечном итоге позволив сэкономить огромное количество как человеко-часов, так и машинного (вычислительного) времени и — как следствие — денег. 

Появление и популяризация Docker послужили толчком созданию множества новых технологий, таких как rkt, Podman, Kubernetes, kind, Rancher, Dokku. Также появилось много новых сервисов: начиная с публичных Container Registry от quay.io до gcr.io, заканчивая Serverless-сервисами — ECS, Cloud Run и так далее. 

Спустя 10 лет огромный вклад Docker в развитие индустрии сложно переоценить, ещё сложнее сказать, что этот импульс принесёт нам в дальнейшем. Только одно можно с уверенностью сказать: «Революция действительно свершилась!»

Дополнительные ресурсы

Комментарии (21)


  1. unreal_undead2
    03.10.2023 13:17
    +5

    Существовали и проекты изоляций процессов на уровне файловой системы вроде jails и chroot, но это совсем другая история

    На мой взгляд это часть той же истории - сначала в Unix v7 был chroot, потом в FreeBSD придумали более продвинутый jail, после в Linux его обобщили до namespaces, которые уже стали ключевым элементом реализации контейнеров в целом и Docker в частности.


    1. nobodysausage
      03.10.2023 13:17

      ну в сторону докер в нулевых шёл 2x правда виртуализируя пользователя и его app среду


  1. Den_CH
    03.10.2023 13:17
    +2

    А чем supervisor плох внутри контейнера?


    1. mysherocker
      03.10.2023 13:17
      -1

      Supervisor вообще потерял какой-либо смысл с момента распространения systemd


    1. 1it Автор
      03.10.2023 13:17

      Дело не том что он плох внутри контейнера, он в принципе не то чтобы очень хорош. Но суть в том, что не нужно плодить процессы внутри контейнера. Один контейнер/один сервис/одна задача.


      1. slonopotamus
        03.10.2023 13:17
        +1

        Кто сказал что один сервис == один процесс? И как это должно выглядень на каком-нибудь php или ruby? Они однопоточные, им надо воркеров запускать.


      1. Den_CH
        03.10.2023 13:17

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

        Каков тут путь? Три докер-контейнера? Не всегда возможно, да и просто не удобно :)


  1. qpepxfhei
    03.10.2023 13:17
    +2

    Кажется, сейчас уже тяжело представить мир без docker


    1. GospodinKolhoznik
      03.10.2023 13:17

      Я вообще девопсер ненастоящий, могу ошибаться. Но мне кажется сейчас есть альтернативы. Например nix-shell - чем не замена докеру?


      1. Gorthauer87
        03.10.2023 13:17
        +1

        Он немного про другое, но вот dockertools хорошая замена dockerfile.


    1. Ulrih
      03.10.2023 13:17
      +3

      Почему? Как-то проработали это 10 лет без докеров


    1. ChizhM
      03.10.2023 13:17
      +2

      Не поверите, очень легко без всего этого живётся мне - вебмастеру-адммну со стажем 22 года.

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


      1. dimas062
        03.10.2023 13:17

        Он очень много где не нужен, куда его пытаются натянуть.


      1. polearnik
        03.10.2023 13:17

        1) быстрая настройка машины. для запуска проекта не надо игратся с утановкой вебсервера пхп ноа и баз данных ожно просто склонировать репу и сделать docker compose up

        2) невозможность ситуации когда для запуска нескольких проектов требующих разные версии одного языка нужно танцевать с бубном. Один сайт спокойно в докере запустится на старом пхп 5.6 другой сайт спокойно запустится на пхп8

        3)возможность быстро попробовать чтото и удалить не оставляя мусора в системе. Запустить пачку контейнеров вдохновившись статьей по заббиксу и разочароввшись в нем очен ьпросто снести его не выковыривая каждый конфиг из отдельной папки и менять обратнокакието системные настройки.

        я работал без докера 6 лет и было норм. но сейчас перешел на докер и не жалею. стало удобнее


  1. bumjmekriz
    03.10.2023 13:17
    +1

    Вообще пора вводить премию за выдающийся вклад в IT, и дать ее docker


  1. firehacker
    03.10.2023 13:17
    +14

    Статья уровня «сепулек». Куча восхваляющих тезисов, как обычно любят маркетологи, но никакой конкретики относительно того, как это устроено, на какие принципы полагается и за счёт чего.

    jail в FreeBSD всегда был понятен: никто никогда не говорил, что это супер-штука, которая революционно изменит вашу жизнь. Всегда декларировалось, что это заложенный в ОС механизм, который изолирует процессы, и создаёт для процесса иллюзию, будто бы он работает внутри обособленной физической машины под управлением FreeBSD, хотя на самом деле ФС, которую видят процессы в джейле и дерево процессов, которые видны в джейле (и ряд других ресурсов), являются только подмножеством родительской ФС, родительского дерева процессов и родительского набора системных вопросов.

    И в общем-то из описания автоматически понятно, как такой механизм может быть устроен: поскольку он часть ОС, а ОС используют защищенный режим процессора и концепцию контроля за доступом разных процессов к разным системным объектам, нет никакой проблемы на уровне ОС не только ограничить доступ процессам к объектам и ресурсам, но и создать им иллюзию работы в изолированной среде, причём такую, что юзер-модный процесс «вырваться из матрицы» никакими ухищрениями не сможет?

    Но как быть с Докером? Про него вы не пишите ничего.

    Это обёртка над уже существующими в ОС инструментами для создания изолированных сред (вроде jail в FreeBSD)? Так бы сразу и писали. Но тогда не понятно, о какой гибкости и универсальности может идти речь, если это примочка для одной отдельно взятой ОС, которая внутри виртуализируемой среды может создавать только видимость той же самой ОС? jail же не умеет на FreeBSD внутри джейла создать видимость ReactOS или MacOS...

    Если это не обёртка над jail (или аналогичными инструментами в др. ОС), то тогда ещё интереснее узнать, за счёт чего оно способно создать изоляцию процессов и иллюзию изолированной среды, не работая в режиме ядра и серьёзнейшим образом не вклиниваясь в работу ОС?

    Так оно лезет в режим ядра или умудряется создавать видимость изолированной среды чисто из пользовательского режима (перехватывая системные вызовы и подменяя аргументы/возвраты/поведение)?

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

    Например эмулятор Сеги Gens32 или эмулятор автомобильных диагностических сканеров Cascade.

    Судя по имеющемуся в статье противопоставлению докера и классических виртуальных машин, Докер это не про этот подход.

    Так всё-таки, как это работает? На каком уровне оно виртуализирует? На какие нижележащие средства оно полагается? Ни слова об этом в статье.

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


    1. slonopotamus
      03.10.2023 13:17
      +2

      обёртка над jail (или аналогичными инструментами в др. ОС)

      Всё так. Причём для линукса и винды это совершенно разные инструменты. Ну и вообще на сегодняшний день докер - это обертка над оберткой над оберткой: docker -> containerd -> runc -> Linux namespaces. И именно поэтому в Kubernetes выкинули докер и напрямую стали работать с containerd, т.к. для них докер не несет в себе никакой дополнительной пользы.

      Докер сделал три важные вещи:

      1. Удобный CLI

      2. Дистрибуцию образов

      3. Докерфайлы


      1. NN1
        03.10.2023 13:17
        +1

        А также способствовал популяризации Go.


    1. 1it Автор
      03.10.2023 13:17

      Чем ответить на ваш  «сепулек», не представляю, боюсь опускаться до такого уровня.
      С вашей точкой зрения всё ясно, однако она не является единственно верной. Как моя статья — субъективное отражение моего понимания вещей, не претендующая на истину в последней инстанции.
      Писать всеобъемлющие технические статьи долго, тяжело и как правило не оправдывает средств. Написать статью, которая привлечет интерес читателя и не заставит его заснуть после пяти минут чтения, а возможно еще и заинтересует и вызовет вопросы — тоже та еще задачка. И потом, если бы люди писали статьи не оставляющие вопросов, (где бы токсики сбрасывали яд?) на Хабре не было бы смысла в комментах.
      На мой взгляд, человек интересующийся чем-то, должен уметь всесторонне оценивать информацию, делать свои выводы, сравнивая разные точки зрения и не упрощать вещи (в которых 245k+ строк кода) до уровня "обертки" или "изоляции".


  1. mesvobodnye
    03.10.2023 13:17
    +1

    Здравствуйте. Ничего толком о Докере не знаю, но постоянно вижу отзывы об этой технологии и нутром чую - "мне надо". Что посоветуете почитать для нулевого новичка?


    1. 1it Автор
      03.10.2023 13:17

      Здравствуйте, в статье есть ссылки где можно почитать еще. А вообще очень много толковых англоязычных ресурсов, погуглите например "ivan velichko docker" - у него весьма толковый бложек.