В прошлом уроке мы познакомились с TaskMaster и выяснили, что Docker упаковывает приложение со всеми зависимостями в контейнер. Но если вы хоть раз слышали про виртуальные машины — у вас наверняка возник вопрос:
«Подождите, а разве виртуальные машины не делают то же самое? Изолированная среда, свои зависимости, работает везде одинаково — в чём разница?»
Разница — принципиальная. И именно она объясняет, почему Docker завоевал мир за несколько лет. Начнём с виртуальных машин — они появились раньше и проще для понимания.
Виртуальная машина (VM) — это компьютер внутри компьютера. Вы берёте свой ноутбук с Windows, устанавливаете программу-гипервизор (VirtualBox, VMware, Hyper-V) и создаёте внутри неё виртуальный компьютер. У этого виртуального компьютера своё ядро, своя операционная система, свои драйверы — полная копия настоящей машины, только программная.
Аналогия. Представьте многоквартирный дом. Виртуальная машина — это отдельная квартира с собственными стенами, полом, потолком, водопроводом, электрикой и даже фундаментом. Каждая квартира полностью автономна. Хотите новую квартиру? Стройте с нуля: фундамент, стены, коммуникации. Это надёжно, но долго и дорого.
Допустим, вы хотите передать TaskMaster коллеге с помощью виртуальной машины. Что для этого нужно? Создать VM, установить в ней Ubuntu (~2 ГБ), потом Python, потом скопировать taskmaster.py — наш скрипт на 40 строк, который весит пару килобайт. Итого: 2 ГБ ради файла, который легче одной фотографии. И это ещё без базы данных, которую мы подключим позже.
У VM есть и другие проблемы:
- Тяжёлые. Каждая VM тащит полную операционную систему — ядро, системные службы, драйверы. Три VM — 6 ГБ только на ОС, ещё до запуска ваших приложений.
- Медленный старт. VM загружается как обычный компьютер: BIOS, ядро, службы, сеть. Это 30–60 секунд минимум. Хотите запустить TaskMaster, чтобы добавить одну задачу? Подождите минуту, пока виртуальная машина загрузится.
- Ресурсы выделяются заранее. Создали VM с 4 ГБ RAM — эти 4 ГБ заблокированы, даже если TaskMaster использует 20 МБ. А теперь — контейнеры. И вот тут начинается самое интересное.
Контейнер не содержит собственного ядра. Он использует ядро хост-машины — того компьютера, на котором запущен Docker. Контейнер — это просто изолированный процесс (или группа процессов) с собственной файловой системой, сетью и переменными окружения. Но ядро — общее.
Вернёмся к аналогии с домом. Если VM — это квартира с собственным фундаментом и коммуникациями, то контейнер — это комната в коворкинге. Стены есть — вы изолированы от соседей. Но фундамент, электрика, водопровод и отопление — общие на всё здание. Вам не нужно их строить. Вы просто заходите, ставите свой ноутбук и работаете. Через минуту. Без стройки.
Для TaskMaster это выглядит так: контейнер содержит Python 3.11 и наш скрипт — всего ~150 МБ. Запускается за секунду. Вы пишете docker run taskmaster add "Купить молоко" — задача добавлена, контейнер завершился. Никакой загрузки ОС, никаких 2 ГБ на диске. Быстро, как запустить обычный скрипт.
Что это даёт на практике:
- Легковесность. Контейнер с TaskMaster — ~150 МБ. VM с тем же TaskMaster — 2+ ГБ. Разница в 15 раз.
- Мгновенный старт. Контейнер запускается за 1–2 секунды. Ядро уже работает — запускается только ваш процесс.
- Эффективное использование ресурсов. На одном сервере можно запустить сотни контейнеров. VM — десятки, в лучшем случае.
Давайте сравним наглядно. Представьте: TaskMaster вырос. Это уже не скрипт на 40 строк, а полноценное веб-приложение с базой данных PostgreSQL и кэшем Redis (мы к этому придём ближе к концу курса). Три компонента нужно запустить изолированно.
С виртуальными машинами:
Хост-машина (ваш компьютер)
├── Гипервизор (VirtualBox / VMware)
│ ├── VM 1: Ubuntu + Python + TaskMaster Web (~2.5 ГБ, старт 40 сек)
│ ├── VM 2: Ubuntu + PostgreSQL (~2.5 ГБ, старт 40 сек)
│ └── VM 3: Ubuntu + Redis (~2.5 ГБ, старт 30 сек)
│
Итого: ~7.5 ГБ, ~2 минуты на запуск
С Docker:
Хост-машина (ваш компьютер)
├── Docker Engine
│ ├── Контейнер: Python + TaskMaster Web (~150 МБ, старт 1 сек)
│ ├── Контейнер: PostgreSQL (~200 МБ, старт 2 сек)
│ └── Контейнер: Redis (~30 МБ, старт 1 сек)
│
Итого: ~380 МБ, ~3 секунды на запуск
7.5 ГБ против 380 МБ. Две минуты против трёх секунд. А когда мы дойдём до Docker Compose — все три контейнера TaskMaster будут подниматься одной командой docker compose up. С виртуальными машинами такое не провернуть.
Значит ли это, что виртуальные машины — устаревшая технология? Нет. У VM есть случаи, где они незаменимы:
- Нужна другая ОС. Хотите запустить Windows-приложение на Linux-сервере? Контейнер так не может — он использует ядро хоста. VM — может, потому что у неё своё ядро.
- Максимальная изоляция. В контейнерах ядро общее — теоретически уязвимость в ядре может затронуть все контейнеры. VM изолированы полностью. Для банков и систем с жёсткими требованиями безопасности это важно.
- Нестандартное ядро. Тестируете драйвер или модуль ядра? Контейнер тут не поможет — нужна VM со своим ядром.
Но для TaskMaster — и для 95% задач разработчика — контейнеры подходят идеально. Нам не нужна другая ОС, не нужно виртуальное оборудование. Нам нужен Python, наш скрипт и пара секунд на запуск. Контейнер — ровно про это.
Виртуальная машина (VM) — программная эмуляция компьютера со своим ядром ОС. Тяжёлая (гигабайты), медленный старт (минуты), полная изоляция.
Контейнер — изолированный процесс, использующий ядро хоста. Лёгкий (мегабайты), мгновенный старт (секунды), эффективное использование ресурсов.
VM виртуализирует оборудование (создаёт виртуальный компьютер). Контейнер виртуализирует ОС (создаёт изолированное пространство). Разница: «построить ещё один дом» vs «добавить комнату в существующий».
VM нужны, когда требуется другая ОС или максимальная изоляция. Контейнеры — для 95% задач разработки. Для TaskMaster нам не нужна целая виртуальная машина — достаточно контейнера с Python.
На Windows и macOS Docker использует лёгкую VM с Linux под капотом — контейнеры работают внутри неё прозрачно.