← Назад к вопросам

Почему Docker легковеснее виртуальной машины?

2.0 Middle🔥 201 комментариев
#Docker, Kubernetes и DevOps

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Ответ: Почему Docker легче виртуальной машины

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

Архитектурные различия

Виртуальная машина (VM):

┌─────────────────────────────────────┐
│  Host OS (Linux, Windows, macOS)    │
│  ┌───────────────────────────────┐  │
│  │   Hypervisor (VMware, KVM)    │  │
│  ├───────────────┬───────────────┤  │
│  │  Guest OS 1   │  Guest OS 2   │  │
│  │  ├─ App 1     │  ├─ App 2     │  │
│  │  ├─ Libs      │  ├─ Libs      │  │
│  │  └─ Kernel    │  └─ Kernel    │  │
│  └───────────────┴───────────────┘  │
└─────────────────────────────────────┘

Каждая VM включает:

  • Полную копию гостевой ОС (например, Ubuntu 20.04)
  • Ядро ОС
  • Файловую систему
  • Все системные утилиты
  • Гиперавизор для управления

Docker (контейнер):

┌─────────────────────────────────────┐
│  Host OS (Linux kernel)             │
│  ┌───────────────┬───────────────┐  │
│  │ Container 1   │ Container 2   │  │
│  │ ├─ App 1      │ ├─ App 2      │  │
│  │ ├─ Libs       │ ├─ Libs       │  │
│  │ └─ rootfs     │ └─ rootfs     │  │
│  ├───────────────┴───────────────┤  │
│  │ Docker Daemon (containerization)│  │
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘

Докер контейнер делит ядро хоста, а не имеет собственное.

1. Ядро ОС (Kernel) — главное отличие

VM: Каждая ВМ имеет СВОЙ kernel

  • VM с Ubuntu: минимум 100-200 MB для ядра
  • VM с CentOS: 150-250 MB для ядра
  • Ядро полностью дублируется для каждой VM

Docker: Все контейнеры ДЕЛЯТ ядро хоста

# На Linux хосте все контейнеры используют один kernel
uname -r  # В хосте
5.15.0-101-generic

# В контейнере — тот же kernel
uname -r  # В контейнере
5.15.0-101-generic

Это экономит сотни МБ на каждый контейнер.

2. Размер образа

VM:

# Образ Ubuntu 20.04 VM
2-3 GB на диске

Docker:

# Docker образ Ubuntu 20.04
docker images | grep ubuntu
ubuntu  20.04    0a1b2c3d4e5f   77 MB (!)  # В 25+ раз меньше

# Java приложение
java:17-alpine    a1b2c3d4e5f6   200 MB    # Компактный образ
java:17-slim      b2c3d4e5f6g7   400 MB    # Среднее
java:17           c3d4e5f6g7h8   700 MB    # Полный JDK

Контейнер — это только приложение + нужные библиотеки, не вся ОС.

3. Время запуска

VM:

  • Загрузка гиперавизора
  • Инициализация ядра ОС (несколько секунд)
  • Загрузка системных сервисов
  • Минимум 5-15 секунд на запуск
# Запуск VM
time vm start ubuntu-machine
# real: 10.234s

Docker:

  • Использует уже работающее ядро хоста
  • Просто изолирует процессы (namespaces, cgroups)
  • Средние < 1 сек на запуск контейнера
# Запуск контейнера
time docker run ubuntu sleep 100
# real: 0.234s

4. Потребление памяти

VM:

  • Каждой VM нужно минимум 512 MB - 2 GB RAM для ОС
  • 5 VM на сервере = 5-10 GB только на ОС

Docker:

  • Контейнер занимает только память приложения
  • 50 контейнеров могут работать на 1 GB RAM
  • В 10 раз экономнее
# Память VM
free -h
total: 16 GB
used: 12 GB (ОС + приложения)

# Память Docker контейнеров
docker stats
CONTAINER  MEM USAGE
app1       120 MB
app2       95 MB
app3       150 MB
# Всего: 365 MB + хост Linux ядро

5. Технология изоляции

VM — полная виртуализация:

Приложение → ОС гостя → Гиперавизор → ОС хоста → Железо

Каждый слой добавляет overhead (накладные расходы).

Docker — изоляция уровня ОС (OS-level virtualization):

Приложение → Namespaces + cgroups → ОС хоста → Железо

Меньше слоёв = меньше overhead.

Namespaces в Linux:

# Docker использует namespaces для изоляции
pid namespace    # Процессы видят только свои PID
net namespace    # Своя сетевая карта (виртуальная)
ipc namespace    # Своя память для IPC
fs namespace     # Своя корневая директория
user namespace   # Своя таблица пользователей

Cgroups — ограничение ресурсов:

# Ограничить контейнер 512MB памяти
docker run -m 512m my-app

# Ограничить 1 CPU
docker run --cpus="1.0" my-app

6. Практическое сравнение

# Запустить 10 VM с Java приложением
10 × (2 GB ОС + 1 GB приложение) = 30 GB памяти
Время запуска: 10 × 10 сек = 100 секунд

# Запустить 10 Docker контейнеров с Java приложением
10 × (500 MB приложение) + 1 × (2 GB kernel хоста) = 7 GB памяти
Время запуска: 10 × 0.5 сек = 5 секунд

Компромисс: Безопасность vs Легковесность

VM:

  • ✅ Максимальная безопасность (полная изоляция)
  • ✅ Можно запустить другую ОС (Windows на Linux)
  • ❌ Тяжело, медленно, дорого в ресурсах

Docker:

  • ✅ Легко, быстро, экономно
  • ✅ Идеально для микросервисов
  • ⚠️ Уровень безопасности ниже (контейнеры в одной ОС)
  • ❌ Только Linux kernel (хотя есть Docker Desktop с VM)

Java приложения в Docker

FROM openjdk:17-slim
COPY app.jar /app.jar
CMD ["java", "-jar", "/app.jar"]

# Размер: 400-500 MB (vs 2-3 GB VM)
# Время запуска: 1-2 сек (vs 10-15 сек VM)

Итоговый вывод

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

  1. Делит ядро хоста вместо дублирования (экономит сотни МБ)
  2. Изоляция на уровне ОС (namespaces, cgroups) вместо гиперавизора
  3. Образ содержит только приложение (не полную ОС)
  4. Быстрый запуск (использует существующее ядро)
  5. Эффективное использование памяти (на 10+ контейнеров приходится меньше памяти)

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