Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке Docker і навіщо він потрібен?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Docker** - відкрита платформа, що пакує застосунок з його залежностями у портативний ізольований модуль під назвою container (контейнер). Image збираєш один раз і запускаєш ідентично всюди, де встановлений Docker engine. ```bash docker run -p 8080:80 nginx # стягне image nginx, запустить ізольовано, прокине порт 80 на хост ``` **Головне:** Docker зводить «встановити, налаштувати, запустити» в один артефакт (image), який поводиться однаково на лептопі, у CI і у проді.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**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 це запущений екземпляр.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.