🐳

Docker — Контейнеризация с нуля

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

Containers DevOps Microservices CI/CD
2013
Год создания
68K+
GitHub Stars
13M+
Разработчиков
#1
Среди контейнеров

🐳 Что такое Docker

Docker — это платформа для разработки, доставки и запуска приложений в контейнерах. Контейнер — это изолированная среда, которая содержит всё необходимое для работы приложения: код, библиотеки, системные инструменты.

📦 Аналогия: Контейнер = Коробка для переезда

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

Docker-контейнер — такая же "коробка" для приложения. Внутри — код, зависимости, настройки. Работает одинаково везде: на вашем ноутбуке, на сервере, в облаке.

Зачем нужен Docker?

Проблема "У меня работает": Код работает на вашем компьютере, но падает на сервере. Разные версии Python, библиотек, ОС — всё влияет.

Решение Docker: Упаковываете приложение со всеми зависимостями. Если работает в контейнере локально — будет работать везде.

Кто использует Docker?

  • Разработчики — одинаковая среда для всей команды
  • DevOps — простой деплой, CI/CD пайплайны
  • Тестировщики — изолированные среды для тестов
  • Компании — Google, Netflix, Spotify, Uber и миллионы других

🧱 Ключевые концепции

📄
Image (Образ)
Шаблон для создания контейнера. Как ISO-образ диска — read-only, содержит ОС, приложение, зависимости.
📦
Container (Контейнер)
Запущенный экземпляр образа. Изолированный процесс со своей файловой системой, сетью, процессами.
📝
Dockerfile
Текстовый файл с инструкциями для сборки образа. Рецепт: какую ОС взять, что установить, как запустить.
🏪
Docker Hub
Публичный реестр образов. Как GitHub, но для Docker-образов. Миллионы готовых образов: nginx, postgres, node и т.д.
💾
Volume (Том)
Постоянное хранилище данных. Контейнер удалили — данные остались. Для баз данных, файлов пользователей.
🌐
Network (Сеть)
Виртуальная сеть для контейнеров. Контейнеры могут общаться друг с другом по имени, изолированно от хоста.
💡 Связь концепций

Dockerfile → (сборка) → Image → (запуск) → Container

Один образ = много контейнеров. Как один рецепт торта = много тортов.

⚔️ Контейнеры vs Виртуальные машины

Контейнеры часто сравнивают с виртуальными машинами (VM). Оба обеспечивают изоляцию, но работают по-разному:

Архитектура: Контейнеры vs VM
🐳 Контейнеры
App 1
App 2
App 3
🐳 Docker Engine
🐧 Host OS (Linux)
🖥️ Hardware
VS
🖥️ Виртуальные машины
App + Guest OS
App + Guest OS
App + Guest OS
Hypervisor (VMware, VirtualBox)
🐧 Host OS
🖥️ Hardware

Сравнение

Параметр 🐳 Контейнеры 🖥️ VM
Размер МБ (10-500 MB) ГБ (1-20 GB)
Запуск Секунды Минуты
Изоляция Процессы (namespace) Полная (отдельная ОС)
Ресурсы Минимальный overhead Значительный overhead
Плотность 100+ на хосте 5-20 на хосте
ОС Общее ядро с хостом Своя ОС
🎯 Когда что использовать

Контейнеры: Микросервисы, CI/CD, разработка, когда нужна скорость и эффективность.

VM: Когда нужна полная изоляция, разные ОС на одном железе, legacy-приложения, требования безопасности.

⚙️ Установка Docker

1
macOS
Скачайте и установите Docker Desktop. Включает Docker Engine, CLI, Docker Compose.
Terminal
$ brew install --cask docker
# Или скачайте .dmg с сайта
2
Windows
Скачайте Docker Desktop for Windows. Требуется WSL 2 (Windows Subsystem for Linux).
PowerShell
# Сначала включите WSL 2
> wsl --install
# Перезагрузитесь, затем установите Docker Desktop
3
Linux (Ubuntu/Debian)
Установка через apt. Официальная инструкция на docs.docker.com.
Terminal
# Добавляем репозиторий Docker
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh
# Добавляем пользователя в группу docker
$ sudo usermod -aG docker $USER
# Перелогиньтесь для применения
4
Проверка установки
Убедитесь, что Docker работает:
Terminal
$ docker --version
Docker version 24.0.7, build afdd53b
$ docker compose version
Docker Compose version v2.23.0

👋 Hello World — Первый контейнер

Запустим ваш первый контейнер! Docker предоставляет специальный тестовый образ hello-world:

Terminal — Первый контейнер
$ docker run hello-world
Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world c1ec31eb5944: Pull complete Digest: sha256:4bd78111... Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. 3. The Docker daemon created a new container from that image. 4. The Docker daemon streamed that output to the Docker client.
🎉 Поздравляем!

Вы только что запустили свой первый Docker-контейнер! Что произошло:

1. Docker не нашёл образ локально
2. Скачал его с Docker Hub
3. Создал контейнер из образа
4. Запустил контейнер, который вывел сообщение
5. Контейнер завершился

Запустим что-то полезное — Nginx

Terminal — Nginx в контейнере
# Запускаем Nginx на порту 8080
$ docker run -d -p 8080:80 --name my-nginx nginx
a1b2c3d4e5f6... (ID контейнера) # -d = запуск в фоне (detached) # -p 8080:80 = порт хоста:порт контейнера # --name = имя контейнера # nginx = имя образа
$ curl http://localhost:8080
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...

Откройте http://localhost:8080 в браузере — вы увидите страницу приветствия Nginx!

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

Terminal
# Список запущенных контейнеров
$ docker ps
CONTAINER ID IMAGE COMMAND PORTS NAMES a1b2c3d4e5f6 nginx "/docker-entrypoint.…" 0.0.0.0:8080->80/tcp my-nginx
$ docker stop my-nginx
my-nginx
$ docker start my-nginx
my-nginx
$ docker rm -f my-nginx
# Удаляем контейнер (с остановкой)

📝 Dockerfile — Создаём свой образ

Dockerfile — это рецепт для создания образа. Давайте создадим образ для простого Python-приложения:

Шаг 1: Создаём приложение

Python app.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
return '🐳 Hello from Docker! 🎉'

@app.route('/health')
def health():
return 'OK'

if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
Text requirements.txt
flask==3.0.0
gunicorn==21.2.0

Шаг 2: Создаём Dockerfile

Dockerfile Dockerfile
# Базовый образ — Python 3.11 на Alpine Linux (минимальный размер)
FROM python:3.11-alpine

# Метаданные
LABEL maintainer="you@example.com"
LABEL version="1.0"

# Рабочая директория внутри контейнера
WORKDIR /app

# Копируем файл зависимостей отдельно (для кеширования слоёв)
COPY requirements.txt .

# Устанавливаем зависимости
RUN pip install --no-cache-dir -r requirements.txt

# Копируем код приложения
COPY app.py .

# Переменные окружения
ENV FLASK_APP=app.py
ENV FLASK_ENV=production

# Открываем порт
EXPOSE 5000

# Команда запуска (production-ready с gunicorn)
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]

Шаг 3: Собираем и запускаем

Terminal — Сборка образа
# Собираем образ (точка = текущая директория)
$ docker build -t my-python-app:1.0 .
[+] Building 15.2s (10/10) FINISHED => [1/5] FROM python:3.11-alpine => [2/5] WORKDIR /app => [3/5] COPY requirements.txt . => [4/5] RUN pip install --no-cache-dir -r requirements.txt => [5/5] COPY app.py . => exporting to image => => naming to docker.io/library/my-python-app:1.0 ✓ Successfully built my-python-app:1.0
$ docker images
REPOSITORY TAG IMAGE ID SIZE my-python-app 1.0 abc123def456 58MB python 3.11 xyz789... 1.01GB
$ docker run -d -p 5000:5000 --name myapp my-python-app:1.0
abc123def456... # Проверяем
$ curl http://localhost:5000
🐳 Hello from Docker! 🎉
💡 Best Practices для Dockerfile

Минимальный базовый образ — используйте alpine или slim версии
Кеширование слоёв — COPY requirements.txt до COPY кода
Один процесс — один контейнер = один процесс
Не запускайте от root — создайте отдельного пользователя
.dockerignore — исключайте ненужные файлы (node_modules, .git)

Файл .dockerignore

Text .dockerignore
# Игнорируем при сборке (как .gitignore)
.git
.gitignore
__pycache__
*.pyc
*.pyo
.env
.venv
venv
node_modules
*.log
.DS_Store
Dockerfile
docker-compose*.yml
README.md

🛠️ Среды разработки и тестирования

Одна из главных суперсил Docker — создание одинаковых сред для всей команды и всех этапов: разработка → тестирование → продакшен.

🎯 Зачем нужны контейнеры для разработки?

Проблема: "У Васи Python 3.8, у Пети 3.11, на сервере 3.9. У всех разные версии библиотек. Код работает по-разному."

Решение: Docker-контейнер с фиксированными версиями всего. Работает одинаково у всех и везде.

Примеры готовых сред

🐘
PostgreSQL для разработки
База данных за 10 секунд
Не нужно устанавливать PostgreSQL на свою машину. Запустите контейнер — готово.
docker run -d \
  --name postgres-dev \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=myapp \
  -p 5432:5432 \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16-alpine
🔴
Redis для кеширования
In-memory хранилище
Redis для сессий, кеша, очередей. Одна команда — и работает.
docker run -d \
  --name redis-dev \
  -p 6379:6379 \
  redis:alpine
🍃
MongoDB
NoSQL база данных
Документо-ориентированная БД для прототипирования и разработки.
docker run -d \
  --name mongo-dev \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secret \
  -p 27017:27017 \
  mongo:7
🐰
RabbitMQ
Message Broker
Очереди сообщений с веб-интерфейсом для мониторинга.
docker run -d \
  --name rabbitmq-dev \
  -p 5672:5672 \
  -p 15672:15672 \
  rabbitmq:3-management
🔍
Elasticsearch
Поисковый движок
Полнотекстовый поиск и аналитика для вашего приложения.
docker run -d \
  --name elastic-dev \
  -e "discovery.type=single-node" \
  -e "xpack.security.enabled=false" \
  -p 9200:9200 \
  elasticsearch:8.11.0
📧
Mailhog
Тестовый почтовый сервер
Перехватывает все письма. Идеально для тестирования email без спама.
docker run -d \
  --name mailhog \
  -p 1025:1025 \
  -p 8025:8025 \
  mailhog/mailhog

Docker Compose — Несколько сервисов вместе

Когда нужно запустить несколько контейнеров (приложение + БД + Redis), используйте Docker Compose:

YAML docker-compose.yml
version: '3.8'

services:
  # Наше приложение
  app:
    build: .
    ports:
      - "5000:5000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    volumes:
      - .:/app  # Для hot-reload при разработке

  # PostgreSQL
  db:
    image: postgres:16-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=myapp
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  # Redis
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"

  # Adminer — веб-интерфейс для БД
  adminer:
    image: adminer
    ports:
      - "8080:8080"

volumes:
  pgdata:
Terminal — Docker Compose
# Запуск всех сервисов
$ docker compose up -d
[+] Running 4/4 ✔ Container myapp-redis-1 Started ✔ Container myapp-db-1 Started ✔ Container myapp-adminer-1 Started ✔ Container myapp-app-1 Started
$ docker compose ps
NAME STATUS PORTS myapp-app-1 Up 2 minutes 0.0.0.0:5000->5000/tcp myapp-db-1 Up 2 minutes 0.0.0.0:5432->5432/tcp myapp-redis-1 Up 2 minutes 0.0.0.0:6379->6379/tcp myapp-adminer-1 Up 2 minutes 0.0.0.0:8080->8080/tcp
$ docker compose logs -f app
# Логи приложения в реальном времени
$ docker compose down
# Останавливаем всё
🚀 Преимущества Docker для разработки

Onboarding за минуты — новый разработчик: git clone + docker compose up
Изолированные проекты — разные версии Python/Node для разных проектов
Чистая система — ничего не устанавливается на хост
Идентичность prod/dev — те же образы, что и в продакшене
Тестирование — запуск тестов в чистом окружении

⌨️ Основные команды Docker

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

Команда Описание
docker pull nginx Скачать образ из Docker Hub
docker images Список локальных образов
docker build -t myapp:1.0 . Собрать образ из Dockerfile
docker rmi nginx Удалить образ
docker push myapp:1.0 Загрузить образ в реестр

Работа с контейнерами

Команда Описание
docker run -d -p 80:80 nginx Создать и запустить контейнер
docker ps Список запущенных контейнеров
docker ps -a Все контейнеры (включая остановленные)
docker stop <id/name> Остановить контейнер
docker start <id/name> Запустить остановленный контейнер
docker rm <id/name> Удалить контейнер
docker exec -it <name> bash Зайти внутрь контейнера
docker logs -f <name> Логи контейнера в реальном времени

Docker Compose

Команда Описание
docker compose up -d Запустить все сервисы
docker compose down Остановить и удалить
docker compose ps Статус сервисов
docker compose logs -f Логи всех сервисов
docker compose build Пересобрать образы
docker compose exec app bash Зайти в контейнер сервиса

Очистка системы

Команда Описание
docker system prune Удалить неиспользуемые данные
docker system prune -a + все неиспользуемые образы
docker volume prune Удалить неиспользуемые тома
docker system df Сколько места занимает Docker

🔄 Альтернативы Docker

Docker — не единственное решение для контейнеризации. Вот популярные альтернативы и когда их использовать:

Лидер рынка
🐳
Docker
Docker, Inc.
Стандарт индустрии. Огромная экосистема, Docker Hub, Docker Compose, отличная документация.
  • Самый популярный
  • Docker Hub — миллионы образов
  • Отличный DX (Developer Experience)
  • Docker Desktop для Win/Mac
Растущий
🦭
Podman
Red Hat
"Rootless" альтернатива Docker. Совместим с Docker CLI. Не требует демона.
  • Без демона (daemonless)
  • Работает без root
  • Совместим с Dockerfile
  • Меньше экосистема
📦
containerd
CNCF
Runtime низкого уровня. Используется внутри Docker и Kubernetes. Для продвинутых сценариев.
  • Используется в Kubernetes
  • Легковесный
  • Нет CLI для людей
  • Не для разработчиков
🚀
CRI-O
Red Hat / CNCF
Легковесный runtime для Kubernetes. Минималистичный, только то, что нужно K8s.
  • Создан для Kubernetes
  • Минимальный overhead
  • Только для K8s
  • Нельзя использовать standalone
🔒
LXC / LXD
Canonical
Контейнеры уровня системы (как VM, но легче). Для запуска полноценных Linux-дистрибутивов.
  • Полноценная ОС в контейнере
  • Systemd работает
  • Не для микросервисов
  • Тяжелее Docker
☸️
Kubernetes
Google / CNCF
Не альтернатива, а уровень выше. Оркестрация контейнеров. Использует Docker/containerd внутри.
  • Автомасштабирование
  • Self-healing
  • Для продакшена
  • Сложность настройки
🎯 Что выбрать?

Для разработки: Docker — стандарт, лучший DX
Для безопасности: Podman — rootless из коробки
Для Kubernetes: containerd или CRI-O
Для VM-подобных контейнеров: LXC/LXD

В 99% случаев — начните с Docker. Переходите на альтернативы, когда появятся конкретные причины.

Частые вопросы

Docker Engine — полностью бесплатный и open-source (Apache 2.0).

Docker Desktop — бесплатный для личного использования и небольших компаний (до 250 сотрудников и $10M выручки). Для крупных компаний — платная подписка ($5-21/мес).

Альтернатива: На Linux можно использовать Docker Engine напрямую. Или Podman — полностью бесплатный.
Практически нет. Контейнеры — это не виртуализация, а изоляция процессов.

• CPU: ~0% overhead
• Memory: ~0% overhead
• Disk I/O: ~1-3% overhead (overlay filesystem)
• Network: ~1% overhead

Для большинства приложений разница незаметна.
Контейнеры — immutable (неизменяемые). Не обновляйте контейнер — замените его:

1. Соберите новый образ с обновлённым кодом
2. Остановите старый контейнер
3. Запустите новый контейнер из нового образа

docker build -t myapp:2.0 .
docker stop myapp && docker rm myapp
docker run -d --name myapp myapp:2.0

Или используйте Docker Compose / Kubernetes для автоматизации.
По умолчанию — нигде. Данные внутри контейнера исчезают при удалении.

Решение — Volumes:
docker run -v mydata:/app/data ...

Volume хранится на хосте, переживает удаление контейнера.

Для баз данных всегда используйте volumes:
docker run -v pgdata:/var/lib/postgresql/data postgres
Да, но с осторожностью. Есть два подхода:

1. Docker-in-Docker (dind):
Запуск полноценного Docker daemon внутри контейнера. Используется в CI/CD.

2. Docker-out-of-Docker:
Монтирование socket хоста внутрь контейнера:
docker run -v /var/run/docker.sock:/var/run/docker.sock ...

⚠️ Второй вариант даёт контейнеру полный контроль над Docker хоста — небезопасно!
Да, с нюансами. Docker Desktop на Windows использует:

WSL 2 (рекомендуется) — настоящее ядро Linux в Windows
Hyper-V — легковесная VM с Linux

Linux-контейнеры работают внутри Linux (WSL2/VM). Есть также Windows-контейнеры (для .NET Framework), но они редко используются.

Для разработчика разницы практически нет — всё работает одинаково.
Сотни и тысячи — зависит от ресурсов хоста и самих контейнеров.

Контейнер — это просто процесс. Если каждый использует 50MB RAM, на сервере с 32GB можно запустить 500+ контейнеров.

На практике:
• Ноутбук разработчика: 10-30 контейнеров
• Продакшен-сервер: 50-200 контейнеров
• Kubernetes-кластер: тысячи контейнеров
🐳 Docker — Итоги
📦
Что это
Платформа контейнеризации приложений
🎯
Зачем
"Works on my machine" → Works everywhere
Скорость
Старт за секунды, минимальный overhead
🛠️
Инструменты
Docker CLI, Compose, Docker Hub
📝
Ключевое
Dockerfile → Image → Container
🔄
Альтернативы
Podman, containerd, LXC
🚀 Следующие шаги

1. Установите Docker — Docker Desktop для Win/Mac или Docker Engine для Linux
2. Запустите hello-worlddocker run hello-world
3. Контейнеризируйте свой проект — напишите Dockerfile
4. Изучите Docker Compose — для нескольких сервисов
5. Переходите к Kubernetes — когда нужна оркестрация

Docker — один из важнейших инструментов современного разработчика. Потратьте день на изучение — сэкономите месяцы в будущем.

© 2025 • Написано для разработчиков, которые хотят освоить Docker

Docker version 24.x • Compose v2.x