Да что такое этот ваш докер и контейнеры?! Хэй! Возможно тебе знакома ситуация, когда коллеги на работе у кулера увлеченно обсуждают какие-то доки, какие-то контейнеры и оркестрацию. Что вы вообще несете? - можешь подумать ты. Мы же не в порту работаем! Да и не в консерватории. Сейчас мы раскроем завесу этой тайны и научим тебя понимать девопсерский язык. Представь, что твой коллега начитался про самые странные языки программирования, написал на одном из них программу, запустил все это дело своём дистрибутиве Linux с нескучными обоями и приправил все это дело мильоном зависимостей. И как теперь тебе это все запускать, связывать с другими частями вашего общего приложения и отдавать в продакшн клиентам, у которых не столь специфичные вкусы, м? Получается, что нам нужно как-то скопировать все что нужно для работы программы, чтобы ее можно было бы запускать везде и работала она одинаково.
Нуу, первое что приходит на ум - виртуальные машины, или как их еще называют “виртуалки”. Если ты не в курсе что это такое, то если кратко, это как будто ты попросил Экзибита прокачать твой компьютер и он установил компьютер в твой компьютер. Только не настоящий, а виртуальный, хотя он считает себя настоящим. Короче, в этой схеме у нас есть наш сервер, на нем установлена операционка, а поверх нее работает ПО, называемое гипервизором: например Hyper-V (хайпер-ви) , VMWare ESX (ви эм вэйр и эс икс) или VirtualBox (виртуал бокс), которые эмулируют железо и управляет виртуальными машинами. Каждый экземпляр виртуалки имеет собственную операционную систему, которая называется гостевой, а приложения работают уже внутри нее. Таким образом, ты можешь на сервере с виндой запускать линукс и кучу других ОС и наоборот. И вот для этой виртуальной машины мы сможем установить нужную операционку и зависимости, и запустить наше прекрасное приложение - все будет работать. Однако, в современных реалиях, с учетом того, что теперь все любят распиливать одну большую программу на много маленьких, и называть это микросервисной архитектурой, такой подход будет не очень оптимальным. Ведь каждая виртуалка запускает у себя отдельную ОС, в результате - все это может работать, мягко говоря, не быстро. Плюс к этому, зачастую нам нужно запускать несколько копий одного и того же приложения, так что нагрузка будет только расти.
Значит настало время попробовать Docker (докер). Это такой инструмент, который упаковывает код приложения, системные инструменты, среду выполнения, библиотеки, зависимости и файлы конфигурации, необходимые для его запуска, в такой виртуальный контейнер, который может работать на любом компьютере, где установлен докер. Уверены, вы поняли аналогию - как контейнеры с грузами в порту! Туда можно удобно поместить всё что угодно - машину, бананы, людей… шучу, не бананы. А потом всё это отправить в долгое путешествие по морю в едином оптимальном форм-факторе. Все это схоже с работой виртуальных машин, но есть одно ключевое отличие. С докером мы избавляемся от гипервизора, а вместо того чтобы виртуализировать железо, мы виртуализируем только операционку. Значит нам нет необходимости в отдельных гостевых ОС, потому что контейнеры используют ядро ОС того сервера, где мы работаем, при помощи приложения Docker Engine (докер энджин). Поэтому, мы тратим меньше ресурсов, и получаем больше удовольствия от удобной работы с легковесными контейнерами. При этом приложения остаются все также изолированы от системы и других приложений. Кстати, докер - не единственная технология контейнеризации, но определенно самая популярная. Круто, разобрались.
Давай теперь про сам Docker (докер) поговорим. Тут нужно знать о трех основных элементах: Докер файл (dockerfile) Образ (image) Контейнер (container) Взаимодействие между ними такое: из докерфайла собирается образ, а на основе образа запускается контейнер. Наша начальная точка, она же докер файл, содержит код, который, по сути, является набором инструкций, которые говорят докеру, как нужно создать образ и что там должно оказаться. Ага, а образ че такое? Образ - это уже готовое к запуску приложение, в котором лежит исходный код, библиотеки, зависимости, инструменты и другие файлы, необходимые для его запуска. И уже из этого образа мы запускаем сам контейнер - экземпляр нашего приложения. Образами приложений можно делиться - для этого используются Docker Registry (докер реджистри) - реестры хранящие образы. Самый крупный это Docker Hub, откуда можно стянуть образ какого-нибудь приложения или операционки и на их основе собрать свой собственный образ.
Давай рассмотрим это на примере. Создадим докерфайл и напишем там:
FROM ubuntu:20.04
Это значит, что мы берем себе за основу уже существующий образ, в нашем примере убунту версии 20.04, который скачаем из реестра, а если точнее - из того самого докер хаба. Затем мы можем запустить команду в терминале, при помощи команды RUN:
RUN apt-get update
RUN apt-get -y install nginx
Этой командой мы можем установить все зависимости которые нужны для работы. Например, в данном случае мы хотим установить веб-сервер nginx (энджинкс) Затем нам нужно открыть порт, по которому мы будем получать доступ к нашему серверу, тут напишем команду EXPOSE:
EXPOSE 80/tcp
Ну а в конце напишем команду CMD которую нужно запустить в терминале, но она выполняется не при сборке образа, как RUN, а при запуске самого контейнера. Мы, конечно же, хотим запустить наш сервер, поэтому напишем следующую строчку в наш докерфайл:
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
Сохраним этот файл, и создадим из него образ используя команду docker build. В этот момент докер пройдется по всем нашим инструкциям шаг за шагом и создаст для нас образ, который будет содержать всё, что мы понаписали в докерфайле. Ну а после создания образа можно запустить из него контейнер, выполнив программу docker run. Теперь, если мы откроем браузер и наберем в адресной строке localhost, то увидим что все работает!
Вот так просто, используя различные команды мы можем выстраивать образ под наши нужды. Однако если нам не требуется скрупулезная настройка образа, а мы просто хотим получить работающую программу - то, как мы уже сказали, мы просто можем стянуть готовый образ с докерхаба. И тогда в нашем случае мы просто выполним команду docker pull nginx и выполним такую же команду docker run. И все так же работает, красота! Конечно, в реальности все обычно сложнее, и приходится решать много нестандартных задач. Например, знаешь ли ты, что по-умолчанию все изменения внутри контейнера теряются при его остановке? И таких нюансов очень много.
Теперь надо поговорить о том случае, когда нужно запускать несколько контейнеров сразу. Как мы говорили раньше - мы живем в век микросервисов, и их может быть довольно таки много. Тут нам на помощь приходит инструмент docker-compose (докер компоуз). С его помощью мы можем упростить развертывание приложения состоящего из нескольких контейнеров, используя всего один файл , в котором описываются сервисы, которые необходимо запустить и их настройки. Создали такой файлик, запустили команду docker-compose up и вуаля - поднялся целый скоп контейнеров разом. Ну, а если что то не работает, то жми на красную кнопку А сколько этих контейнеров обычно запускается? Ну, в реальных приложениях это могут быть десятки и сотни. И этим делом надо как-то управлять, мониторить, обновлять, выделять ресурсы, балансировать нагрузку, следить чтобы каждый почистил зубки и покушал, короче - куча забот. Тут в игру вступают так называемые приложения оркестрации контейнеров. И хотя у докера есть свое приложение Docker Swarm (докер сворм), многие используют инструмент под названием Kubernetes (кубернетис). И кажется, что эта связка стала легендарной. Подводя итоги можно сказать что докер, это круто не только потому, что строчка с ним в резюме определенно повысит твою ЗП, а кубернетис повысит ее еще больше, но и потому, что он совмещает в себе все, что мы так любим в айти: автоматизацию, скорость, консистентность, модульность, экономичность и классный логотип Ну и под конец как всегда вопрос к знатокам: если докер такой классный, то почему он не выдавил с рынка виртуальные машины? В каких задачах без виртуалок не обойтись?