БОЛЬ

Пятница, 18:47. Вы обновляете Python на сервере, где крутятся 5 микросервисов. apt upgrade python3 – и бот в Telegram падает, потому что ему нужен Python 3.10, а вы только что поставили 3.12. Заодно сломался Flask-сервис, который зависел от libssl1.1, а теперь стоит libssl3.

Знакомо? Это классика: конфликт зависимостей на общем хосте. Один apt update может положить всё, потому что 5 сервисов делят одну файловую систему, одни библиотеки, один Python.

Docker решает эту боль изоляцией: каждый сервис живёт в своём контейнере со своими зависимостями. Обновление Python в одном контейнере не трогает остальные.

КАК УСТРОЕНО

docker run – это точка входа в мир контейнеров. Одна команда берёт образ (image) и запускает из него изолированный процесс (контейнер).

Что происходит при docker run nginx:

  1. Docker ищет образ nginx локально
  2. Если нет – скачивает из Docker Hub
  3. Создаёт изолированный контейнер (namespaces + cgroups)
  4. Запускает процесс nginx внутри

Ключевые флаги, которые нужно знать:

ФлагЧто делаетПример
-dФоновый режим (detach)docker run -d nginx
-pПроброс порта host:container-p 8080:80
--nameИмя контейнера--name web
-eПеременная окружения-e DB_HOST=postgres
-vТом (volume)-v ./data:/app/data
--rmУдалить после остановкиdocker run --rm alpine echo hi
--networkСеть--network backend

ПРАКТИКА

Вам нужно запустить веб-приложение в контейнере: фоновый режим, проброс порта 8080 на 80, имя webapp, переменная NODE_ENV=production, том для данных.

Расставьте части команды docker run в правильном порядке

  • --name webapp
  • -v ./data:/app/data
  • -e NODE_ENV=production
  • node:22-alpine
  • -p 8080:80
  • docker run -d
Порядок флагов docker run: сначала команда docker run -d, затем все флаги (--name, -p, -e, -v), и в самом конце – имя образа. Образ всегда идёт последним, после него можно указать только команду для запуска внутри контейнера. Порядок флагов между собой не критичен, но образ обязательно в конце.

РАЗБОР

# Полная команда
docker run -d \
  --name webapp \
  -p 8080:80 \
  -e NODE_ENV=production \
  -v ./data:/app/data \
  node:22-alpine

Что здесь происходит:

  • docker run -d – запускаем контейнер в фоне, терминал не блокируется
  • --name webapp – даём контейнеру понятное имя вместо случайного angry_turing
  • -p 8080:80 – порт 8080 на хосте проксируется на порт 80 контейнера
  • -e NODE_ENV=production – переменная окружения, приложение знает что это прод
  • -v ./data:/app/data – локальная папка ./data монтируется внутрь контейнера, данные переживут рестарт
  • node:22-alpine – образ (всегда последний аргумент перед командой)

ВОПРОС НА СОБЕСЕ

Вопрос: Чем отличается контейнер от виртуальной машины?

Показать ответ

Контейнер – это изолированный процесс, который делит ядро ОС с хостом. VM – это полная эмуляция железа со своим ядром.

Практические отличия:

  • Запуск: контейнер стартует за миллисекунды, VM – за минуты
  • Размер: контейнер – мегабайты, VM – гигабайты
  • Изоляция: VM сильнее (своё ядро), контейнер – слабее (общее ядро)
  • Плотность: на одном хосте могут работать сотни контейнеров, но только десятки VM

Docker использует namespaces (изоляция PID, сети, файловой системы) и cgroups (лимиты CPU, RAM). Это не эмуляция – это ограничение видимости процесса в существующем ядре.