DevOps

Docker: основы

2013 год. Heroku инженер Solomon Hykes за 5 минут демонстрирует Docker на PyCon. Аудитория аплодирует стоя. Через год GitHub имеет 14 000 звёзд, Docker становится самым быстрорастущим open-source проектом в истории. Идея проста: если приложение работает в контейнере на ноутбуке разработчика - оно точно так же работает на production сервере. 'Works on my machine' исчезает как класс проблемы.

  • **Netflix** запускает 700+ типов микросервисов в Docker - каждый деплоится независимо по тысячи раз в день
  • **GitHub Actions** каждый CI/CD pipeline - это контейнер с известным окружением, не 'флакирующие тесты из-за версии Python'
  • **Cloudflare Workers** isolation model основан на той же namespace-изоляции что и Docker, только без overhead image слоёв

Solomon Hykes и рождение Docker

Docker Inc. выросла из dotCloud - PaaS компании, основанной Solomon Hykes в 2008 году. Внутренний инструмент для изоляции клиентских приложений был представлен публике в марте 2013. Идея не была революционной технически: Linux containers (LXC) существовали с 2008, namespaces с 2002, cgroups с 2006. Революцией стал UX: Dockerfile + image registry + простой CLI превратили сложную системную технологию в доступный инструмент для любого разработчика. К 2016 Docker стал де-факто стандартом контейнеризации, что привело к созданию OCI (Open Container Initiative) - нейтрального стандарта runtime и image format.

Dockerfile

**Dockerfile** - текстовый файл с инструкциями для сборки Docker image. Каждая инструкция создаёт отдельный слой в union filesystem; слои кэшируются и переиспользуются при повторных сборках. Цель - reproducible build: один и тот же Dockerfile даёт идентичный image на любом хосте в любое время.

ИнструкцияСоздаёт слойНазначение
FROMДаБазовый image - отправная точка
COPY / ADDДаКопирование файлов в image
RUNДаВыполнение команд при сборке
ENVДаПеременные окружения
EXPOSEНетДокументирование порта (не открывает!)
CMD / ENTRYPOINTНетКоманда запуска контейнера

**Порядок слоёв критичен для кэша**: инструкции с редко меняющимися данными (установка зависимостей) должны идти перед инструкциями с часто меняющимися (копирование исходников). Один изменённый слой инвалидирует все последующие.

Почему в Dockerfile рекомендуют копировать package.json до копирования исходного кода?

Images

**Docker image** - read-only шаблон для создания контейнеров. Структура: union filesystem из наложенных слоёв. Каждый слой - дельта изменений поверх предыдущего. Идентификация: content-addressable SHA256 digest, тег (name:tag) - мутабельный указатель на digest.

**Базовые images по размеру**: Ubuntu ~77MB, Debian Slim ~80MB, Alpine ~7MB, Distroless ~2MB, Scratch 0MB. Меньший image = быстрее pull в CI/CD, меньше attack surface. Alpine + musl libc подходит для большинства Go и Node приложений.

РеестрНазначениеОсобенности
Docker HubПубличные official imagesПо умолчанию в docker pull
GitHub Container RegistryImages из GitHub Actionsghcr.io, интеграция с GHCR
AWS ECR / GCR / ACRPrivate cloud registryIAM интеграция, geo-репликация
Self-hosted HarborOn-premises registryVulnerability scanning, RBAC

Два Docker image имеют одинаковый контент (одинаковые слои), но разные теги. Как хранится этот контент в Docker?

Containers

**Docker container** - запущенный экземпляр image. Технически: Linux namespace изоляция (pid, net, mnt, uts, ipc, user) + cgroups для ограничения ресурсов + тонкий writable слой поверх read-only image слоёв. Не виртуальная машина - процессы видны в host OS через `ps`, нет гипервизора.

**OOM Killer**: при достижении memory limit Linux OOM Killer убивает процесс в контейнере (exit code 137). Без `--memory` контейнер может съесть всю память хоста, убив соседние контейнеры. Всегда устанавливай memory limits в production.

Контейнер завершился с exit code 137. Что произошло?

Volumes

**Docker volumes** решают фундаментальную проблему: writable слой контейнера эфемерен - данные исчезают при удалении контейнера. Volumes - механизм persistent хранилища, управляемого Docker daemon вне файловой системы контейнера. Три типа монтирования с разными trade-offs.

ТипСинтаксисГде хранитсяКогда использовать
Named Volume-v mydata:/data/var/lib/docker/volumes/Production: БД, uploads, любые персистентные данные
Bind Mount-v /host/path:/container/pathПроизвольный путь на хостеРазработка: hot reload исходников
tmpfs Mount--tmpfs /tmpТолько RAMСекреты, временные файлы, тесты

**Secrets vs Volumes**: пароли и ключи НЕ стоит передавать через `-e` (видны в `docker inspect`). Docker Secrets (Swarm) или Kubernetes Secrets монтируются как tmpfs - в памяти, не на диске, не видны в метаданных контейнера.

Docker volumes - это просто папки на хосте, Docker здесь лишний посредник

Named volumes управляются Docker daemon: портируемы между хостами через volume drivers (NFS, cloud storage), имеют встроенный lifecycle management, поддерживают backup через `docker run --volumes-from`

Bind mounts действительно просто папки на хосте. Named volumes - абстракция поверх: driver может хранить данные на S3, NFS, iSCSI. При переносе контейнера на другой хост данные следуют за ним через volume driver.

PostgreSQL запущен в Docker без volumes. Что произойдёт с данными при `docker rm postgres-container`?

Ключевые идеи

  • **Dockerfile** - reproducible build: инструкции слой за слоем, кэш инвалидируется сверху-вниз - порядок инструкций критичен для скорости
  • **Image** - read-only шаблон из union filesystem слоёв, идентифицируется SHA256 digest, тег - мутабельный указатель
  • **Container** - изолированный процесс через Linux namespaces + cgroups, не VM. Exit 137 = SIGKILL (OOM или принудительный kill)
  • **Volume** - persistent хранилище вне ephemeral слоя контейнера: named volumes для production, bind mounts для dev, tmpfs для секретов

Вопросы для размышления

  • Компания переходит с bare-metal серверов на Docker. Разработчик предлагает упаковать весь монолит (nginx + app + PostgreSQL) в один контейнер для простоты. Какие конкретные проблемы создаёт такой подход и как их решить?

Связанные уроки

  • devops-01
  • devops-02
  • devops-03
  • cloud-01
  • se-04
  • devops-05
  • cloud-04
  • emb-04
  • bt-04-dns-tls
  • os-19-containers
  • os-12-virtualization
Docker: основы

0

1

Войти