Основные термины Docker


Оглавление (нажмите, чтобы открыть):

Шпаргалка Docker

22 October 2014

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

docker pull ОБРАЗ — загружает образ из Docker Hub (аналог GitHub для Docker)

docker build ПУТЬ | URL — создает образ с помощью Dockerfile
Параметры:

  • -t | —tag=»» — помечает созданный образ переданным названием (и, тэгом, если он будет передан)
  • —rm — Удаляет промежуточные контейнеры после успешной сборки (по умолчанию == true)

Управление образами

docker rmi — Удаляет образ, образ не может быть удален, если существуют контейнеры (даже незапущенные), которые основаны
на данном образе
Параметры:

  • -f — позволяет удалить образ даже если на нём основаны контейнеры

docker images — Отображает список всех существующих образов
Параметры:

  • -a | —all — отображает все образы (по умолчанию не отображает промежуточные контейнеры)
  • -q — отображает только id образов, вместо таблицы

Запуск и остановка контейнеров

docker run ОБРАЗ [КОМАНДА + АРГУМЕНТЫ] — Запускает выбранный образ в новом контейнере
Параметры:

  • -d | —detach — запускает контейнер в фоновом режиме и выводит только >false )
  • -i | —interactive — запускает контейнер в интерактивном режиме (оставляет STDIN открытым, даже если контейнер запущен в неприкрепленном режиме)
  • -t | —tty — запускает псевдотерминал, часто используется с -i
  • -p | —publish=[] — пробрасывает порты контейнера в хост. Формат: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort
  • -e | —env=[] — пробрасывает переменные окружения внутрь контейнера.
  • -v | —volume=[] — пробрасывает директорию файловой системы внутрь контейнера

docker stop КОНТЕЙНЕР — останавливает контейнер, передавая внутрь SIGTERM, а по истечении таймаута — SIGKILL

  • docker start КОНТЕЙНЕР — запускает остановленный контейнер.
    Параметры:
    • -i | —interactive — аналогично docker run -i
  • docker restart КОНТЕЙНЕР — Перезапускает выбранный контейнер с помощью docker stop и docker start
  • docker kill КОНТЕЙНЕР — Убивает контейнер, передавая внутрь SIGKILL
  • Управление контейнерами

    • docker port КОНТЕЙНЕР — отображает маппинг портов между хостом и контейнером
    • docker ps — отображает список запущенных контейнеров
      Параметры:
      • -a | —all=(true|false) — отображать ли все контейнеры. По умолчанию == false , т.е. отображаются только запущенные контейнеры
      • -q — отображает только ID контейнеров вместо таблицы
    • docker rm КОНТЕЙНЕР — удаляет контейнер. По умолчанию можно удалить только запущенный контейнер.
      Параметры:
      • -f | —force=(true|false) — позволяет удалить запущенный контейнер. Используется передача SIGKILL внутрь.
    • docker diff — отображает изменения относительно образа.

    Синтаксис Dockerfile

    Dockerfile служит скриптом сборки для команды docker build . Перед началом сборки docker передает сборщику всё содержимое папки с Dockerfile’ом,
    поэтому располагать его в корневой директории системы будет не лучшей идеей.

    Первая инструкция обязательно должна быть инструкцией FROM.

    FROM ОБРАЗ | FROM ОБРАЗ:ТЭГ — Задает базовый образ для последующих инструкций. Может встречаться несколько раз в одном Dockerfile,
    если необходимо собрать несколько образов за раз.

    MAINTAINER имя — Позволяет задать поле Author сгенерированного образа

    RUN команда | RUN [«исполняемый файл», «параметр1», «параметр2», ..] — Запускает команду на основе текущего образа и фиксирует изменения в новом образе. Новый образ будет использован для исполнения последующих инструкций. Первый синтаксис подразумевает запуск команд в стандартной оболочке (bin\sh -c)

    CMD [«исполняемый файл», «параметр1», «параметр2»] | CMD [«параметр1», «параметр2»] | CMD команда параметр1 параметр2 — Предоставляет значения по умолчанию для запуска контейнера. Эти значения могут как включать исполняемый файл (варианты 1, 3), так и не включать его (вариант 2). В последнем случае запускаемая команда
    должна быть задана с помощью инструкции ENTRYPOINT .

    EXPOSE порт — Информирует Docker, что контейнер будет прослушивать указанные порты во время исполнения. Docker может использовать эту информацию, чтобы соединять контейнеры между собой используя связи. EXPOSE сам по себе не делает порт доступным из хостовой системы. Для того, чтобы открыть порты в хостовую систему следует использовать флаг -p .

    ENV ключ значение — Позволяет задавать переменные окружения. Эти переменные будут использованы при запуске контейнера из собранного образа. Могут быть просмотрены с помощью команды docker inspect , а также переопределены с помощью флага —env команды docker run .

    ADD ОТКУДА КУДА — Используется для добавления новых файлов, директорий или ссылок на удалённые файлы в файловую систему контейнера. Несколько ОТКУДА может быть передано одновременно, но в этом случае все адреса должны быть относительны для директории, из которой происходит сборка. Каждый вхождение ОТКУДА может содержатьодин или несколько символов подстановки, которые будут разрешены с использование функции языка Go filepath.Match. КУДА должен быть абсолютным путем внутри контейнера.

    ENTRYPOINT [«исполняемый файл», «параметр1», «параметр2»] | ENTRYPOINT команда параметр1 параметр2 — позволяет сконфигурировать контейнер так, чтобы он запускался как исполняемый файл. В отличии от команды CMD значение не будет переопределено аргументами, переданными в команду docker run . Таким образом, аргументы из команды docker run будут переданы внутрь контейнера, т.е. docker run ОБРАЗ -d передаст -d исполняемому файлу.

    VOLUME [ПУТЬ] — создает точку монтирования с указанным именем и помечает её как содержащую подмонтированные разделы из хостовой системы или других контейнеров. Значение может быть задано как массив JSON, например, VOLUME [«/var/log/»] , так и как обычной строкой с одним или несколькими аргументами, например VOLUME /var/log или VOLUME /var/log /var/db

    USER имя — позволяет задавать имя пользователя или UID, который будет использован для запуска образа, а так же для любой из инструкций RUN

    WORKDIR ПУТЬ — задает рабочую директорию для команд RUN , CMD и ENTRYPOINT . Инструкция может быть использована несколько раз. Если ПУТЬ относителен, то он будет относительным для ПУТИ, заданным предыдущей инструкцией WORKDIR .

    Изучаем Docker, часть 2: термины и концепции

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

    Термины экосистемы Docker

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

    Механизмы Docker

    ▍Платформа Docker

    Платформа Docker (Docker Platform) — это программа, которая даёт нам возможность упаковывать приложения в контейнеры и запускать их на серверах. Платформа Docker позволяет помещать в контейнеры код и его зависимости. Как результат, системы, основанные на контейнерах, легко масштабировать, так как контейнеры можно переносить и воспроизводить.

    ▍Движок Docker

    Движок Docker (Docker Engine) — это клиент-серверное приложение. Компания Docker разделила движок Docker на два продукта. Docker Community Edition (CE) — это бесплатное ПО, во многом основанное на опенсорсных инструментах.

    Вероятно, вы будете пользоваться именно этой версией Docker. Docker Enterprise — это платная версия системы, дающая пользователям дополнительные возможности в области поддержки систем, управления ими и безопасности. Платная версия Docker даёт компании средства, необходимые для её существования.

    ▍Клиент Docker

    Клиент Docker и другие механизмы экосистемы (взято из документации)

    Клиент Docker (Docker Client) — это основное средство, которое используют для взаимодействия с Docker. Так, при работе с интерфейсом командной строки Docker (Docker Command Line Interface, CLI), в терминал вводят команды, начинающиеся с ключевого слова docker , обращаясь к клиенту. Затем клиент использует API Docker для отправки команд демону Docker.

    ▍Демон Docker

    Демон Docker (Docker Daemon) — это сервер Docker, который ожидает запросов к API Docker. Демон Docker управляет образами, контейнерами, сетями и томами.

    ▍Тома Docker

    Тома Docker (Docker Volumes) представляют собой наиболее предпочтительный механизм постоянного хранения данных, потребляемых или производимых приложениями.

    ▍Реестр Docker

    Реестр Docker (Docker Registry) представляет собой удалённую платформу, используемую для хранения образов Docker. В ходе работы с Docker образы отправляют в реестр и загружают из него. Подобный реестр может быть организован тем, кто пользуется Docker. Кроме того, поставщики облачных услуг могут поддерживать и собственные реестры. Например, это касается AWS и Google Cloud.

    ▍Хаб Docker

    Хаб Docker (Docker Hub) — это самый крупный реестр образов Docker. Кроме того, именно этот реестр используется при работе с Docker по умолчанию. Пользоваться хабом Docker можно бесплатно.

    ▍Репозиторий Docker

    Репозиторием Docker (Docker Repository) называют набор образов Docker, обладающих одинаковыми именами и разными тегами. Теги — это идентификаторы образов.

    Обычно в репозиториях хранятся разные версии одних и тех же образов. Например, Python — это имя популярнейшего официального репозитория Docker на хабе Docker. А вот Python:3.7-slim — это версия образа с тегом 3.7-slim в репозитории Python. В реестр можно отправить как целый репозиторий, так и отдельный образ.

    Теперь поговорим о терминах экосистемы Docker, имеющих отношение к масштабированию.

    Масштабирование решений, основанных на контейнерах

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

    ▍Сеть Docker

    Сетевые механизмы Docker (Docker Networking) позволяют организовывать связь между контейнерами Docker. Соединённые с помощью сети контейнеры могут выполняться на одном и том же хосте или на разных хостах. Подробности о сетевой подсистеме Docker можно почитать здесь.

    ▍Docker Compose

    Docker Compose — это инструмент, который упрощает развёртывание приложений, для работы которых требуется несколько контейнеров Docker. Docker Compose позволяет выполнять команды, описываемые в файле docker-compose.yml . Эти команды можно выполнять столько раз, сколько потребуется. Интерфейс командной строки Docker Compose упрощает взаимодействие с многоконтейнерными приложениями. Этот инструмент устанавливается при установке Docker.

    ▍Docker Swarm

    Docker Swarm — это решение, предназначенное для управления контейнерными развёртываниями (то есть, как говорят, для оркестрации контейнеров). В этом материале из официального учебного курса по Docker можно найти сведения о Docker Swarm. Мне хотелось бы порекомендовать вам не тратить время на изучение Docker Swarm в том случае, если у вас нет на то веской причины.

    ▍Сервисы Docker

    Сервисы Docker (Docker Services) — это различные части распределённого приложения. Вот что о них говорится в документации:

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

    Сервисы Docker позволяют масштабировать контейнеры в пределах нескольких демонов Docker, благодаря им существует и технология Docker Swarm.

    Краткий перечень терминов

    Давайте, буквально в двух словах, повторим только что представленные вам термины:

    1. Платформа Docker — ПО, благодаря которому можно работать с контейнерами.
    2. Движок Docker — клиент-серверное приложение (CE или Enterprise).
    3. Клиент Docker — программа, которая позволяет взаимодействовать с демоном Docker посредством CLI.
    4. Демон Docker — сервер Docker, отвечающий за управление ключевыми механизмами системы.
    5. Тома Docker — хранилище информации, используемое в контейнерах.
    6. Реестр Docker — удалённое хранилище образов.
    7. Хаб Docker — самый крупный реестр Docker, используемый по умолчанию.
    8. Репозиторий — коллекция образов Docker с одним и тем же именем.
    1. Сетевая подсистема Docker — среда, которая позволяет организовывать взаимодействие контейнеров.
    2. Docker Compose — технология, упрощающая работу с многоконтейнерными приложениями.
    3. Docker Swarm — средство для управления развёртыванием контейнеров.
    4. Сервисы Docker — контейнеры в продакшне.

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

    Вот, на всякий случай, ещё один пончик


    Этот термин относится не к самой платформе Docker, а к технологии, которая очень часто используется совместно с Docker.

    Kubernetes

    Kubernetes — это технология, которая позволяет автоматизировать развёртывание и масштабирование контейнеризированных приложений, а также управление ими. Это — бесспорный лидер рынка средств для оркестрации контейнеров. Если вам нужен инструмент для работы с группами контейнеров, для масштабирования решений, основанных на них, используйте не Docker Swarm, а Kubernetes. Kubernetes не является частью Docker. Они с Docker, скорее, похожи на лучших друзей.

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

    Итоги: печём пончики с Docker

    Помните, как в прошлый раз мы сравнивали платформу Docker с духовкой, которую устанавливают в кухне? Сейчас самое время установить Docker на вашей «кухне» и что-нибудь приготовить.

    Docker можно запускать локально на Linux, Mac и Windows. Если вы пользуетесь Mac или Windows, вы можете установить свежую версию Docker Desktop отсюда. Вместе с этой программой, кстати, устанавливается и Kubernetes. Если вы устанавливаете Docker на другой платформе, то загляните сюда для того, чтобы найти подходящую версию.

    После установки Docker взгляните на первые две части официального руководства.

    В следующий раз мы продолжим разговор о Docker. В частности, поговорим о файлах Dockerfile.

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

    Docker: практическое руководство для начинающих

    Перевод первой части статьи «Docker simplified: a hands-on guide for absolute beginners».

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

    В этом посте я постараюсь как можно более простым языком рассказать, что такое Docker.

    Итак, что такое Docker?

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

    Написан Docker на языке программирования Go, первая его версия была выпущена в 2013 году.

    В связи с богатством функционала, предлагаемого Docker, он широко применяется в ведущих мировых организациях и университетах (среди них – Visa, PayPal, Корнеллский университет и университет Индианы) для запуска и управления их приложениями.

    А теперь давайте разберемся, какая проблема стоит перед разработчиками и какое ее решение предлагает Docker

    Проблема

    Скажем, у вас есть три различных приложения на Python, которые вы планируете размещать на серверах (это могут быть физические или виртуальные машины).

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

    Поскольку мы не можем установить на одной машине разные версии Python, мы не можем и разместить на ней и все три приложения сразу.

    Решение

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

    Оба варианта позволят нам установить различные версии Python и пакеты зависимостей на каждой из этих машин.

    И при любом из этих вариантов расходы, связанные с приобретением и поддержкой «железа», будут довольно высокими.

    А теперь давайте рассмотрим вариант решения с помощью Docker и разберемся, почему оно более экономичное.

    Чтобы это понять, нужно вникнуть в то, как именно функционирует Docker.

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

    Машину, на которой установлен и запущен Docker, обычно называют Docker Host или просто «хост».

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

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

    Таким образом, ядро операционной системы хоста разделяется между всеми контейнерами, запущенными на нем.

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

    Короче говоря, вместо виртуализации компонентов «железа», Docker виртуализирует операционную систему хоста, на котором он установлен и запущен.

    Преимущества и недостатки использования Docker

    Основные преимущества применения Docker

    • Множественные приложения с различными требованиями и зависимостями могут располагаться вместе на одном хосте, если у них одинаковые требования к операционной системе.
    • Оптимизированное хранилище. На одном хосте может размещаться очень много приложений, поскольку контейнеры обычно занимают всего несколько мегабайт и потребляют очень мало дискового пространства.
    • Надежность. В контейнере нет отдельной операционной системы. Поэтому он потребляет очень мало памяти по сравнению с виртуальной машиной, где устанавливается и запускается ОС. Благодаря этому также снижается до нескольких секунд время загрузки, в то время как виртуальной машине на загрузку нужна пара минут.
    • Снижение расходов. Docker менее требователен относительно «железа», на котором он запускается.

    Недостатки использования Docker

    • Приложения с разными требованиями к операционной системе не могут размещаться на одном хосте Docker. Допустим, у нас есть четыре разных приложения, три из которых запускаются в Linux, а одно – в Windows. При таком сценарии первые три могут размещаться на одном хосте Docker, а для одного, которое нуждается в Windows, потребуется другой хост.

    Основные компоненты Docker

    Движок Docker (Docker Engine) это один из его ключевых компонентов. Он отвечает за функционирование платформы Docker в целом. По своей сути это клиент-серверное приложение, состоящее из трех основных компонентов:

    Сервер запускает демон под названием dockerd (Docker Daemon), являющийся просто процессом. Он отвечает за создание и управление образами Docker, контейнерами, сетями томами платформы Docker.

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

    Клиент это ни что иное как интерфейс командной строки, позволяющий пользователям взаимодействовать с Docker при помощи команд.

    Терминология Docker

    Давайте пробежимся по терминам, связанным с Docker.

    Образы Docker (Docker Images) и контейнеры Docker (Docker Containers) это две важных вещи, с которыми вы будете постоянно сталкиваться, работая с Docker.

    Говоря простыми словами, образ Docker это шаблон, содержащий приложение и все зависимости, необходимые для запуска этого приложения в Docker.

    А контейнер Docker это логическая сущность. Более конкретно – это запущенный экземпляр образа Docker.

    Что такое Docker Hub?

    Docker Hub это официальный онлайн-репозиторий, где вы можете найти все доступные для использования образы Docker.

    Docker Hub также позволяет нам хранить и при желании распространять наши собственные образы. Мы можем делать их публичными или приватными в зависимости от наших нужд.

    Пожалуйста, учтите, что при бесплатном использовании Docker Hub можно хранить приватно только один образ Docker. Если вам нужно больше, придется оформить платную подписку.

    Редакции Docker

    Docker доступен в двух редакциях:

    • Community Edition, CE (редакция сообщества)
    • Enterprise Edition, EE (корпоративная редакция)

    Community Edition подходит для отдельных разработчиков и маленьких команд. Эта редакция предоставляет ограниченный функционал по сравнению с Enterprise Edition.

    Enterprise Edition, в свою очередь, подходит для больших команд и для использования Docker в продакшен-среде.

    Enterprise Edition делится еще на три разных редакции:

    • Basic Edition
    • Standard Edition
    • Advanced Edition

    Установка Docker

    Прежде чем приступить к работе с Docker, давайте рассмотрим, как его устанавливать.

    Ниже даны ссылки на официальные руководства Docker по установке Community Edition. Они довольно простые, можете воспользоваться ими для установки Docker на вашу машину.

    Если вам лень устанавливать Docker или же у вас просто недостаточно свободных ресурсов на вашей машине для его установки, а поиграться хочется, – есть решение. Есть специальная онлайн-«песочница» – Play with Docker. Там пользователи могут попрактиковаться вводить команды, не устанавливая ничего на свою машину. Площадка проста в использовании и совершенно бесплатна.

    В следующей статье мы рассмотрим основные команды Docker, которые помогут вам начать работать с ним.

    [Перевод] Изучаем Docker, часть 2: термины и концепции 13.02.2020 12:48

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

    Термины экосистемы Docker

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

    Механизмы Docker

    ▍Платформа Docker

    Платформа Docker (Docker Platform) — это программа, которая даёт нам возможность упаковывать приложения в контейнеры и запускать их на серверах. Платформа Docker позволяет помещать в контейнеры код и его зависимости. Как результат, системы, основанные на контейнерах, легко масштабировать, так как контейнеры можно переносить и воспроизводить.

    ▍Движок Docker

    Движок Docker (Docker Engine) — это клиент-серверное приложение. Компания Docker разделила движок Docker на два продукта. Docker Community Edition (CE) — это бесплатное ПО, во многом основанное на опенсорсных инструментах.

    Вероятно, вы будете пользоваться именно этой версией Docker. Docker Enterprise — это платная версия системы, дающая пользователям дополнительные возможности в области поддержки систем, управления ими и безопасности. Платная версия Docker даёт компании средства, необходимые для её существования.

    ▍Клиент Docker

    Клиент Docker и другие механизмы экосистемы (взято из документации)

    Клиент Docker (Docker Client) — это основное средство, которое используют для взаимодействия с Docker. Так, при работе с интерфейсом командной строки Docker (Docker Command Line Interface, CLI), в терминал вводят команды, начинающиеся с ключевого слова docker , обращаясь к клиенту. Затем клиент использует API Docker для отправки команд демону Docker.

    ▍Демон Docker

    Демон Docker (Docker Daemon) — это сервер Docker, который ожидает запросов к API Docker. Демон Docker управляет образами, контейнерами, сетями и томами.

    ▍Тома Docker

    Тома Docker (Docker Volumes) представляют собой наиболее предпочтительный механизм постоянного хранения данных, потребляемых или производимых приложениями.

    ▍Реестр Docker

    Реестр Docker (Docker Registry) представляет собой удалённую платформу, используемую для хранения образов Docker. В ходе работы с Docker образы отправляют в реестр и загружают из него. Подобный реестр может быть организован тем, кто пользуется Docker. Кроме того, поставщики облачных услуг могут поддерживать и собственные реестры. Например, это касается AWS и Google Cloud.

    ▍Хаб Docker

    Хаб Docker (Docker Hub) — это самый крупный реестр образов Docker. Кроме того, именно этот реестр используется при работе с Docker по умолчанию. Пользоваться хабом Docker можно бесплатно.

    ▍Репозиторий Docker


    Репозиторием Docker (Docker Repository) называют набор образов Docker, обладающих одинаковыми именами и разными тегами. Теги — это идентификаторы образов.

    Обычно в репозиториях хранятся разные версии одних и тех же образов. Например, Python — это имя популярнейшего официального репозитория Docker на хабе Docker. А вот Python:3.7-slim — это версия образа с тегом 3.7-slim в репозитории Python. В реестр можно отправить как целый репозиторий, так и отдельный образ.

    Теперь поговорим о терминах экосистемы Docker, имеющих отношение к масштабированию.

    Масштабирование решений, основанных на контейнерах

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

    ▍Сеть Docker

    Сеть Docker (взято из документации)

    Сетевые механизмы Docker (Docker Networking) позволяют организовывать связь между контейнерами Docker. Соединённые с помощью сети контейнеры могут выполняться на одном и том же хосте или на разных хостах. Подробности о сетевой подсистеме Docker можно почитать здесь.

    ▍Docker Compose

    Docker Compose — это инструмент, который упрощает развёртывание приложений, для работы которых требуется несколько контейнеров Docker. Docker Compose позволяет выполнять команды, описываемые в файле docker-compose.yml . Эти команды можно выполнять столько раз, сколько потребуется. Интерфейс командной строки Docker Compose упрощает взаимодействие с многоконтейнерными приложениями. Этот инструмент устанавливается при установке Docker.

    ▍Docker Swarm

    Docker Swarm — это решение, предназначенное для управления контейнерными развёртываниями (то есть, как говорят, для оркестрации контейнеров). В этом материале из официального учебного курса по Docker можно найти сведения о Docker Swarm. Мне хотелось бы порекомендовать вам не тратить время на изучение Docker Swarm в том случае, если у вас нет на то веской причины.

    ▍Сервисы Docker

    Сервисы Docker (Docker Services) — это различные части распределённого приложения. Вот что о них говорится в документации:

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

    Сервисы Docker позволяют масштабировать контейнеры в пределах нескольких демонов Docker, благодаря им существует и технология Docker Swarm.

    Краткий перечень терминов

    Давайте, буквально в двух словах, повторим только что представленные вам термины:

    1. Платформа Docker — ПО, благодаря которому можно работать с контейнерами.
    2. Движок Docker — клиент-серверное приложение (CE или Enterprise).
    3. Клиент Docker — программа, которая позволяет взаимодействовать с демоном Docker посредством CLI.
    4. Демон Docker — сервер Docker, отвечающий за управление ключевыми механизмами системы.
    5. Тома Docker — хранилище информации, используемое в контейнерах.
    6. Реестр Docker — удалённое хранилище образов.
    7. Хаб Docker — самый крупный реестр Docker, используемый по умолчанию.
    8. Репозиторий — коллекция образов Docker с одним и тем же именем.
    1. Сетевая подсистема Docker — среда, которая позволяет организовывать взаимодействие контейнеров.
    2. Docker Compose — технология, упрощающая работу с многоконтейнерными приложениями.
    3. Docker Swarm — средство для управления развёртыванием контейнеров.
    4. Сервисы Docker — контейнеры в продакшне.
    Мастер Йода рекомендует:  песочница — всё по этой теме для программистов

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

    Вот, на всякий случай, ещё один пончик

    Этот термин относится не к самой платформе Docker, а к технологии, которая очень часто используется совместно с Docker.

    Kubernetes

    Kubernetes — это технология, которая позволяет автоматизировать развёртывание и масштабирование контейнеризированных приложений, а также управление ими. Это — бесспорный лидер рынка средств для оркестрации контейнеров. Если вам нужен инструмент для работы с группами контейнеров, для масштабирования решений, основанных на них, используйте не Docker Swarm, а Kubernetes. Kubernetes не является частью Docker. Они с Docker, скорее, похожи на лучших друзей.

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

    Итоги: печём пончики с Docker

    Помните, как в прошлый раз мы сравнивали платформу Docker с духовкой, которую устанавливают в кухне? Сейчас самое время установить Docker на вашей «кухне» и что-нибудь приготовить.

    Docker можно запускать локально на Linux, Mac и Windows. Если вы пользуетесь Mac или Windows, вы можете установить свежую версию Docker Desktop отсюда. Вместе с этой программой, кстати, устанавливается и Kubernetes. Если вы устанавливаете Docker на другой платформе, то загляните сюда для того, чтобы найти подходящую версию.

    После установки Docker взгляните на первые две части официального руководства.

    В следующий раз мы продолжим разговор о Docker. В частности, поговорим о файлах Dockerfile.

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

    Как и для чего использовать Docker

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

    Содержание

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

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

    Установка

    Докер поставляется в виде Community Edition (CE) и Enterprise Edition (EE). Нас интересует CE. На главной странице этой версии доступны ссылки для скачивания под все популярные платформы. Выберите вашу и установите Докер.

    В работе Докера есть одна деталь, которую важно знать при установке на Mac и Linux. По умолчанию Докер работает через unix сокет. В целях безопасности сокет закрыт для пользователей, не входящих в группу docker. И хотя установщик добавляет текущего пользователя в эту группу автоматически, Докер сразу не заработает. Дело в том, что если пользователь меняет группу сам себе, то ничего не изменится до тех пор, пока пользователь не перелогинится. Такова особенность работы ядра. Для проверки того, в какие группы входит ваш пользователь, можно набрать команду id .

    Проверить успешность установки можно командой docker info :

    Она выдает довольно много информации о конфигурации самого Докера и статистику работы.

    Запуск

    На этом этапе команды на выполнение даются “как есть” без объяснения деталей. Подробнее о том, как их формировать и что в них входит разбирается позже.

    Начнем с самого простого варианта:

    При первом вызове данная команда начнет скачивать образ (image) nginx, поэтому придется немного подождать. После того, как образ скачается, запустится bash, и вы окажетесь внутри контейнера (container).

    Побродите по файловой системе, посмотрите папку /etc/nginx . Как видите, её содержимое не совпадает с тем, что находится у вас на компьютере. Эта файловая система появилась из образа nginx. Все, что вы сделаете здесь внутри, никак не затронет вашу основную файловую систему. Вернуться в родные скрепы можно командой exit .

    Теперь посмотрим вариант вызова команды cat , выполненной уже в другом контейнере, но тоже запущенном из образа nginx:

    Команда выполняется практически мгновенно, так как образ уже загружен. В отличие от предыдущего старта, где запускается баш и начинается интерактивная сессия внутри контейнера, запуск команды cat /etc/nginx/nginx.conf для образа nginx выведет на экран содержимое указанного файла (взяв его из файловой системы запущенного контейнера) и вернет управление в то место, где вы были. Вы не окажетесь внутри контейнера.

    Последний вариант запуска будет таким:

    Данная команда не возвращает управление, потому что стартует nginx. Откройте браузер и наберите localhost:8080 . Вы увидите как загрузилась страница Welcome to nginx!. Если в этот момент снова посмотреть в консоль, где был запущен контейнер, то можно увидеть, что туда выводится лог запросов к localhost:8080 . Остановить nginx можно командой Ctrl + C .

    Несмотря на то, что все запуски выполнялись по-разному и приводили к разным результатам, общая схема их работы — одна. Докер при необходимости автоматически скачивает образ (первый аргумент после docker run ) и на основе него стартует контейнер с указанной командой.

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

    Контейнер — запущенный процесс операционной системы в изолированном окружении с подключенной файловой системой из образа.

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

    Попробуйте выполнить команду docker run -it ubuntu bash и наберите ps auxf внутри запущенного контейнера. Вывод будет таким:

    Как видно, процесса всего два, и у Bash P >/home командой ls /home и убедиться, что она пустая. Также обратите внимание, что внутри контейнера по умолчанию используется пользователь root .

    Зачем все это?

    Докер — универсальный способ доставки приложений на машины (локальный компьютер или удаленные сервера) и их запуск в изолированном окружении.

    Вспомните, когда вам приходилось собирать программы из исходников. Этот процесс включает в себя следующие шаги:

    • Установить все необходимые зависимости под вашу операционную систему (их список еще надо найти).
    • Скачать архив, распаковать.
    • Запустить конфигурирование make configure .
    • Запустить компиляцию make compile .
    • Установить make install .

    Как видите, процесс нетривиальный и далеко не всегда быстрый. Иногда даже невыполнимый из-за непонятных ошибок. И это не говоря про загрязнение операционной системы.

    Докер позволяет упростить эту процедуру до запуска одной команды причем с почти 100% гарантией успеха. Посмотрите на вымышленный пример, в котором происходит установка программы Tunnel на локальный компьютер в папку /usr/local/bin используя образ tunnel:

    Запуск этой команды приводит к тому, что в основной системе в папке /usr/local/bin оказывается исполняемый файл программы, находящейся внутри образа tunnel. Команда docker run запускает контейнер из образа tunnel, внутри происходит компиляция программы и, в конечном итоге, она оказывается в папке /usr/local/bin основной файловой системы. Теперь можно стартовать программу, просто набрав tunnel в терминале.

    А что если программа, которую мы устанавливаем таким способом, имеет зависимости? Весь фокус в том, что образ, из которого был запущен контейнер, полностью укомплектован. Внутри него установлены все необходимые зависимости и его запуск практически гарантирует 100% работоспособность независимо от состояния основной ОС.

    Часто даже не обязательно копировать программу из контейнера на вашу основную систему. Достаточно запускать сам контейнер когда в этом возникнет необходимость. Предположим, что мы решили разработать статический сайт на основе Jekyll. Jekyll — популярный генератор статических сайтов, написанный на Ruby. Например, гайд который вы читаете прямо сейчас, находится на статическом сайте, сгенерированном с его помощью. И при его генерации использовался Докер (об этом можно прочитать в гайде: как делать блог на Jekyll).

    Старый способ использования Jekyll требовал установки на вашу основную систему как минимум Ruby и самого Jekyll в виде гема (gem — название пакетов в Ruby). Причем, как и всегда в подобных вещах, Jekyll работает только с определенными версиями Ruby, что вносит свои проблемы при настройке.

    С Докером запуск Jekyll сводится к одной команде, выполняемой в папке с блогом (подробнее можно посмотреть в репозитории наших гайдов):

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

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

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

    Но в какой-то момент все изменилось. Картинка стоит тысячи слов:

    Контейнеры уровняли все виды грузов и стандартизировали инструменты погрузки и разгрузки во всем мире. Что в свою очередь привело к упрощению процессов, ускорению и, следовательно, понижению стоимости.

    То же самое произошло и в разработке ПО. Docker стал универсальным средством доставки софта независимо от его структуры, зависимостей и способа установки. Все, что нужно программам, распространяемым через Докер, находится внутри образа и не пересекается с основной системой и другими контейнерами. Важность этого факта невозможно переоценить. Теперь обновление версий программ никак не задействует ни саму систему, ни другие программы. Сломаться больше ничего не может. Все, что нужно сделать, это скачать новый образ той программы, которую требуется обновить. Другими словами, Докер убрал проблему dependency hell и сделал инфраструктуру immutable (неизменяемой).

    Больше всего Docker повлиял именно на серверную инфраструктуру. До эры Докера управление серверами было очень болезненным мероприятием даже не смотря на наличие программ по управлению конфигурацией (chef, puppet, ansible). Основная причина всех проблем — изменяемое состояние. Программы ставятся, обновляются, удаляются. Происходит это в разное время на разных серверах и немного по разному. Например, обновить версию таких языков, как PHP, Ruby или Python могло стать целым приключением с потерей работоспособности. Проще поставить рядом новый сервер и переключиться на него. Идейно Докер позволяет сделать именно такое переключение. Забыть про старое и поставить новое, ведь каждый запущенный контейнер живет в своем окружении. Причем, откат в такой системе тривиален: все что нужно — остановить новый контейнер и поднять старый, на базе предыдущего образа.

    Приложение в контейнере

    Теперь поговорим о том, как приложение отображается на контейнеры. Возможны два подхода:

    1. Все приложение — один контейнер, внутри которого поднимается дерево процессов: приложение, веб сервер, база данных и все в этом духе.
    2. Каждый запущенный контейнер — атомарный сервис. Другими словами каждый контейнер представляет из себя ровно одну программу, будь-то веб-сервер или приложение.

    На практике все преимущества Docker достигаются только со вторым подходом. Во-первых, сервисы, как правило, разнесены по разным машинам и нередко перемещаются по ним (например, в случае выхода из строя сервера), во-вторых, обновление одного сервиса, не должно приводить к остановке остальных.

    Первый подход крайне редко, но бывает нужен. Например, Хекслет работает в двух режимах. Сам сайт с его сервисами использует вторую модель, когда каждый сервис отдельно, но вот практика, выполняемая в браузере, стартует по принципу один пользователь — один контейнер. Внутри контейнера может оказаться все, что угодно в зависимости от практики. Как минимум, там всегда стартует сама среда Хекслет IDE, а она в свою очередь порождает терминалы (процессы). В курсе по базам данных в этом же контейнере стартует и база данных, в курсе, связанном с вебом, стартует веб-сервер. Такой подход позволяет создать иллюзию работы на настоящей машине и резко снижает сложность в поддержке упражнений. Повторюсь, что такой вариант использования очень специфичен и вам вряд ли понадобится.

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

    Работа с образами

    Docker — больше, чем просто программа. Это целая экосистема со множеством проектов и сервисов. Главный сервис, с которым вам придется иметь дело — Registry. Хранилище образов.

    Концептуально оно работает так же, как и репозиторий пакетов любого пакетного менеджера. Посмотреть его содержимое можно на сайте https://store.docker.com/ (либо по старому адресу https://hub.docker.com/), кликнув по ссылке Containers.

    Когда мы выполняем команду run docker run , то Docker проверяет наличие указанного образа на локальной машине и скачивает его по необходимости. Список образов, уже скачанных на компьютер, можно посмотреть командой docker images :

    Разберемся с тем, как формируется имя образа, и что оно в себя включает.

    Вторая колонка в выводе выше называется TAG. Когда мы выполняли команду docker run nginx , то на самом деле выполнялась команда docker run nginx:latest . То есть мы не просто скачиваем образ nginx, а скачиваем его конкретную версию. Latest — тег по умолчанию. Несложно догадаться что он означает последнюю версию образа.

    Важно понимать что это всего лишь соглашение, а не правило. Конкретный образ вообще может не иметь тега latest, либо иметь, но он не будет содержать последние изменения, просто потому что никто их не публикует. Впрочем, популярные образы следуют соглашению. Как понятно из контекста, теги в Докере изменяемы, другими словами, вам никто не гарантирует, что скачав образ с одним и тем же тегом на разных компьютерах в разное время вы получите одно и тоже. Такой подход может показаться странным и ненадежным, ведь нет гарантий, но на практике есть определенные соглашения, которым следуют все популярные образы. Тег latest действительно всегда содержит последнюю версию и постоянно обновляется, но кроме этого тега активно используется семантическое версионирование. Рассмотрим https://store.docker.com/images/nginx

    Теги, в которых присутствует полная семантическая версия (x.x.x) всегда неизменяемы, даже если в них встречается что то еще, например 1.12.2-alphine. Такую версию смело нужно брать для продакшен-окружения. Теги, подобные такому 1.12, обновляются при изменении path версии. То есть внутри образа может оказаться и версия 1.12.2 и в будущем 1.12.8. Точно такая же схема и с версиями, в которых указана только мажорная версия, например 1. Только в данном случае обновление идет не только по патчу, но и по минорной версии.

    Как вы помните, команда docker run скачивает образ если его нет локально, но эта проверка не связана с обновлением содержимого. Другими словами, если nginx:latest обновился, то docker run его не будет скачивать, он использует тот latest, который прямо сейчас уже загружен. Для гарантированного обновления образа существует другая команда: docker pull . Вот она всегда проверяет обновился ли образ для определенного тега.

    Кроме тегов имя образа может содержать префикс: например, etsy/chef . Этот префикс является именем аккаунта на сайте, через который создаются образы, попадающие в Registry. Большинство образов как раз такие, с префиксом. И есть небольшой набор, буквально сотня образов, которые не имеют префикса. Их особенность в том, что эти образы поддерживает сам Docker. Поэтому если вы видите, что в имени образа нет префикса, значит это официальный образ. Список таких образов можно увидеть здесь: https://github.com/docker-library/official-images/tree/master/library

    Удаляются образы командой docker rmi .

    Если в Докере присутствует хоть один контейнер из удаляемого образа, то Докер не даст его удалить по понятным причинам. Если вы все же хотите удалить и образ и все контейнеры связанные с ним, то используйте флаг -f .

    Управление контейнерами


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

    Проследите путь команды docker run . Несмотря на то, что команда одна, с точки зрения работы Докера выполняется два действия: создание контейнера и запуск. Существуют и более сложные варианты исполнения, но в этом разделе мы рассмотрим только базовые команды.

    Запустим nginx так, чтобы он работал в фоне. Для этого после слова run добавляется флаг -d :

    После её выполнения Докер выводит идентификатор контейнера и возвращает управление. Убедитесь в том, что nginx работает, открыв в браузере ссылку localhost:8080 . В отличие от предыдущего запуска, наш nginx работает в фоне, а значит не видно его вывода (логов). Посмотреть его можно командой docker logs , которой нужно передать идентификатор контейнера:

    Вы так же можете подсоединиться к выводу лога в стиле tail -f . Для этого запустите docker logs -f 431a3b3fc24bf8440efe2bca5bbb837944d5ae5c3b23b9b33a5575cb3566444e . Теперь лог будет обновляться каждый раз, когда вы обновляете страницу в браузере. Выйти из этого режима можно набрав Ctrl + C , при этом сам контейнер остановлен не будет.

    Теперь выведем информацию о запущенных контейнерах командой docker ps :

    • CONTAINER_ID — идентификатор контейнера. Так же, как и в git, используется сокращенная запись хеша.
    • IMAGE — имя образа, из которого был поднят контейнер. Если не указан тег, то подразумевается latest.
    • COMMAND — команда, которая выполнилась на самом деле при старте контейнера.
    • CREATED — время создания контейнера
    • STATUS — текущее состояние.
    • PORTS — проброс портов.
    • NAMES — алиас. Докер позволяет кроме идентификатора иметь имя. Так гораздо проще обращаться с контейнером. Если при создании контейнера имя не указано, то Докер самостоятельно его придумывает. В выводе выше как раз такое имя у nginx.

    (Команда docker stats выводит информацию о том, сколько ресурсов потребляют запущенные контейнеры).

    Теперь попробуем остановить контейнер. Выполним команду:

    Если попробовать набрать docker ps , то там этого контейнера больше нет. Он удален.

    Команда docker ps выводит только запущенные контейнеры. Но кроме них могут быть и остановленные. Причем, остановка может происходить как и по успешному завершению так и в случае ошибок. Попробуйте набрать docker run ubuntu ls , а затем docker run ubuntu bash -c «unknown» . Эти команды не запускают долго живущего процесса, они завершаются сразу по выполнению, причем вторая с ошибкой, так как такой команды не существует.

    Теперь выведем все контейнеры командой docker ps -a . Первыми тремя строчками вывода окажутся:

    Здесь как раз два последних наших запуска. Если посмотреть на колонку STATUS, то видно, что оба контейнера находятся в состоянии Exited. То есть запущенная команда внутри них выполнилась, и они остановились. Разница лишь в том, что один завершился успешно (0), а второй с ошибкой (127). После остановки контейнер можно даже перезапустить:

    Только в этот раз вы не увидите вывод. Чтобы его посмотреть воспользуйтесь командой docker logs determined_tereshkova .

    Взаимодействие с другими частями системы

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

    Interactive mode

    Самый простой вариант использования Докера, как мы уже убедились — поднять контейнер и выполнить внутри него какую либо команду:

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

    Дело в том, что bash запускает интерактивную сессию внутри контейнера. Для взаимодействия с ней нужно оставить открытым поток STDIN и запустить TTY (псевдо-терминал). Поэтому для запуска интерактивных сессий нужно не забыть добавить опции -i и -t . Как правило их добавляют сразу вместе как -it . Поэтому правильный способ запуска баша выглядит так: docker run -it ubuntu bash .

    Ports

    Если запустить nginx такой командой docker run nginx , то nginx не сможет принять ни один запрос, несмотря на то, что внутри контейнера он слушает 80 порт (напомню, что каждый контейнер по умолчанию живет в своей собственной сети). Но если запустить его так docker run -p 8080:80 nginx , то nginx начнет отвечать на порту 8080.

    Флаг -p позволяет описывать как и какой порт выставить наружу. Формат записи 8080:80 расшифровывается так: пробросить порт 8080 снаружи контейнера в контейнер на порт 80. Причем, по умолчанию, порт 8080 слушается на 0.0.0.0 , то есть на всех доступных интерфейсах. Поэтому запущенный таким образом контейнер доступен не только через localhost:8080 , но и снаружи машины (если доступ не запрещен как нибудь еще). Если нужно выполнить проброс только на loopback, то команда меняется на такую: docker run -p 127.0.0.1:8080:80 nginx .

    Docker позволяет пробрасывать столько портов, сколько нужно. Например, в случае nginx часто требуется использовать и 80 порт и 443 для HTTPS. Сделать это можно так: docker run -p 80:80 -p 443:443 nginx Про остальные способы пробрасывать порты можно прочитать в официальной документации.

    Volumes

    Другая частая задача связана с доступом к основной файловой системе. Например, при старте nginx-контейнера ему можно указать конфигурацию, лежащую на основной фс. Докер прокинет её во внутреннюю фс, и nginx сможет её читать и использовать.

    Проброс осуществляется с помощью опции -v . Вот как можно запустить баш сессию из образа Ubuntu, подключив туда историю команд с основной файловой системы: docker run -it -v

    /.bash_history:/root/.bash_history ubuntu bash . Если в открытом баш понажимать стрелку вверх, то отобразится история. Пробрасывать можно как файлы так и папки. Любые изменения производимые внутри volume меняются как внутри контейнера, так и снаружи, причем по умолчанию доступны любые операции. Как и в случае портов, количество пробрасываемых файлов и директорий может быть любым.

    При работе с Volumes есть несколько важных правил, которые надо знать:

    • Путь до файла во внешней системе должен быть абсолютным.
    • Если внутренний путь (то, что идет после : ) не существует, то Докер создаст все необходимые папки и файл. Если существует, то заменит старое тем, что было проброшено.

    Кроме пробрасывания части фс снаружи, Докер предоставляет еще несколько вариантов создания и использования Volumes. Подробнее — в официальной документации.

    Переменные окружения

    Конфигурирование приложения внутри контейнера, как правило, осуществляется с помощью переменных окружения в соответствии с 12factors. Существует два способа их установки:

    • Флаг -e . Используется он так: docker run -it -e «HOME=/tmp» ubuntu bash
    • Специальный файл, содержащий определения переменных окружения, который пробрасывается внутрь контейнера опцией —env-file .

    Подготовка собственного образа

    Создание и публикация собственного образа не сложнее его использования. Весь процесс делится на три шага:

    • Создается файл Dockerfile в корне проекта. Внутри описывается процесс создания образа.
    • Выполняется сборка образа командой docker build
    • Выполняется публикация образа в Registry командой docker push

    Рассмотрим процесс создания образа на примере упаковки линтера eslint (не забудьте повторить его самостоятельно). В результате сборки, мы получим образ, который можно использовать так:

    То есть достаточно запустить контейнер из этого образа, подключив папку с файлами js для проверки как Volume во внутреннюю папку /app .

    1. Конечная структура папки, на основе файлов которой соберется образ, выглядит так:

    Файл eslintrc.yml содержит конфигурацию линтера. Он автоматически прочитывается если лежит в домашней директории под именем .eslintrc.yml . То есть этот файл должен попасть под таким именем в папку /root внутрь образа.

    2. Создание Dockerfile

    Dockerfile имеет довольно простой формат. На каждой строчке указывается инструкция (директива) и её описание.

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

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

    Основная инструкция в Dockerfile. Фактически здесь указывается sh команда, которая будет выполнена в рамках окружения, указанного во FROM при сборке образа. Так как по умолчанию все выполняется от пользователя root, то использовать sudo не нужно (и скорее всего его нет в базовом образе). К тому же учтите, что сборка образа — процесс не интерактивный. В тех ситуациях, когда вы используете команду, которая может запросить что-то от пользователя, необходимо подавлять этот вывод. Например, в случае пакетных менеджеров делают так: apt-get install -y curl . Флаг -y как раз говорит о том что нужно производиться установку без дополнительных вопросов.

    Технически образ Докера — это не один файл, а набор так называемых слоев. Каждый вызов RUN формирует новый слой, который можно представить как набор файлов, созданных и измененных (в том числе удаленных) командой, указанной в RUN. Такой подход позволяет значительно улучшить производительность системы, задействовав кеширование слоев, которые не поменялись. С другой стороны, Докер переиспользует слои в разных образах если они идентичны, что сокращает и скорость загрузки и занимаемое пространство на диске. Тема кеширования слоев довольно важная при активном использовании Докера. Для её эффективной работы нужно понимать как она устроена и как правильно описывать инструкции RUN для максимальной утилизации.

    В соответствии со своим названием команда COPY берет файл или папку из основной файловой системы и копирует её внутрь образа. У команды есть ограничение. То, что копируется, должно лежать в той же папке, где и Dockerfile. Именно эту команду используют при разработке когда необходимо упаковать приложение внутрь образа.

    WORKDIR

    Инструкция, устанавливающая рабочую директорию. Все последующие инструкции будут считать, что они выполняются именно внутри указанной папки. По сути она действует как команда cd . Кроме того, когда мы запускаем контейнер, то он также стартует из папки WORKDIR. Например, запустив bash вы окажетесь внутри неё.

    Та самая инструкция, определяющая действие по умолчанию при использовании docker run . Она используется только в том случае, если контейнер был запущен без указания команды, иначе она игнорируется.

    3. Сборка

    Для сборки образа используется команда docker build . С помощью флага -t передается имя образа, включая имя аккаунта и тег. Как обычно, если не указывать тег, то подставляется latest.

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

    4. Публикация

    Для успешного выполнения публикации нужно соблюсти два условия:

    • Зарегистрироваться на Docker Cloud и создать там репозиторий для образа.
    • Залогиниться в cli интерфейсе используя команду docker login .

    Docker Compose

    Docker Compose — продукт, позволяющий разрабатывать проект локально используя Докер. По решаемым задачам его можно сравнивать с Vagrant.

    Docker Compose позволяет управлять набором контейнеров, каждый из которых представляет из себя один сервис проекта. Управление включает в себя сборку, запуск с учетом зависимостей и конфигурацию. Конфигурация Docker Compose описывается в файле docker-compose.yml , лежащем в корне проекта, и выглядит примерно так:

    В бою

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

    1. Скачать новый образ.
    2. Остановить старый контейнер.
    3. Поднять новый контейнер.

    Причем, данный порядок действий не зависит от стека технологий. Выполнять деплой можно (как и настройку машин) с помощью Ansible.

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

    Докер под капотом

    Изоляция, которую предоставляет Докер, достигается благодаря возможностям ядра Cgroups и Namespaces. Они позволяют запускать процесс операционной системы не только в изолированном окружении, но и с ограничением по использованию физических ресурсов, таких как памяти или процессора.

    Мастер Йода рекомендует:  Логическая задача на взвешивание

    Введение в контейнеры, VM и Docker для новичков

    Если вы являетесь программистом или техником, то вы наверняка хотя бы слышали о Docker — полезном инструменте для упаковки, отправки и запуска приложений в «контейнерах». Трудно не знать об этой вещи, ведь в последнее время она получает много внимания от всех, начиная от разработчиков и заканчивая сисадминами. Даже такие крупные шишки, как Google, VMware и Amazon создают сервисы, поддерживающие Docker.

    Независимо от того, использовали ли вы уже Docker или нет, я думаю, важно понять некоторые фундаментальные концепции того, что такое «контейнер», и сопоставить его с виртуальной машиной (VM). В то время как Интернет полон отличных руководств по использованию Docker, я не смог найти понятных для начинающих руководств о концепции, особенно о том, из чего состоит контейнер. Итак, надеюсь, этот пост решит эту проблему!

    Давайте начнем с понимания того, что такое виртуальные машины и контейнеры.

    Что такое «контейнеры» и «VM»?

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

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

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

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

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

    Давайте разберемся с жаргоном:

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

    Виртуальная машина, работающая на хосте (опять же, с использованием гипервизора), также часто называется «гостевой машиной». Этот гостевой компьютер содержит как приложение, так и все, что ему нужно для его запуска (например, системные двоичные файлы и библиотеки). Он также включает в себя весь собственный виртуализированный аппаратный стек (в него входят виртуализированные сетевые адаптеры, хранилище и процессор). Это означает, что у него также есть своя полноценная гостевая операционная система. Изнутри гостевая машина ведет себя как отдельное устройство с собственными ресурсами. С точки зрения извне, мы знаем, что это VM-ресурсы совместного доступа, предоставляемые хост-машиной.

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

    Во-первых, хостовый гипервизор виртуализации работает на операционной системе хост-машины. Например, компьютер с OSX может иметь виртуальную машину (например, VirtualBox или VMware Workstation 8), установленную «поверх» этой ОС. У VM нет прямого доступа к аппаратным средствам, поэтому она должна проходить через операционную систему хоста (в нашем случае — Mac OSX).

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

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

    После этого разговора о гипервизорах вам могло стать интересно, почему нам нужен этот дополнительный слой гипервизора между виртуальной машиной и машиной-хостом.

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

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

    Контейнеры

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

    С точки зрения всех целей и задач контейнеры ничем не отличаются от виртуальных машин. Например, они могут иметь личное пространство для обработки, выполнять команды, такие как root, иметь частный сетевой интерфейс и IP-адрес, разрешать кастомные маршруты и правила iptable, монтировать файловые системы и т. д.

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

    На этой диаграмме показано, что контейнеры содержат только пользовательское пространство, а не ядро или виртуальное оборудование, как в случае с VM. Каждый контейнер Docker получает свое изолированное пользовательское пространство, позволяющее нескольким контейнерам запускаться на одном хосте. Мы видим, что вся архитектура ОС делится между контейнерами. С нуля создаются только файлы bin, lib. Именно поэтому контейнеры такие легкие.


    Когда же в дело вступает Docker?

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

    Контейнеры — это не новое изобретение. Google использует собственные технологии контейнеров уже многие годы. Другие технологии контейнеров на Linux включают в себя Solaris Zones, BSD jails и LXC, которые существуют уже много лет.

    Так почему же Docker внезапно набирает обороты?

    1. Простота использования: Docker упростил для всех (разработчиков, системных администраторов, архитекторов и других) использование контейнеров для быстрой сборки и тестирования портативных приложений. Это позволяет кому угодно передавать приложение на свой ноутбук. Такое приложение, в свою очередь, может работать без изменений в любом общедоступном облаке, в частном облаке или даже на чистом сервере. Девиз таков: «Создайте один раз, запускайте откуда угодно»;
    2. Скорость: Контейнеры в Docker очень легкие и быстрые. Поскольку контейнеры — это помещенные в «песочницу» среды, работающие на ядре, они потребляют меньше ресурсов. На создание и запуск Docker контейнеров тратятся мгновения по сравнению с VM. Работа с ними может занять больше времени, потому что каждый раз они должны загружать полную виртуальную ОС;
    3. Docker Hub: Пользователи Docker также получают выгоду от все больше богатеющей экосистемы Docker Hub, которую вы можете назвать «магазином приложений для образов Docker». Docker Hub содержит десятки тысяч общедоступных образов, созданных сообществом. Они легко доступны для использования. Теперь невероятно легко найти образы, которые отвечают вашим потребностям. Их уже можно взять и использовать практически без изменений;
    4. Модульность и масштабируемость: Docker позволяет легко разбить функциональность вашего приложения на отдельные контейнеры. Например, ваша база данных Postgres может работать в одном контейнере, а сервер Redis — в другом, приложение Node.js — в третьем. С Docker стало проще связать эти контейнеры вместе для создания приложения. В будущем это упростит масштабирование или обновление компонентов независимо друг от друга.

    И наконец: кто же не любит кита Docker?

    Фундаментальные Docker концепции

    Раз уж мы разобрались с основной картиной, можно перейти к фундаментальным частям Docker.

    Docker Engine

    Docker Engine — это слой, на котором работает Docker. Это легкая среда и набор инструментов, которые позволяют осуществлять управление контейнерами, образами, версиями и многим другим. По умолчанию эта часть работает на системах Linux и состоит из:

    • Docker Daemon (работает на хосте);
    • Docker Client (связывается с Docker Daemon, чтобы осуществлять команды);
    • REST API (для удаленного взаимодействия с Docker Daemon).

    Docker Client

    Клиент Docker — то, с чем вы, конечный пользователь Docker, взаимодействуете. Вы можете представить его как интерфейс Docker. Например, когда вы задаете:

    Вы связываетесь с клиентом Docker, который впоследствии передает ваши инструкции Docker Daemon.

    Docker Daemon

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

    Dockerfile

    Dockerfile — то, где вы пишете инструкции для создания образов Docker. Эти инструкции могут быть таковы:

    • Для установки пакета ПО: RUN apt-get y install some-package;
    • Для раскрытия порта: EXPOSE 8000;
    • Для передачи переменной среды: ENV ANT_HOME /usr/local/apache-ant.

    Бывают и другие инструкции. Как только вы запустите Dockerfile, то сможете использовать команду docker build для создания образа. Вот пример Dockerfile:

    Docker Image

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

    Образы Docker создаются с помощью Dockerfile. Каждая инструкция в Dockerfile добавляет к образу новый «слой». Слои представляют собой часть файловой системы, которая либо дополняет слой под собой, либо заменяет его. Слои — ключ к легкой, но мощной структуре Docker. Для этого Docker применяет Union FS.

    Union File System

    Docker применяет Union FS для создания образов. Думайте о Union FS как о составной файловой системе. Это значит, что файлы и директории отдельных систем (их называют ветками) могут без перекодировки сформировать единую систему.

    Содержимое директорий, которые имеют одинаковые пути в ветках, представляется в виде объединенного директория. Из-за этого не требуется создавать копии каждого слоя. Вместо этого они получат указатели к одному и тому же ресурсу. Когда вам понадобится изменить определенные слои, будет создана копия. Изменения будут происходить на копии, а оригинал останется нетронутым. Поэтому вам может казаться, что файловые системы можно переписать, хотя на самом деле они этого не позволяют. (Другими словами, это система «копирование при записи».)

    Многоуровневые системы имеют 2 главных преимущества:

    • Свободное копирование: слои помогают избежать необходимости дублировать полный набора файлов каждый раз, когда вы используете образ для создания и запуска нового контейнера. Это делает создание контейнеров в Docker очень быстрым и «дешевым»;
    • Разделение слоев: внесение изменений происходит намного быстрее — при изменении образа Docker распространяет обновления только на слой, который был изменен.

    Volume

    Volume — это часть контейнера, ответственная за данные. Ее инициализация происходит при создании контейнера. Volume позволяют хранить и передавать данные контейнера. Volume отделены от обычной Union FS. Они существуют в виде обычных директорий и файлов в хостовой системе файлов. Даже если вы разрушите, обновите или рекомпилируете контейнер Docker, данные Volume останутся нетронутыми. Если вы хотите обновить Volume, нужно изменять его напрямую. (Дополнительное преимущество: данные в Volume можно распределять и использовать в нескольких контейнерах, что достаточно удобно.)

    Контейнеры Docker

    Контейнер Docker, как говорилось выше, упаковывает ПО приложения в невидимую «коробку», в которой есть все, что необходимо для запуска приложения. Туда входят ОС, код приложения, среда, инструменты, библиотеки и т. д. Контейнеры Docker создаются из образов. Так как образы доступны только для чтения, для создания контейнера Docker добавляет файловую систему «чтение/запись» поверх системы «read-only».

    Более того, после создания контейнера Docker добавляет сетевой интерфейс (он позволяет контейнеру общаться с локальным хостом), присоединяет доступный IP-адрес к контейнеру и выполняет процесс, который вы указали для запуска приложения при определении образа.

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

    Применение двойного клика к контейнерам

    Фух! Как много подвижных частей. Меня всегда интересовало: а как контейнеры вообще создаются? Вокруг них ведь нет какой-то абстрактной инфраструктуры. Я много читал, и теперь все стало ясно. Я попытаюсь объяснить это вам!

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

    1) Пространства имен

    Пространства имен предоставляют контейнерам свое собственное представление о базовой системе Linux. Это ограничивает то, что контейнер может видеть и к чему он может получать доступ. Когда вы запускаете контейнер, Docker создает пространства имен, которые будет использовать конкретный контейнер.

    В ядре используется несколько различных типов пространств имен, например:

    a. NET: Предоставляет контейнер с собственным представлением сетевого стека системы (например, собственные сетевые устройства, IP-адреса, таблицы IP-маршрутизации, каталог /proc/net, номера портов и т. д.);

    b. P >ps aux в командной строке, чтобы проверить, какие процессы запущены в вашей системе, вы видели столбец с названием «PID». Пространство имен PID дает контейнерам свое собственное видение процессов, которые они могут просматривать и с которыми способны взаимодействовать, включая независимый init (PID 1), который является «предком всех процессов»;

    c. MNT: дает контейнеру собственное представление о «монтировании» в системе. Таким образом, процессы в разных пространствах имеют разные представления об иерархии файловой системы;

    d. UTS: UTS обозначает UNIX Timesharing System. Это позволяет процессу идентифицировать системные идентификаторы (т. е. имя хоста, имя домена и т. д.). UTS позволяет контейнерам иметь свое собственное имя хоста и имя домена NIS, которое не зависит от других контейнеров и хост-системы;

    e. IPC: IPC расшифровывается как InterProcess Communication. Пространство имен IPC отвечает за изоляцию ресурсов IPC между процессами, выполняющимися внутри каждого контейнера;

    f. USER: это пространство имен используется для изоляции пользователей в каждом контейнере. Он функционирует, позволяя контейнерам иметь другое представление диапазонов uid (идентификатор пользователя) и gid (идентификатор группы) по сравнению с хост-системой. В результате uid и gid процесса могут различаться внутри и снаружи пространства имен пользователя. Это позволяет процессу иметь непривилегированного пользователя вне контейнера, не жертвуя привилегиями root внутри него.

    Docker использует эти пространства имен вместе, чтобы изолировать и начать создание контейнера. Следующий элемент — контрольные группы.

    2) Контрольные группы

    Контрольные группы (также называются cgroups) — это функция ядра Linux, которая изолирует, расставляет приоритеты и учитывает использование ресурсов (ЦП, память, дисковый ввод-вывод, сеть и т. д.) для набора процессов. Cgroup гарантирует, что контейнеры Docker используют только те ресурсы, которые им необходимы, и при необходимости устанавливает ограничения на то, какие ресурсы контейнер может использовать. Cgroups также гарантирует, что единственный контейнер не исчерпает один из этих ресурсов и не разрушит всю систему.

    Наконец, Docker также использует Union FS.

    3) Изолированная Union FS

    Описана выше в разделе «Docker Image».

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

    Будущее Docker: сосуществование Docker и VM

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

    Например, если вам нужно запустить несколько приложений на нескольких серверах, возможно, имеет смысл использовать виртуальные машины. С другой стороны, если вам нужно запустить много копий одного приложения, Docker предлагает некоторые неоспоримые преимущества.

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

    Безопасность также вызывает беспокойство в случае контейнеров Docker. Поскольку контейнеры используют одно и то же ядро, барьер между ними становится меньше. В то время как полная виртуальная машина может выдавать только гипервызовы гипервизору хоста, контейнер Docker может делать системные вызовы к ядру хоста, что создает большую площадь поверхности для атаки. Когда безопасность особенно важна, разработчики могут выбирать виртуальные машины. Они изолированы абстрактным оборудованием. Это значительно затрудняет их взаимодействие друг с другом.

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

    Заключение

    Надеюсь, теперь вы вооружились знаниями и пониманием того, что вам нужно больше узнать о Docker и, быть может, когда-нибудь применить его в проекте.

    Национальная библиотека им. Н. Э. Баумана
    Bauman National Library

    Персональные инструменты

    Docker

    Разработчики: Компания Docker Операционная система: GNU/Linux Платформа: x86-64 Лицензия: Apache 2.0 Веб-сайт https://www.docker.com/

    Docker — opensource-приложение (проект или инфраструктура), которое позволяет упаковывать, распространять, устанавливать и использовать opensource-приложения [1] .

    Система написана на Go. Работает в различных UNIX/Linux-системах, ожидается, что будет поддерживаться и Windows. Docker обычно использует различные системы виртуализации на уровне ОС, в настоящее время наибольшее распространение получила комбинация Docker + LXC, на которой он и был первоначально основан. Это привело к тому, что многие путают Docker и LXC, в действительности, это совершенно разные проекты с разными функциями.

    В своем ядре Docker позволяет запускать практически любое приложение, безопасно изолированное в контейнере. Безопасная изоляция позволяет вам запускать на одном хосте много контейнеров одновременно. Легковесная природа контейнера, который запускается без дополнительной нагрузки гипервизора, позволяет вам добиваться больше от вашего железа [2] .

    Содержание

    История

    Проект начат как внутренняя собственническая разработка компании dotCloud, основанной Соломоном Хайксом в 2008 году с целью построения публичной PaaS-платформы с поддержкой различных языков программирования. Наряду с Хайксом в первоначальной разработке значительное участие приняли инженеры dotCloud Андреа Лудзарди и Франсуа-Ксавье Бурле.

    В марте 2013 года код Docker был опубликован под лицензией Apache 2.0. В июне 2013 года генеральным директором в dotCloud приглашён Бен Голуб, ранее руководивший фирмой Gluster (разрабатывавшей технологию распределённого хранения GlusterFS и поглощённой за $136 млн Red Hat в 2011 году). В октябре 2013 года, подчёркивая смещение фокуса к новой ключевой технологии, dotCloud переименована в Docker (при этом PaaS-платформа сохранена под прежним названием — dotCloud).

    В октябре 2013 года выпущен релиз Havana тиражируемой IaaS-платформы OpenStack, в котором реализована поддержка Docker (как драйвер для OpenStack Nova). С ноября 2013 года частичная поддержка Docker включена в дистрибутив Red Hat Enterprise Linux версии 6.5 и полная — в 20-ю версию дистрибутива Fedora, ранее было достигнуто соглашение с Red Hat о включении с 2014 года Docker в тиражируемую PaaS-платформу Open Shift. В декабре 2013 года объявлено о поддержке развёртывания Docker-контейнеров в среде Google Compute Engine.

    С 2014 года ведутся работы по включению поддержки Docker в среду управления фреймворка распределённых приложений Hadoop. По результатам тестирования вариантов платформы виртуализации для Hadoop, проведённом в мае 2014 года, Docker показал на основных операциях (по массовому созданию, перезапуску и уничтожению виртуальных узлов) существенно более высокую производительность, нежели KVM, в частности, на тесте массового создания виртуальных вычислительных узлов прирост потребления процессорных ресурсов в Docker зафиксирован в 26 раз ниже, чем в KVM, а прирост потребления ресурсов оперативной памяти — втрое ниже.

    Использование Docker

    Быстрое выкладывание ваших приложений

    Docker хорош для организации цикла разработки. Docker позволяет разработчикам использовать локальные контейнеры с приложениями и сервисами. Это в последствии позволяет интегрироваться с процессом постоянной интеграции и выкладывания (continuous integration and deployment workflow).

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

    Докер не является заменой для LXC. «LXC» относится к возможностям ядра Linux (в частности, имена и контрольные группы), которые позволяет песочница процессов друг от друга, и контролирующее распределения их ресурсов. [3]

    На низком уровне функций ядра, Docker предлагает инструмент высокого уровня с несколькими мощными функциональными возможностями:

    • Портативное развертывание нескольких машин
    • Ориентированные приложения
    • Автоматическая сборка
    • Версии
    • Компонент повторного использования
    • Обмен
    • Инструмент экосистемы

    Более простое выкладывание и разворачивание

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

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

    Высокие нагрузки и больше полезных нагрузок

    Docker легковесен и быстр. Он предоставляет устойчивую, рентабельную альтернативу виртуальным машинам на основе гипервизора. Он особенно полезен в условиях высоких нагрузок, например, при создания собственного облака или платформа-как-сервис (platform-as-service). Но он так же полезен для маленьких и средних приложений, когда вам хочется получать больше из имеющихся ресурсов.

    Знакомимся с основными возможностями Docker

    Содержание статьи

    Надеюсь, Фабрицио смог убедить тебя в том, что Docker — это действительно must have инструмент для разработчика и администратора сколько-нибудь крупного проекта. Но даже если это не так, Docker все равно нужно знать: уже в самом ближайшем будущем он будет везде, начиная от десктопного Linux-дистрибутива и заканчивая пулом серверов на AWS. А самое приятное, что разобраться с Docker довольно легко, если, конечно, правильно понимать принцип его работы.

    Apt-get в мире виртуальных окружений

    Docker базируется на технологиях namespaces и cgroups (первая обеспечивает изоляцию, вторая — группировку процессов и ограничение ресурсов), поэтому в плане виртуализации он мало чем отличается от привычных нам LXC/OpenVZ, и рассказывать тут особо не о чем. Та же нативная скорость работы, те же методы изоляции, основанные на механизмах ядра Linux. Однако уровнем выше начинается совсем другая история. Изюминка Docker в том, что он позволяет развернуть полноценное виртуальное окружение и запустить в нем приложение так же просто, как, например, перезапустить веб-сервер.

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

    И это все. Мы только что запустили утилиту top внутри контейнера с окружением на базе последней доступной на данный момент версии Ubuntu с выводом информации в текущий терминал. И все это с помощью одной простой команды (установка не в счет). Неплохо, не правда ли? В общем-то, мы можем даже «зайти» в этот контейнер и делать все то, что обычно делают со свежеустановленной системой:


    Как видишь, с сетью тоже все ОK, поэтому мы можем обновить систему, установить и настроить любой софт. Немного похоже на магию, но на самом деле все очень просто. Docker — это своего рода apt-get в мире контейнеров, только вместо пакетов здесь образы файловой системы, а вместо официальных Debian/Ubuntu-репозиториев — облачное хранилище, называемое Docker Hub.

    Когда мы выполнили «docker run. », система сделала следующее:

    1. Утилита docker связалась с демоном dockerd на нашей локальной машине, передала от нас привет и попросила запустить последнюю версию Ubuntu (об этом говорит тег latest в команде) в изолированном контейнере.
    2. Демон dockerd сверился со своей записной книжкой, сходил в каталог /var/lib/docker и выяснил, что образа файловой системы с последней Ubuntu на нашей машине нет, поэтому он решил обратиться к Docker Hub с целью выяснить, а есть ли такой образ там.
    3. Пообщавшись с Docker Hub, он убедился, что образ все-таки существует, и попросил отправить его нам.
    4. Получив нужный образ, dockerd смонтировал его файловую систему, сделал в нее chroot и запустил указанную в последнем аргументе команду, ограничив ее «область видимости» с помощью namespaces (по сути, отрезал ей доступ к основной ФС, процессам хост-системы, IPC и прочему, заперев в песочнице), но перекинул в нее файлы устройства текущего терминала (флаг -t), чтобы наш top смог отрисовать свой псевдографический интерфейс.

    Изюминка такой модели в том, что Docker Hub открыт для всех и любой может подготовить собственный образ (об этом позже) и опубликовать его с целью установки на другую машину и/или другим человеком. На момент написания статьи в Docker Hub было опубликовано более 45 тысяч образов на все случаи жизни, начиная от образов «голых» дистрибутивов и заканчивая образами с преднастроенными серверными и десктопными приложениями, работающими в минималистичном Linux-окружении.

    Docker Hub собственной персоной

    Хакер #196. Все о Docker

    Что, если мы хотим запустить Firefox внутри виртуального окружения? Нет ничего проще, открываем Docker Hub в браузере, нажимаем Browse & Search и вбиваем firefox. На экран вывалится список результатов. Смотрим, kennethkl/firefox вроде вполне подходит. Клацаем по нему и видим инфу, как все это дело запустить. Автор говорит нам выполнить такую команду:

    Пробуем. Да, действительно, после недолгого скачивания образа получаем на экране стандартный Firefox. На этом же примере, кстати, можно ознакомиться с еще четырьмя полезными опциями команды docker run:

    • -d — «демонизирует» контейнер, то есть просто отключает Docker от STDOUT виртуального окружения и позволяет ему работать в фоне;
    • —name — имя контейнера, которое он получит вместо идентификатора;
    • -e — позволяет «пробросить» в виртуалку переменную окружения;
    • -v — пробрасывает указанный файл или каталог (формат /файл/на/хост/системе:/файл/в/виртуалке или просто /файл/на/хост/системе, если пути совпадают).

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

    Есть и более простой способ поиска образов Docker, с помощью команды docker search:

    Поиск в Docker Hub из консоли

    Любой пользователь Docker может запустить свой личный приватный Hub. Он носит название «реестр» и доступен в виде уже готового образа. Все, что нужно сделать, — это просто запустить его: docker run -p 5555:5555 registry.

    Демон Docker доступен не только с помощью клиента, но и с использованием RESTful API, причем как локально, так и с удаленной машины. Стандартные порты Docker — tcp/2375 e tcp/2376.

    Образ Docker не обязательно запускать сразу после скачивания, можно сначала скачать его на локальную машину с помощью команды docker pull, а лишь затем запустить: docker pull ubuntu.

    Слоеный пирог

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

    Если ты уже успел поиграть с образом Ubuntu из первых двух примеров, то наверняка заметил, что каждый новый запуск контейнера происходит «с нуля», а все изменения, сделанные в прошлом сеансе, теряются. Это вовсе не баг, это одна из ключевых особенностей архитектуры Docker, которая делает его еще более интересным и привлекательным решением.

    Дело в том, что в подавляющем большинстве случаев «образ Docker» — это вовсе не монолитный образ файловой системы, а своего рода слоеный пирог, состоящий из нескольких образов файловых систем, на основе которых формируется контейнер. При этом отдельно взятые образы ФС вовсе не отвечают за те или иные части структуры каталога (как, например, в случае с разбиением диска под Linux на разделы /home, /var, /boot), а наслаиваются друг на друга с помощью механизма AUFS ядра Linux (также есть поддержка той же функциональности через использование btrfs, device mapper и overlay).

    Мастер Йода рекомендует:  Русификация Drupal – это просто!

    Чтобы разобраться с тем, как это работает, вернемся к нашей контейнерной Ubuntu. Запускаем контейнер и устанавливаем nginx, как показано во втором примере в начале статьи, но не завершаем его. Вместо этого запускаем еще один терминал и смотрим список запущенных контейнеров:

    Эта команда покажет все запущенные контейнеры вместе с их ID, используемым образом, запущенной командой, временем работы и прочим. Нас интересует значение в столбце CONTEINER ID. Копируем его и запускаем следующую команду:

    После того как она отработает, можно выйти из контейнера, таким образом завершив его работу. А далее просто запускаем контейнер ubuntu-nginx и видим, что nginx никуда не пропал и находится на своем месте:

    Что же мы сделали? Мы создали еще один слой, то есть дополнительный образ ФС, и сгенерировали новый Docker-образ на основе уже существующего Docker-образа Ubuntu с включением нашего образа ФС, который содержит nginx. Звучит немного путано, правда? На самом деле все довольно просто.

    Мы уже выяснили, что каждый Docker-образ состоит из нескольких образов ФС. Когда мы запускаем контейнер, эти образы монтируются и собираются в одну структуру каталога с помощью AUFS. Например, первый образ может содержать только базовую установку Ubuntu, второй добавляет к ней набор стандартных демонов, третий — утилиты администрирования и так далее. Docker монтирует все слои в режиме «только чтение», но, чтобы мы имели возможность изменять содержимое образа, сверху подключается еще один изначально пустой слой в режиме «чтение/запись».

    Список локально сохраненных образов

    По умолчанию после завершения контейнера (которое происходит после завершения последнего работающего в нем процесса) последний слой стирается и все наши изменения пропадают. Однако, используя команду docker commit, мы можем «зафиксировать» изменения, создав новый Docker-образ на основе уже существующих образов ФС плюс образа ФС с нашими изменениями. Так внесенные нами изменения сохранятся. По желанию мы можем запустить контейнер ubuntu-nginx, внести в него изменения и точно так же сохранить в новый Docker-образ с помощью commit, добавив еще один слой. Чтобы посмотреть список всех получившихся в итоге (и полученных из Docker Hub) образов, можно использовать команду docker images, а для просмотра истории формирования слоев — команду docker history:

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

    История формирования образа Docker из слоев

    Docker вне Linux

    Единственный способ запустить Docker в OS X или Windows — это установить его в виртуальную машину. Не обязательно делать это вручную, можно воспользоваться уже готовым решением, например boot2docker. Это набор скриптов, которые позволяют быстро развернуть виртуальную машину с Linux и Docker внутри VirtualBox и запустить ее с автоматическим открытием доступа по SSH. Инструкцию по его использованию и сам инсталлятор можно найти на официальном сайте Docker.

    Настройка сети

    Для того чтобы контейнеры могли общаться между собой и с внешним миром, Docker автоматически поднимает виртуальный сетевой мост и настраивает правила маскарадинга (NAT) для внешнего сетевого интерфейса. Это значит, что извне достучаться до контейнеров не получится. Однако мы можем настроить проброс портов, чтобы запрос к определенным портам внешнего сетевого интерфейса машины автоматически перенаправлялся на указанные порты контейнера. Например, в компании Mirantis главный узел Fuel (это такой GUI для деплоя и настройки OpenStack) запускается в Docker и использует функцию проброса портов, чтобы открыть доступ к контейнеру ful/nginx (порт 8000):

    Мы могли бы пробросить порт 8000 на любой другой порт контейнера, просто изменив второе число в опции -p, но в данной конфигурации это не имеет смысла.

    Проброс файлов и Dockerfile

    В начале статьи мы уже познакомились с флагом -v, позволяющим пробросить в контейнер любой файл или каталог из хост-системы. Это очень удобная функция, ее можно использовать как для хранения каких-либо временных данных, так и для расшаривания файлов между несколькими контейнерами. В Mirantis эта функция используется для проброса файлов конфигурации сервиса Fuel/astute (/etc/astute) внутрь контейнера:

    То же самое можно сделать с помощью команды VOLUME в Dockerfile. Сам по себе Dockerfile — это местный эквивалент Makefile, но если последний предназначен для сборки приложений из исходных текстов, то Dockerfile позволяет собирать образы для Docker. Его назначение — упростить создание новых образов без необходимости запускать контейнер, производить в нем какие-то операции и выполнять коммит. Ты можешь просто написать Dockerfile, и Docker сделает все за тебя. Для примера рассмотрим Dockerfile для сборки Fuel/astute:

    Нетрудно понять, для чего он предназначен. Он создает образ на базе fuel/centos, запускает несколько команд для подготовки образа, добавляет в образ файлы из текущего каталога, применяет манифест Puppet, меняет права доступа на некоторые файлы, пробрасывает в контейнер каталог /etc/asture/ из хост-системы и запускает контейнер с помощью команды /usr/local/bin/start.sh.

    Для сборки контейнера достаточно положить Dockerfile и все файлы, которые будут добавлены в него, в какой-нибудь каталог и выполнить следующую команду:

    В данном случае мы выбрали имя fuel/astute_6.0:latest, хотя оно может быть любым.

    Dockerfile для сборки образа MySQL

    Нюансы работы с Docker

    Docker построен вокруг идеи о том, что в каждом контейнере должен работать только один сервис. Ты расфасовываешь Apache, MySQL, nginx, Varnish и все, что может понадобится для проекта, по разным контейнерам, а затем используешь Docker для сборки всего этого вместе. Такой подход дает большую гибкость, так как позволяет с легкостью менять конфигурацию, тестировать обновления и выполнять миграцию отдельных сервисов на другие машины.

    По этой же причине Docker не принято использовать для запуска полноценных Linux-окружений с демоном init, демонами cron и syslog и другими стандартными компонентами дистрибутива. Вместо этого мы просто запускаем нужный нам сервис, и он работает в виртуальном окружении в полном одиночестве:

    Но здесь есть небольшая проблема. Docker завершает работу контейнера сразу после того, как будет завершен запущенный в нем процесс (в данном случае nginx), а так как nginx по умолчанию демонизируется, то есть форкает новый процесс и завершает тот, что мы запустили руками, то Docker сразу после этого завершает и контейнер, прибивая форкнутый Docker.

    В случае с nginx обойти эту проблему можно, добавив daemon off; первой строкой в его конфиг. Для других демонов потребуются свои настройки, а некоторым можно запретить демонизироваться прямо из командной строки. Например, в sshd для этого предусмотрен флаг -D:

    В любой момент к контейнеру можно подключиться с помощью команды docker exec с целью просмотреть логи или изменить настройки (здесь и далее ID-контейнера — это либо ID, которое можно увидеть в выводе docker ps, либо имя, заданное при запуске в опции —name):

    Но и здесь есть одна небольшая загвоздка. Как мы знаем, вся накопленная во время работы виртуального окружения информация потеряется, если мы завершим работу виртуального окружения, а вместе с ней исчезнут логи и изменения, внесенные в настройки. Бесконечно создавать слои мы тоже не можем (хотя бы потому, что их может быть не больше 127), но мы можем пойти немного другим путем и воспользоваться встроенной в Docker системой агрегации логов. Конечно, Docker не умеет собирать логи отдельных приложений, но умеет накапливать вывод STDOUT, то есть любой консольный вывод. Все, что нам остается, — это изменить конфиг nginx так, чтобы логи сыпались в /dev/stdout, а затем просматривать их с помощью команды docker logs:

    Другой и более правильный вариант — это просто вынести логи (а если нужно, и настройки) на хост-систему с помощью уже описанной опции -v:

    При необходимости контейнер можно остановить корректно, завершив работающий в нем сервис с помощью команды docker stop:

    А если корректно остановить по какой-то причине не выходит, то можно и прибить его с помощью kill:

    При этом происходит одна важная вещь, о которой забывают многие новички: Docker сохраняет метаинформацию о контейнере. На деле это значит, что если ты запускаешь, например, nginx, указав с помощью аргументов команды docker run его имя, каталоги, которые нужно пробросить в контейнер, порты, переменные окружения и тому подобное, то вся эта информация будет сохранена при завершении контейнера и, чтобы запустить его в следующий раз, тебе уже не придется ее указывать, а достаточно просто выполнить такую команду (вместо ID можно использовать имя):

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

    Уничтожить все ранее сохраненные контейнеры можно с помощью такой команды:

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

    В любой момент образ можно экспортировать в единый файл и затем импортировать на другой машине. Для этого предусмотрены команды docker save и docker restore. Использовать их очень просто, экспорт выполняется так:

    Выводы

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

    Преимущества Docker перед LXC, OpenVZ и другими решениями виртуализации уровня ОС

    1. Docker использует переносимый универсальный формат образов. Это означает, что эти образы могут быть без каких-либо проблем перенесены на другую машину и расшарены для использования другими юзерами.
    2. Образ может служить базой для других образов. В Docker считается нормой использовать множество слоев для формирования конечного образа. Ты можешь начать с базового образа Ubuntu, затем добавить Apache 2.4, чтобы создать микросервис Ubuntu + Apache.
    3. При выполнении коммита образ можно версионировать, так же как это делается в GIT.
    4. У Docker большое комьюнити и обширная экосистема, которая включает серьезное количество инструментов масштабирования, группировки, мониторинга, разворачивания и управления контейнерами.

    Евгений Зобнин

    Редактор рубрики X-Mobile. По совместительству сисадмин. Большой фанат Linux, Plan 9, гаджетов и древних видеоигр.

    Введение в контейнеры, виртуальные машины и docker

    Рубрика: Информационные технологии

    Дата публикации: 20.09.2020 2020-09-20

    Статья просмотрена: 2684 раза

    Библиографическое описание:

    Подорожный И. В., Светличный А. Н., Подлеснов А. В. Введение в контейнеры, виртуальные машины и docker // Молодой ученый. — 2020. — №19. — С. 49-53. — URL https://moluch.ru/archive/123/33873/ (дата обращения: 10.11.2020).

    This article discusses virtual machines and docker, their architecture and distinctive capabilities.

    Keywords: virtual machines, containers, docker, LXC, UnionFS

    Что такое «контейнеры» и «виртуальные машины»?

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

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

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

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

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

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

    Рис. 1. Архитектура виртуальной машины

    Виртуальную машину, запускаемую на хосте, также часто называют «гостевой машиной». Гостевая машина содержат как приложение, так и все, что нужно для его запуска (например, системные исполняемые файлы и библиотеки). Она также несет в себе весь аппаратный стек, включая виртуальные сетевые адаптеры, файловое хранилище и центральный процессор, и свою собственную полноценную гостевую операционную систему. С внутренней стороны, гостевая машина ведет себя как свой собственный блок со своими собственными выделенными ресурсами. С внешней стороны, мы знаем, что это виртуальная машина, использующая общие ресурсы, предоставленные хостом.

    Контейнеры

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

    В целом, контейнеры выглядят как виртуальные машины. Например, у них есть изолированное пространство для запуска приложений, они позволяют выполнять команды с правами суперпользователя (root), имеют частный сетевой интерфейс и IP-адрес, пользовательские маршруты и правила межсетевого экрана и т. д.

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

    Рис. 2. Архитектура контейнера

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

    Docker

    Docker — программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы, например LXC. Позволяет «упаковать» приложение со всем его окружением и зависимостями в контейнер, который может быть перенесён на любую Linux-систему с поддержкой cgroups в ядре, а также предоставляет среду по управлению контейнерами.

    Основные преимущества Docker

    1. Простота использования. Основанная на контейнерах docker платформа позволят легко портировать полезную нагрузку. Docker контейнеры могут работать как на реальной локальной машине или машине в датацентре, так и на виртуальной машине в облаке. Портируемость и легковесная природа docker позволяет легко динамически управлять нагрузкой. Можно использовать docker, чтобы развернуть или погасить ваше приложение или сервисы. Скорость docker позволяет делать это почти в режиме реального времени.
    2. Скорость работы. Docker-контейнеры легковесны и быстры. Можно создать и запустить Docker-контейнер за секунды, в отличии от виртуальных машин, каждый раз запускающих полноценную виртуальную ОС.
    3. Модульность имасштабируемость. Docker позволяет легко разделять функциональность приложения в отдельные контейнеры. Например, можно запускать базу данных Postgres в одном контейнере, хранилище Redis в другом, в то время как приложение Node.js находится в третьем. Это позволит легко масштабировать и обновлять компоненты приложения независимо друг от друга.

    Архитектура Docker

    Docker использует архитектуру клиент-сервер. Docker-клиент общается с демоном Docker, который берет на себя тяжесть создания, запуска, распределения контейнеров. И клиент и сервер могут работать на одной системе, можно подключить клиент к удаленному демону docker. Клиент и сервер общаются через сокет или через RESTful API.


    Docker-демон

    Как показано на рисунке 3, демон запускается на хосте. Пользователь не взаимодействует с сервером напрямую, а использует для этого Docker-клиент.

    Docker-клиент

    Docker-клиент, программа docker — главный интерфейс к Docker. Она получает команды от пользователя и взаимодействует с docker-демоном.

    Рис. 3. Архитектура Docker

    Чтобы понимать из чего состоит docker нужно знать о трех его компонентах:

    Образы

    Docker-образ — это read-only шаблон. Например, образ может содержать операционную систему Ubuntu c веб-сервером Nginx и приложением на ней. Образы используются для создания контейнеров. Docker позволяет легко создавать новые образы и обновлять существующие.

    Каждый образ состоит из набора уровней. Docker использует UnionFile System для сочетания этих уровней в один образ. Union File System позволяет файлам и директориями из разных файловых систем (разным ветвям) прозрачно накладываться, создавая когерентную файловую систему.

    Одна из причин, по которой docker легковесен — это использование таких уровней. При изменении образа (например, при обновлении приложения) создается новый уровень. Так, без замены всего образа или его пересборки (как это пришлось бы сделать с виртуальной машиной) происходит лишь добавление или удаление нужных уровней. Это также позволяет распространять образы проще и быстрее.

    В основе каждого образа находится базовый образ. Например, ubuntu, базовый образ Ubuntu, или debian, базовый образ дистрибутива Debian.

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

    ‒ добавление файла или директории;

    ‒ создание переменной окружения;

    ‒ указания что запускать, когда запускается контейнер этого образа.

    Эти инструкции хранятся в файле Dockerfile. Docker считывает Dockerfile при сборке образа, выполняет эти инструкции и возвращает конечный образ.

    Реестр

    Docker-реестр хранит образы. Есть публичные и приватные реестры, из которых можно скачать либо загрузить образы. Существует публичный Docker-реестр с огромной коллекцией контейнеров — Docker Hub.

    Контейнеры

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

    Используемые технологии

    Докер написан на языке Go и использует некоторые возможности ядра Linux, чтобы реализовать приведенный выше функционал.

    Пространства имен

    Docker использует технологию «namespaces» для организации изолированных рабочих пространств, которые называются контейнерами. При запуске контейнера docker создает набор пространств имен для данного контейнера. Это создает изолированный уровень, каждый аспект контейнера запущен в своем пространстве имен и не имеет доступ к внешней системе.

    Существует несколько типов пространств имен, которые использует docker:

    pid: для изоляции процесса;

    net: для управления сетевыми интерфейсами;

    ipc: для управления IPC ресурсами;

    mnt: для управления точками монтирования;

    utc: для изолирования ядра и контроля генерации версий.

    Контрольные группы

    Docker также использует технологию «cgroups» или контрольные группы. Ключ к работе приложения в изоляции — предоставление приложению только тех ресурсов, которые ему нужны для правильного функционирования. Это гарантирует, что контейнеры будут хорошими соседями. Контрольные группы позволяют разделять доступные ресурсы железа и если необходимо, устанавливать пределы и ограничения. Например, ограничить возможное количество памяти контейнеру.

    Файловая система UnionFS

    Union File System или UnionFS — вспомогательная файловая система для Linux и FreeBSD, производящая каскадно-объединённое монтирование других файловых систем. Это позволяет файлам и каталогам изолированных файловых систем, известных как ветви, прозрачно перекрываться, формируя единую связанную файловую систему. Каталоги, которые имеют тот же путь в объединённых ветвях, будет совместно отображать содержимое в объединённом каталоге новой виртуальной файловой системы. Docker использует UnionFS для создания блоков, из которых строится контейнер. Docker может использовать несколько реализаций UnionFS, включая: AUFS, btrfs, vfs и DeviceMapper.

    Как не бояться docker

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

    Эту заметку я пишу для себя и таких, как я. И здесь не будет готовых рецептов для решения частных (и частых) вопросов. Этого, полно и так. Здесь я по шагам покажу, что такое docker изнутри, чтобы любые другие ваши действия стали понятны для вас.

    Установка docker

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

    Что нужно проверить перед началом работы: что у вас запущен демон. Если вы видите что-то такое:

    значит надо запустить демона.

    В вашей системе команда может быть другой. Если же вы используете systemctl , возможно, вы ещё захотите включить демона в автозапуск systemctl enable .

    Когда вы запустите демона, возможно появление такой ошибки

    Обычно, достаточно или включить пользователя в группу docker (но я не рекомендовал бы так делать потому, что тем самым, вы фактически дадите пользователю рутовые права), либо просто использовать sudo.

    Если вы это видите — ваш docker готов к использованию.

    Как обычно используется docker и что будем делать мы

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

    Два слова о том, как работает docker

    Не вдаваясь в историю и в детали реализации на разных операционных системах, скажу, что сейчас в Linux docker использует не виртуализацию (как многие думают), а средства ядра, позволяющие создавать изолированные группы процессов. Т.е. запуская «виртуальную машину» (пишу это в кавычках), docker делает всего несколько системных вызовов и ядро создаёт для нового процесса отдельное пространство PID-ов, отдельную виртуальную сеть, отдельный набор ограничений по ресурсам. Процесс «запущенный в docker», на самом деле находится не в какой-то виртуальной машине (нет никакого эмулятора настоящей машины, никакой виртуальной сущности), он запущен на той же машине, тем же ядром, просто ядро ассоциирует его со специфическим набором настроек. Это почти то же самое, что и sodo или chroot , просто набор ограничений чуть шире и полней.

    Начнём: получаем docker-образ

    Существует github для docker: хранилище готовых образов. Вы можете там хранить и свои. Возьмём оттуда готовый образ какой-нибудь широко известной операционной системы:

    Мы можем убедиться, что образ приехал:

    Теперь мы можем запустить любой бинарь из этого образа. Да, это звучит и выглядит, как запуск виртуальной машины и сбивает с толку. На самом деле, мы помним, что это чуть более умный chroot/sudo.

    • в контейнере мы стали пользователем root, но это не тот же root, что в хост-системе, ядро создало для нашего процесса отдельно пространство пользователей
    • в контейнере у нас своя отдельная файловая система, это похоже на chroot (но не совсем)
    • в нашем контейнере очень мало что есть (mc пока нет).

    Давайте посмотрим на наш контейнер снаружи:

    Мы видим, что контейнер сделан на основе образа ubuntu , какая запущена команда, видим и имя контейнера из опции —name .

    Если мы выйдем из контейнера:

    То он никуда не пропадёт, а просто остановится:

    Обратите внимание на опцию -a , без неё мы бы не увидели остановленный контейнер.

    docker: Error response from daemon: Conflict

    Это самая частая ошибка, с которой сталкиваются начинающие пользователи. Если сейчас попытаться снова запустить наш bash из контейнера, то вы увидите что-то подобное:

    Вы можете перезапустить этот контейнер, но сейчас давайте просто удалим его:

    При этом вы не удалили никакие данные или процессы, вы удалили только мета-информацию о песочнице, в которой бежал ваш bash.

    Вам может много раз понадобится удобная команда, удаляющая все завершённые контейнеры:

    Теперь вы можете снова запустить контейнер.

    Мы научились уверенно запускать контейнеры, давайте разберёмся с файлами.

    Файловая система docker

    Если мы снова запустим наш контейнер и установим в него mc:

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

    Чтобы сохранить текущее состояние, мы должны создать новый образ:

    Посмотри, что получилось:

    • появился новый образ ubuntu-mc : это и есть базовая Ubuntu, плюс mc , который мы установили сами
    • у образа есть tag, как мы и указали в команде

    Теперь мы можем запуститься на новом образе и наш mc будет с нами

    Здесь надо упомянуть про слои: файловая система докера слоёная, каждый слой хранится отдельно и один накладывается поверх другого. Для нас сейчас это не важно, но для оптимальной работы с докером, это хорошо бы знать. Если вы не знаете, почитайте про это. Я же пойду дальше.

    Запускаем сервер в docker

    Давайте создадим контейнер с крошечным сервером.

    Запустимся на базовом образе и поставим nodejs:

    Набросаем http-сервер, который возвращает на любой запрос текущее время:

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

    Как сделать ssh-дотуп в docker?

    Поднять в docker ssh-сервер не сложнее, чем в обычной системе, но вам не надо этого делать.

    Вспомните: docker-контейнер, это не виртуальная машина. Это просто отдельное пространство процессов.

    Чтобы попасть в это пространство, вам надо просто подселить туда ещё один процесс. Это происходит точно так же, как и запуск первого процесса.

    Что бы запустить любой процесс, в том числе shell, в существующем контейнере, существует команда docker exec .

    Видим, что наш контейнер с сервером запущен:

    Мы можем просто запустить в нём ещё один shell, аналогично команде docker run :

    • подселили новый shell в запущенный контейнер с уже бегущим процессом node ,
    • убедились, что node слушает на порту 80,
    • обратились к этому серверу и получили ответ

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

    Как включить проброс порта в уже запущенный docker

    К сожалению, никак. Настройку портов можно производить только в момент создания контейнера.

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

    Итак. Чтобы не потерять нашу работу по настройке контейнера, делаем commit и сохраняем образ:

    Видим, что появился третий образ с нашей нодой. Тег latest удобен тем, что его можно опускать, при указании образа.

    Останавливаем контейнер. Я просто прибью все контейнеры командой:

    Запускаем сразу наш сервер и пробрасываем порт 80 наружу. Снаружи я ему назначил номер 9911:

    Теперь мы можем обратиться к серверу, бегущему в контейнере, снаружи:

    Поздравляю: для собственного сервера мы подготовили образ и запустили его в контейнере. И сделали мы это полностью осознанно. Мы знаем, как найти контейнер, как войти в контейнер, если что-то пойдёт не так. Я надеюсь, что сейчас вы ощущаете себя полным хозяином обстановки. И даже если у вас остались вопросы, вы сами знаете, куда смотреть и где искать ответы.

    Осталось немного: показать, как можно автоматизировать все эти шаги.

    Dockerfile

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

    Созадём два файла: server.js (он есть выше) и Dockerfile :

    Мы описали все шаги, необходимые для запуска нашего сервера (всё, что мы делали руками до команды commit ). Замечаний заслуживают, пожалуй, только: — -y в третьей строке — нам не надо лишних вопросов — COPY — мы копируем файл с хост-системы в контейнер (да, снова в корень, не очень красиво, но сейчас это не принципиально) — CMD — запускает команду с аргументами в качеств процесса с P >EXPOSE — не совершает никаких действий, но декларирует, что порт 80 не мешало бы пробросить наружу.

    Теперь мы можем создать контейнер, согласно описанию:

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

    Теперь у нас появился образ node-server:

    И теперь мы можем запустить контейнер, как все нормальные люди (без -it , без указания команды…):

    Вы уже знаете, как посмотреть, что он бежит ( docker ps ), остановить и перезапустить его, как подключиться к нему для дебага… И конечно, вы можете обратиться к нему снаружи:

    Здесь не рассказано про множество мелких деталей. Рекомендую почитать про все команды докера и про Dockerfile . Но про это есть множество материалов, статей, лекций и выступлений.

    Я же, напоследок, расскажу, как удалить всё, что мы наделали:

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