Мышление как контейнеры

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

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

Виртуализация

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

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

  • ОЗУ машины: 16 ГБ
  • Квота Windows 10: 4 ГБ
  • Квота Ubuntu 18.04: 4 ГБ

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

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

Контейнеры

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

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

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

Экспериментирование

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

Все эти неприятные вещи, которые иногда мешают нам проводить эксперименты. Ушли.

Переключение контекста

Иногда многие из нас работают над различными проектами. Переключение контекстов может быть неудобным. В одном проекте используется PostgreSQL 9.5, а в другом — PostgreSQL 11. Управлять двумя экземплярами Postgres в локальной среде? Удачи вам в этом.

При использовании контейнеров переключение контекста происходит легко:

$ docker rm -f postgres_9
$ docker run --name postgres_11 postgres:11 
Войти в полноэкранный режим Выход из полноэкранного режима

Унификация

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

Это переводит нас в другое положение, когда мы имеем полный контроль над приложением. Это НАМНОГО проще для отладки и воспроизведения ошибок, поскольку мы используем одну и ту же ОС и библиотеки.

Больше никаких «это работает на моей машине» или «это НЕ работает на моей машине».

Независимость от развертывания

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

$ docker run --name my_application my_application
Вход в полноэкранный режим Выход из полноэкранного режима

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

Хотите попробовать более дешевого облачного провайдера? Отлично. Ваш контейнер будет запущен там без особых усилий.

Режимы выполнения контейнеров

Для запуска контейнеров нам необходимо установить и настроить среду выполнения контейнеров. Для целей этой статьи и в силу ее популярности мы будем использовать Docker.

Первый контейнер

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

Предположим, что у вас правильно настроен Docker, мы хотим запустить bundle install в каком-нибудь приложении, которое у нас есть, но помните, что у нас на компьютере не установлен Ruby.

  • Мы не хотим устанавливать ни Ruby, ни его зависимости.
  • мы просто хотим запустить bundle install внутри контейнера и все.

Первое, что нужно сделать:

$ docker run ruby:2.7
Войдите в полноэкранный режим Выход из полноэкранного режима

Команда run берет где-то заранее определенный образ контейнера и запускает контейнер, следуя правилам, описанным в этом самом образе. Откуда взялся образ ruby:2.7? Из Docker Hub. Считайте его Github для образов Docker.

Существует больше реестров контейнеров, чем Docker Hub, например, Github Registry, Amazon ECR и другие. Мы можем изменить реестр в любое время с помощью команды docker login.

Приведенная выше команда не сделала ничего, кроме показа сообщения Switch to inspect mode.. Это потому, что команда по умолчанию, предопределенная в образе ruby:2.7 — это irb, что означает, что контейнер попытается выделить псевдо-TTY, чтобы мы могли взаимодействовать на этом tty, или «терминале».

Для этого нужно использовать опцию flag в команде run:

$ docker run -it ruby:2.7

### Options
-t Allocate a pseudo-TTY
-i Keep STDIN open even if not attached
Войти в полноэкранный режим Выйти из полноэкранного режима

Теперь у нас есть полная установка Ruby 2.7, готовая к получению инструкций, прямо на нашем компьютере без необходимости установки хоста!

Это большое YAY, с моей точки зрения 😀

Вход в контейнер

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

$ docker run ruby:2.7 ls
Войти в полноэкранный режим Выйти из полноэкранного режима

Это:

  • создает контейнер, используя изображение
  • выполняет команду ls внутри контейнера
  • выходит из контейнера

Зная, что мы можем выполнить любую команду, мы можем выполнить команду bash, которая приведет нас прямо в контейнер:

$ docker run -it ruby:2.7 bash

# Remember that the bash, as the same as irb, will 
# allocate a pseudo-TTY
Войти в полноэкранный режим Выйти из полноэкранного режима

Что если мы попытаемся запустить bundle внутри контейнера?

$ Could not locale Gemfile
Войти в полноэкранный режим Выйти из полноэкранного режима

Вот почему: контейнеры изолированы. Представьте себе отдельные «компьютеры» (контейнеры) внутри нашего компьютера (хоста).

Как насчет «копирования» наших файлов с хоста в контейнер? Мы можем использовать тома.

$ docker run 
    -it 
    -v $(pwd):/app 
    ruby:2.7 
    bash

## Options
-v source:target, where the source is our current dir on host (pwd), and target a folder we will cal "app" in the container
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь, внутри контейнера, мы можем запустить bundle install. Если вы используете обычное Ruby-приложение с Gemfile, оно начнет установку драгоценных камней с помощью bundler!

Конфиг bundler и установленные гемы находятся в стандартном каталоге, /usr/local/bundler.

Контейнеры эфемерны

Попробуйте выйти из контейнера и войти в него снова. Запустите bundle install. Что произойдет?

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

Да, тома.

$ docker run 
    -it 
    -v $(pwd):/app 
    -v bundler_gems:/usr/local/bundler 
    ruby:2.7 
    bash
Вход в полноэкранный режим Выход из полноэкранного режима

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

Мы просто говорим:

I want to associate anything "inside /usr/local/bundler" 
FROM the container 
TO a volume named "bundler_gems" 
ON the host
Войти в полноэкранный режим Выйти из полноэкранного режима

Первая установка bundle install займет время, потому что том еще пуст. Но со второго раза и далее, каждый раз, когда мы запускаем новый контейнер, Docker будет ассоциировать именованный том с /usr/loca/bundler внутри контейнера и наоборот.

Такова природа томов: двустороннее связывание. Если вы меняете с хоста, это повлияет на контейнер. Если вы измените из контейнера, это повлияет на хост.

Заключение

Эта статья была введением в контейнеры и, если быть более строгим, в то, как думать как контейнер.

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

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

Оцените статью
devanswers.ru
Добавить комментарий