Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Запуск Docker: Основы

Начнем сразу с примера, показывающего основные принципы работы Docker. Запустим его:

# nginx взят просто для примера
docker run -it nginx bash

root@a6c26812d23b:/#

Этой командой мы говорим "запусти bash внутри контейнера используя образ nginx". Что это значит?

  • Образ (Image) — это слепок файловой системы, в который упаковано что-то, ради чего мы используем Docker. Например, это может быть PostgreSQL, nginx или наше приложение
  • Контейнер (Container) — это процесс операционной системы, подключенный к образу. Кроме того, контейнер изолирован от внешней среды и живет в своем окружении. В этом смысле контейнер похож на обычную виртуальную машину, но он более легковесный и зависит от основной операционной системы

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

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

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

# Общая структура
# docker run <имя образа> <команда> <параметры если есть>
docker run nginx cat /etc/nginx/nginx.conf

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
...

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

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

# Обратите внимание на то, что после имени образа не указана никакая команда
# Такой подход работает в случае если команда на запуск прописана в самом образе
# -p — проброс портов, расскажем о нем в следующих уроках
docker run -p 8080:80 nginx

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

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

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

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.1  0.1  18240  3300 pts/0    Ss   15:39   0:00 /bin/bash
root        12  0.0  0.1  34424  2808 pts/0    R+   15:40   0:00 ps aux

Как видно, процесса всего два, и у Bash PID равен 1. Из этого можно сделать несколько выводов:

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

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

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

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

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

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

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

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

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

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

На этом месте стоит немного окунуться в происхождение названия "Docker".

docker logo

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

loading cargo onto a ship

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

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

shipping container terminal

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

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

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

Основная причина всех проблем — изменяемое состояние. Программы ставятся, обновляются, удаляются. Все это происходит в разное время на разных серверах и немного по-разному. Например, обновить версию PHP, Ruby или Python — это целое рискованное приключение. Проще поставить рядом новый сервер и переключиться на него. Идейно Docker позволяет сделать именно такое переключение, забыть про старое и поставить новое. Каждый запущенный контейнер живет в своем окружении, причем откат в такой системе очень прост: нужно все лишь остановить новый контейнер и поднять старый на базе предыдущего образа.


Самостоятельная работа

По традиции первая программа, которую создают программисты, называется Hello, World!. В нашем случае запустим аналогичную программу, которая выведет приветствие.

Изучите ридми образа hello-world и запустите его.


Дополнительные материалы

  1. Docker Documentation: docker run

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

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

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

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

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и соглашаетесь с «Условиями использования»