Skip to main content

Що таке Docker і навіщо він потрібен?

Docker - відкрита платформа, яка пакує застосунок і його залежності в один ізольований модуль під назвою container (контейнер), щоб одне і те саме програмне забезпечення запускалось ідентично на лептопі, у CI і на проді.

Теорія

TL;DR

  • Docker = формат пакування + рантайм: збираєш один раз, запускаєш всюди, де є Docker engine
  • Container це процес, ізольований від хоста через можливості Linux kernel (namespaces і cgroups), а не маленька VM
  • Розв'язує клас багів «у мене працює» бо рантайм їде разом з кодом
  • Стандарт індустрії з виходу Docker Engine 1.0 у 2014; актуальна стабільна гілка 29.x (квітень 2026)
  • Беремо коли потрібен паритет середовищ, швидкі деплої, ізоляція сервісів. Не беремо для статики і одноразових скриптів

Швидкий приклад

bash
$ docker run -p 8080:80 nginx Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx e4fff0779e6d: Pull complete 2c5c0f9c49b1: Pull complete Status: Downloaded newer image for nginx:latest 2026/04/30 10:24:01 [notice] 1#1: nginx/1.27.4

Ця одна команда стягнула готовий image nginx, запустила його ізольовано від хоста і пробросила порт 80 всередині container на 8080 на лептопі. Без встановлення nginx, без конфіг-файлів, без сміття після зупинки.

Чому команди реально перейшли

До Docker задеплоїти сервіс означало мати runbook: встановити Node 16, libpng, скопіювати ось ці env-змінні, запустити міграцію. Кожне середовище дрейфувало окремо. Docker звертає це у єдиний артефакт під назвою image, який ти збираєш раз і запускаєш всюди ідентично. Жарт «у мене на компі працює» перестав бути жартом, коли деви побачили, що image, протестований локально, побітово ідентичний тому, що крутиться у проді.

Коли тягнутися за Docker

  • Кілька сервісів живуть на одному хості, але потребують різних версій рантайму (Python 3.11 і Python 3.13 на одній машині)
  • CI має відтворити продакшен-середовище точно
  • Новачок у команді клонує репо і піднімає весь стек однією командою (docker compose up)
  • Ти деплоїшся до кількох cloud-провайдерів і не хочеш бути прив'язаним до AWS-специфічного тулінгу

Коли Docker не потрібен

Статичний сайт, що йде на CDN, нічого не отримає від container. Короткий shell-скрипт, який запускається раз, не треба загортати. Embedded-системам зі строгими обмеженнями пам'яті 30 MB оверхеду відчутні. Точка беззбитковості зазвичай два-три сервіси з різними рантаймами, або CI-пайплайн, що вимагає відтворюваності. Нижче цього складність коштує більше, ніж економить консистентність.

Як це насправді запускається

Docker не є віртуальною машиною. Коли ти робиш docker run nginx, Docker daemon (dockerd) просить container runtime (containerd, далі runc) запустити процес nginx на kernel хоста. Цей процес отримує свою власну в'юху файлової системи, мережевих інтерфейсів і PID через Linux namespaces. Ліміти на CPU і пам'ять приходять з cgroups. Процес nginx думає, що він сам на машині; kernel хоста знає, що це просто ще один процес з додатковими обмеженнями. Тому container стартує за мілісекунди, а VM за десятки секунд.

Типові помилки

Сприймати container як довгоживучий сервер

bash
# НЕПРАВИЛЬНО: заходити всередину і ставити пакети docker exec -it mycontainer apt-get install vim # Ці зміни зникнуть при перезапуску container. # ПРАВИЛЬНО: запекти все потрібне у Dockerfile FROM nginx:1.27 RUN apt-get update && apt-get install -y vim

Container задумано як замінний. Все, що ти змінюєш всередині запущеного, втрачається при наступному рестарті, якщо це не у volume.

Плутати image і container у розмові

bash
$ docker images # список image (шаблони) $ docker ps # список запущених container (екземпляри) $ docker rm <id> # видалити container $ docker rmi <id> # видалити image

Image це креслення. Container це запущена штука. У них окремі команди, і плутанина між ними коштує новачкам першої години.

Запускати все під root

dockerfile
# НЕПРАВИЛЬНО: дефолтний користувач root, container escape стає страшнішим FROM node:22 COPY . /app CMD ["node", "app.js"] # ПРАВИЛЬНО: скинути привілегії FROM node:22 COPY . /app USER node CMD ["node", "app.js"]

Container поділяє kernel з хостом. Процес під root всередині залишається процесом під root, якщо вирветься з namespace.

Реальне застосування

  • Netflix: деви будують і тестують microservices у Docker container, потім деплоять у AWS. Ідентичність image від лептопа до проду прибрала цілий клас «deploy regression» багів.
  • Spotify: роками крутили самописний оркестратор (Helios) поверх Docker, перш ніж мігрувати на Kubernetes. Створення сервісу, що раніше займало годину, після міграції стало хвилинами.
  • PayPal, Uber, Airbnb: Docker як стандартний CI-артефакт. PR-білд генерує image, інтеграційні тести бігають проти нього, image заливається у registry і йде у деплой.
  • Локальна розробка: docker compose up піднімає Postgres, Redis і застосунок одразу замість brew install п'яти речей і пам'ятати версії.

Одного разу я два дні шукав мисматч між Node 16 на dev і Node 14 на проді, який зник того дня, коли ми загорнули обидва у однакові Docker images. Саме для цього класу багів Docker і існує.

Питання для поглиблення

Q: Якщо Docker не VM, чому відчуття таке саме?


A: Бо ізоляція достатньо хороша, щоб процеси всередині не бачили нічого зовні. Але це процес на kernel твого хоста, а не гостьова операційна система. Саме тому container запускається у мілісекундах, а VM у десятки секунд.

Q: Що Docker реально ставить на машину?


A: Docker Engine. Це dockerd (фоновий daemon), docker (CLI client), containerd (власне container runtime) і кілька CLI-помічників. На Mac і Windows він пакує маленьку Linux VM, бо container'ам потрібен Linux kernel.

Q: Docker це те саме що Kubernetes?


A: Ні. Docker будує і запускає окремі container на одному хості. Kubernetes оркеструє багато container на багатьох хостах і вирішує речі типу рестартів, rolling-апдейтів і service discovery. Більшість продакшен-команд використовують обидва.

Q: Чому деякі команди беруть Podman або nerdctl замість docker?


A: Той самий OCI image-формат, ті самі workflow, але без daemon (Podman) або тонший стек (nerdctl лежить прямо на containerd). Має значення у регульованих середовищах, де живий root-daemon сам собою проблема для безпеки.

Q: (Senior) Коли Docker стає неправильним інструментом?


A: Коли оверхед і складність переважують виграш у консистентності. Статичний сайт за CDN нічого не отримає. Команда з одним Go-бінарником і одним сервером отримує дуже мало. Точка беззбитковості зазвичай два-три сервіси з різними рантаймами, або CI-пайплайн, що вимагає відтворюваності. Нижче цього ти платиш за можливості, які не використаєш.

Приклади

Запуск одноразової бази для локальної розробки

bash
$ docker run -d --name pg \ -e POSTGRES_PASSWORD=devpass \ -p 5432:5432 \ postgres:16 # Підключення з застосунку $ psql -h localhost -U postgres

Без встановлення Postgres на хост, без сервісу, який треба підтримувати. Зупинка і видалення docker rm -f pg. Хочеш Postgres 17 наступного місяця? Заміни 16 на 17. Жодних конфліктів, жодних залишків даних, поки явно не попросиш.

Пакування власного Node-застосунку

dockerfile
# Dockerfile FROM node:22-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev COPY . . USER node EXPOSE 3000 CMD ["node", "server.js"]
bash
$ docker build -t myapp:0.1 . $ docker run -p 3000:3000 myapp:0.1

Тепер будь-який тіммейт робить git pull && docker build -t myapp:0.1 . && docker run -p 3000:3000 myapp:0.1 і отримує ту саму версію Node, ті самі залежності, той самий рантайм, що у проді. Dockerfile це рецепт збірки; image це результат; container це запущений екземпляр.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Коментарі

Ще немає коментарів