Docker Desktop проти Docker у WSL: що насправді швидше?

Було корисно?

Якщо ваші контейнери працюють ніби крізь мокрий цемент у Windows, вам це не здається. Різниця в продуктивності між «Docker Desktop» і «Docker у WSL» є — але її часто неправильно розуміють. Більшість людей тестують не те, а потім «виправляють» проблему, ускладнюючи налаштування і ускладнюючи діагностику.

Я розкажу, що насправді швидше, чому, і як довести це на вашій машині менш ніж за годину — без культу налаштувань, які ви не згадаєте наступного кварталу.

Що ви насправді порівнюєте (і чому назви вводять в оману)

У Windows «Docker» як продукт і «Docker» як движок переплітаються. Люди кажуть «Docker Desktop повільний», коли мають на увазі «мої bind-монти повільні». Або кажуть «Docker у WSL швидший», коли випадково перенесли код у файлову систему Linux і перестали платити «податок» Windows файлової системи.

Визначимо дві конфігурації так, як це важливо для продуктивності:

  • Docker Desktop: Windows-додаток, який запускає Docker Engine всередині Linux VM. У сучасних версіях ця VM зазвичай базується на WSL2. Desktop додає інтеграції: UI, помічники облікових даних, мережеві зв’язки, шляхи доступу до файлів, розширення та налаштування політик.
  • Docker Engine всередині WSL2 («Docker у WSL»): ви встановлюєте і запускаєте Linux Docker Engine без Desktop. Контейнери працюють у тому ж середовищі WSL2 VM, але демон керується як звичайна Linux-служба.

Зверніть увагу, чого тут немає: сам рантайм контейнерів не змінюється магічно. Обидва варіанти в кінцевому підсумку працюють у контексті Linux-ядра (WSL2 VM). Різниця — у тому, де розташований демон, як налаштовано шар файлового доступу і скільки додаткових трансляційних шарів ви мимоволі додаєте.

Ось найкоротший спосіб мислити про це:

  • Якщо ваша задача обмежена CPU (компіляція, стиснення, криптографія), різниця між Desktop і WSL Engine зазвичай є похибкою вимірювання.
  • Якщо задача обмежена файловою системою (npm install, hot reload, language servers, великі моно-репозиторії), на перше місце виходять розташування файлів і тип монтування.
  • Якщо задача мережево-інтенсивна (багато локальних сервісів, проксів, VPN), деталі інтеграції та шляхи NAT можуть зробити одну конфігурацію «випадково» гіршою.

Цитата, тому що пасує: Werner Vogels має ідею, що все ламається постійно — тому ви проєктуєте й експлуатуєте, припускаючи відмови. Робота з продуктивністю схожа: припускайте, що найшвидший шлях деградуватиме, якщо ви не триматимете його простим і відстежуваним.

Жарт №1: Бенчмаркувати Docker на Windows, не перевіривши, де лежить ваш код — це як вимірювати час спортивного авто з затягнутим ручним гальмом. Ви отримаєте число, звісно.

Кілька фактів та історичний контекст для аргументів

Це не жарти для вікторин. Вони пояснюють, чому профіль продуктивності виглядає так, як виглядає.

  1. Docker на Windows спочатку сильно опирався на Hyper-V для запуску Linux VM, бо контейнери потребують Linux-ядра. Ранні налаштування мали помітніші накладні витрати і менш надійну мережу.
  2. WSL1 не був VM; він транслював виклики системи Linux у поведінку Windows. Це було хитро, але це не було «справжнім Linux», і багато контейнерних поведінок були незручними або неможливими.
  3. WSL2 перейшов на справжнє Linux-ядро в легкій VM, що зробило Linux-контейнери суміснішими — і часто швидшими для операцій у файловій системі, природних для Linux.
  4. Проблеми з файловою продуктивністю часто походять від перетину Windows/Linux (наприклад, доступ до /mnt/c з Linux). Ця межа має транслювати метадані, права і семантику повідомлень про зміни.
  5. Bind-монти не є за визначенням повільними; повільними є ті bind-монти, що проходять через віртуалізаційну межу. Linux-bind-монт всередині Linux-файлової системи зазвичай працює добре.
  6. Docker Desktop виріс у платформу, а не просто запуск демона. Додаткові функції корисні, але вони додають рухомих частин, які можуть вплинути на продуктивність і ускладнити діагностику.
  7. BuildKit змінив характеристики побудови Docker, покращивши кешування, паралелізм і кроки з mount. Але він також зробив певні файлові вузькі місця більш помітними.
  8. Сповіщення про зміни файлів у Windows відрізняються від Linux у граничних випадках; стеки hot reload можуть поводитися по-різному залежно від того, чи події передаються, чи відбувається опитування.

Звідки береться швидкість: CPU, диск, монтовані файлові системи та мережа

CPU: зазвичай не визначальний фактор

Задачі, обмежені CPU (Go/Rust збірки, gzip, тест-ранери, що не навантажують диск), зазвичай працюють схоже між Desktop і WSL Engine, бо обидва виконуються всередині одного WSL2-підтриманого середовища в сучасних налаштуваннях. Межа VM присутня в обох випадках. Питання в тому: чи ви випадково не додали зайві шари (наприклад, використовуєте Docker Desktop, але монтуєте Windows-шляхи з важкими bind-монтами)?

Диск I/O: тут більшість людей втрачає тиждень

Найбільша важіль швидкості на Windows для dev-контейнерів — це де зберігаються файли проєкту і як вони змонтовані.

  • Найкращий випадок: код зберігається у файловій системі Linux WSL2 (ext4 у VHDX дистро), і контейнери використовують томи або bind-монти, що залишаються в Linux. Швидка робота з метаданими, швидкі операції з дрібними файлами.
  • Найгірший випадок: код зберігається на NTFS (наприклад, C:\src) і ви монтуєте його в контейнери через межу (/mnt/c/src або механізм шарингу Desktop). Роботи з великою кількістю дрібних файлів сильно страждають.

Чому? Тому що «проста» операція на кшталт «stat 30 000 файлів» перетворюється на вечірку трансляцій: відображення метаданих, відображення прав, дивні кейси чутливості до регістру і інвалідації кешу. node_modules — це фактично тест на дрібні файли. Також це стосується Python virtualenv і Rust cargo registry.

Bind-монти проти томів: ваша прихована угода про продуктивність

Томи живуть у Linux-бекенді Docker (overlay2 на ext4 у WSL2). Вони зазвичай швидкі і передбачувані. Bind-монти віддзеркалюють хост-путь у контейнер. Якщо цей шлях на Windows — ви платите за трансляцію. Якщо шлях всередині дистро WSL2 — bind-монти можуть бути нормальними.

Порада у вигляді перекладу: зберігайте ваші залежності у Linux (томи), навіть якщо джерело має бути на Windows. А краще: тримайте обидва в Linux і використовуйте інтеграцію редактора для роботи з WSL-шляхами.

Мережа: в цілому добре, поки не зʼявляться VPN і localhost

WSL2 використовує NAT-мережу. Docker додає власну віртуальну мережеву логіку. Docker Desktop додає інтеграції, щоб localhost поводився так, як очікують користувачі Windows.

Проблеми з мережею зазвичай виглядають так:

  • таємничі стрибки латентності при підключеному корпоративному VPN
  • затримки DNS-резолюції всередині контейнерів
  • нестабільність переадресації портів між Windows ↔ WSL ↔ контейнер

Desktop частіше «просто працює» для публікації портів у Windows. WSL Engine може бути чистішим для Linux‑to‑Linux серісних мешів всередині WSL, але вам доведеться більше ручної роботи, щоб Windows-інструменти бачили ці сервіси.

Пам’ять і сторінковий кеш: тиха причина, чому одна конфігурація «відчувається» швидшою

Linux page cache — це сила продуктивності. Якщо ваша задача багаторазово читає ті самі дерева залежностей, кеш дуже допомагає. Але поведінка пам’яті WSL2 (динамічне виділення і звільнення) може робити продуктивність нестабільною, якщо VM позбавлена ресурсів або постійно «балониться». Desktop додає свої обмеження ресурсів і UI-налаштування, що можуть бути корисними — або ж обмежувати вас, якщо виставлені занадто низько.

Хто швидший для чого: проста матриця рішень

Універсального «хто завжди швидший» не існує. Є швидший варіант для вашого вузького місця. Ось практичні рекомендації.

Якщо хочете максимальної швидкості для файлово-інтенсивної розробки

Вибирайте Docker Engine всередині WSL2 і зберігайте репозиторії у файловій системі WSL (\\wsl$ з Windows; фактичне сховище під VHDX дистро). Використовуйте інструменти Linux‑рівня. Монтуйте з Linux-шляхів, а не з /mnt/c.

Якщо хочете максимально передбачуваний досвід розробника в змішаному Windows середовищі

Вибирайте Docker Desktop, особливо якщо вам потрібні GUI‑керування, помічники облікових даних, корпоративні проксі, перемикання Kubernetes або менше звернень «чому localhost не працює». Але все одно: якщо вам важлива швидкість — тримайте проєкт у WSL.

Якщо вузьке місце — збірки, а не live-reload

Будь-яка конфігурація може бути швидкою. Важливіше BuildKit, стратегія кешування і уникнення зайвих інвалідацій (копіювання всього репозиторію рано у Dockerfile або перевстановлення залежностей при кожній зміні).

Якщо у вас корпоративний VPN, що ламає DNS

Desktop часто має кращі налаштування та інтеграцію. WSL Engine може бути «чистішим», але ви ризикуєте розбиратися з resolv.conf і проксі Windows під вечір.

Жарт №2: Нічого так не пришвидшує зустріч «оптимізуємо Docker», як хтось, хто каже «в мене працює на ноуті». І тоді кожен ноут стає доказом.

Практичні завдання: команди, очікуваний вивід і що вирішувати

Це реальні перевірки, які я запускаю перед тим, як вірити будь-якому бенчмарку. Кожне завдання включає: команду, що означає вивід, і подальші кроки.

Завдання 1: Підтвердьте, де працює Docker (Desktop чи WSL Engine)

cr0x@server:~$ docker context ls
NAME                DESCRIPTION                               DOCKER ENDPOINT                             ERROR
default *           Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
desktop-linux       Docker Desktop                            unix:///var/run/docker.sock

Значення: Контексти показують, до якого демона ви підключені. Якщо бачите desktop-linux, ймовірно ви використовуєте демон Docker Desktop.

Рішення: Якщо ви порівнюєте, явно переключіться між контекстами і повторіть тести. Не «думайте», що переключилися — доведіть це.

Завдання 2: Визначте демон і драйвер зберігання

cr0x@server:~$ docker info --format '{{.ServerVersion}} {{.Driver}} {{.OperatingSystem}}'
27.3.1 overlay2 Docker Desktop

Значення: overlay2 на Linux — типовий випадок. Якщо не бачите overlay2, щось незвичне. Якщо не Linux — ви не в тому шляху, який мали на увазі.

Рішення: Якщо драйвер зберігання несподіваний — зупиніться. Ваша інспекція продуктивності буде вигаданою, поки це не виправите.

Завдання 3: Виміряйте, чи ваш проєкт на Windows або у файловій системі WSL

cr0x@server:~$ pwd
/mnt/c/src/myapp

Значення: /mnt/c — це Windows NTFS, змонтований у WSL. Якщо ваш проєкт тут і ви монтуєте його у контейнери, ви, ймовірно, платите «податок» межі.

Рішення: Якщо вам важлива швидкість — перемістіть репозиторій у Linux (наприклад, ~/src/myapp у WSL) і повторіть тести перед іншими змінами.

Завдання 4: Порівняйте операції з метаданими (тест «node_modules» без інсталяції)

cr0x@server:~$ time find . -type f | wc -l
48219

real    0m3.214s
user    0m0.112s
sys     0m0.988s

Значення: Це апроксимація вартості обходу великої кількості дрібних файлів. На /mnt/c це може бути значно повільніше, ніж всередині Linux.

Рішення: Якщо sys час високий, а real набагато перевищує очікування — ваш вузький контакт повʼязаний з трансляцією файлової системи. Виправляйте розташування/монти, а не CPU.

Завдання 5: Порівняйте продуктивність bind-монту всередині контейнера

cr0x@server:~$ docker run --rm -v "$PWD":/work -w /work alpine sh -lc 'time find . -type f >/dev/null'
real    0m4.02s
user    0m0.07s
sys     0m1.21s

Значення: Це вимірює шлях bind-монту з погляду контейнера. Якщо воно значно повільніше, ніж запуск find на хості, причина в мосту монтування.

Рішення: Якщо повільно — переключіться на репозиторій всередині Linux або використовуйте Docker-томи для директорій із важкими залежностями.

Завдання 6: Підтвердіть, куди ваш контейнер записує дані — в том чи bind-монт

cr0x@server:~$ docker inspect -f '{{range .Mounts}}{{.Type}} {{.Source}} -> {{.Destination}}{{"\n"}}{{end}}' myapp
bind /mnt/c/src/myapp -> /app
volume myapp_node_modules -> /app/node_modules

Значення: Гібридне налаштування часто найкраще: вихідний код через bind-монт, залежності через том.

Рішення: Якщо node_modules або target чи .venv знаходяться на bind-монті, підключеному до Windows — перемістіть їх у том.

Завдання 7: Перевірте версію WSL і стан дистро (із WSL)

cr0x@server:~$ wsl.exe -l -v
  NAME            STATE           VERSION
* Ubuntu-22.04    Running         2

Значення: Для продуктивності та сумісності ядра вам потрібен WSL2. WSL1 — інша історія.

Рішення: Якщо ви на WSL1 — мігруйте. Не налаштовуйте навколо цього.

Завдання 8: Перевірте, чи Docker Desktop — це демон, з яким ви розмовляєте (WSL інтеграція може плутати)

cr0x@server:~$ ps -ef | grep -E 'dockerd|containerd' | grep -v grep
root        2660       1  0 10:14 ?        00:00:02 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Значення: Якщо бачите dockerd всередині WSL дистро — ймовірно ви запускаєте Engine у WSL. Якщо ні — можливо все ще використовуєте Desktop‑socket інтеграцію.

Рішення: Визначте, хто володіє демоном: Desktop чи systemd у WSL. Уникайте напівпричетності, якщо хочете передбачуваної діагностики.

Завдання 9: Перевірте стан systemd у WSL (важливо для запуску Docker Engine як сервісу)

cr0x@server:~$ ps -p 1 -o comm=
systemd

Значення: Якщо PID 1 — systemd, ви можете керувати Docker як звичайною Linux-службою. Якщо ні — можливо ви використовуєте альтернативні методи ініціалізації.

Рішення: Якщо хочете стабільності WSL Engine — увімкніть systemd і запускайте Docker під ним.

Завдання 10: Виміряйте продуктивність збірки (BuildKit увімкнений, кеш працює)

cr0x@server:~$ DOCKER_BUILDKIT=1 docker build -t myapp:bench .
[+] Building 18.2s (12/12) FINISHED
 => [internal] load build definition from Dockerfile                                      0.0s
 => => transferring dockerfile: 1.23kB                                                    0.0s
 => [internal] load metadata for docker.io/library/node:20-alpine                         0.8s
 => [1/6] FROM docker.io/library/node:20-alpine@sha256:...                                0.0s
 => [internal] load .dockerignore                                                         0.0s
 => => transferring context: 2.31kB                                                       0.0s
 => [2/6] WORKDIR /app                                                                    0.1s
 => [3/6] COPY package*.json ./                                                           0.1s
 => [4/6] RUN npm ci                                                                      14.9s
 => [5/6] COPY . .                                                                        1.5s
 => [6/6] RUN npm test                                                                    0.8s
 => exporting to image                                                                    0.0s

Значення: Повільний крок очевидний. Якщо COPY . . повільний — контекст і шлях файлової системи погані. Якщо npm ci повільний — ви обмежені I/O або мережею.

Рішення: Якщо COPY повільний — виправте розташування репозиторію і .dockerignore. Якщо встановлення залежностей повільне — перенесіть кеші у томи і переконайтеся, що DNS/проксі не гальмує.

Завдання 11: Спостерігайте CPU‑тротлінг або конкуренцію за ресурси на хості

cr0x@server:~$ docker stats --no-stream
CONTAINER ID   NAME        CPU %     MEM USAGE / LIMIT     MEM %     NET I/O       BLOCK I/O      PIDS
c3a1d2e9f0b1   myapp       225.41%   612.3MiB / 7.6GiB     7.86%     12.4MB / 9MB  1.2GB / 38MB  34

Значення: Якщо CPU завантажений, а ви все одно повільні — можливо обмеження обчислень або призначені CPU занадто малі.

Рішення: Якщо CPU високий і кроки збірки обчислювально-важкі — виділіть більше CPU/пам’яті для WSL2/Desktop або зменшіть паралелізм у інструментах.

Завдання 12: Перевірте використання диска і де Docker зберігає дані

cr0x@server:~$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          27        6         9.812GB   5.104GB (52%)
Containers      14        2         1.102GB   812.4MB (73%)
Local Volumes   19        7         22.44GB   8.201GB (36%)
Build Cache     45        0         3.993GB   3.993GB

Значення: Надмірне зростання томів і кешу збірки може призвести до «диск став повільним», бо VHDX розширюється і хост-диск фрагментується або піддається тиску.

Рішення: Якщо reclaimable великий — очищуйте кеш збірки/непотрібні томи. Якщо хост-диск майже повний — припиніть вважати це проблемою лише Docker.

Завдання 13: Перевірте латентність DNS всередині контейнерів (мережева «повільність» часто означає DNS)

cr0x@server:~$ docker run --rm alpine sh -lc 'time nslookup registry-1.docker.io >/dev/null'
real    0m0.42s
user    0m0.01s
sys     0m0.01s

Значення: Якщо DNS займає секунди — інсталяції пакетів і pulls будуть повзти. VPN і split-DNS можуть викликати це.

Рішення: Якщо повільно — зосередьтеся на налаштуванні DNS (поведінка resolv.conf у WSL, налаштування DNS proxy у Desktop, корпоративні правила), а не на прапцях Docker.

Завдання 14: Виміряйте поведінку подій bind-монту для hot reload (inotify проти опитування)

cr0x@server:~$ docker run --rm -v "$PWD":/work -w /work alpine sh -lc 'apk add --no-cache inotify-tools >/dev/null && inotifywait -t 2 -e modify . || echo timeout'
Setting up watches.
Watches established.
timeout

Значення: Якщо події не надходять надійно, ваш інструмент hot reload може перейти на опитування, що спалює CPU і «відчувається» повільно.

Рішення: Якщо події не доходять через монти — перемістіть код у файлову систему WSL або налаштуйте watcher на опитування з розумними інтервалами (та прийміть витрати CPU).

Швидкий план діагностики (перша/друга/третя перевірки)

Це порядок, який найшвидше знайде вузьке місце в реальних командах. Не теорія — триаж.

Перше: ідентифікуйте межу, яку ви перетинаєте

  • Ваш репозиторій знаходиться під /mnt/c?
  • Ви bind-монтуєте Windows-шляхи в контейнери?
  • Ваші директорії залежностей живуть на Windows-підтримуваних монтах?

Якщо так: очікуйте повільних операцій з метаданими. Виправляйте розташування файлів/стратегію монтування перед будь-якими іншими налаштуваннями.

Друге: вирішіть, хто володіє демоном, і тримайте це послідовно

  • Ви використовуєте демон Docker Desktop через інтеграцію, чи dockerd, що запускається всередині WSL?
  • У вас встановлені обидва і ви іноді переключаєтеся, не помічаючи?

Якщо непослідовно: ваші виміри будуть змінюватись. Оберіть один варіант, задокументуйте його і примусьте команду дотримуватися контекстів або скриптів.

Третє: ізолюйте збірку vs runtime vs мережу

  • Збірка повільна? Перегляньте вивід docker build: що саме повільне — COPY, встановлення залежностей чи тести?
  • Робота в runtime повільна? Перевірте docker stats, патерни запису на диск і поведінку файлових подій.
  • Pull/install повільні? Перевірте латентність DNS і поведінку VPN/проксі.

Четверте: перевірте обмеження ресурсів і конкуренцію на хості

  • Чи WSL/Desktop обмежені 2 CPU і 2GB RAM, бо хтось «оптимізував» їх?
  • Чи диск хоста майже заповнений або під активним антивірусним скануванням?

Якщо так: ви не налаштовуєте Docker — ви налаштовуєте середовище хоста.

Три корпоративні історії з практики

Інцидент: неправильне припущення «WSL = швдикість Linux»

Середня компанія видала Windows-ноутбуки команді розробки, що раніше працювала на Linux. План був простий: «Використовувати WSL2, запускати Docker, і все ніби знову Linux». Першого тижня інженери жалілися, що тест-рання і встановлення залежностей жахливо повільні — але тільки для деяких репозиторіїв.

Команда припустила, що причина — накладні витрати Docker Desktop, почали видаляти Desktop, переходити на Docker Engine у WSL і тонко налаштовувати демон. Стало… трохи краще. Але не добре.

Справжня причина була нудна: репозиторії зберігалися на C:\ через політики бекапу і захисту кінцевих пристроїв. Розробники редагували код у Windows-інструментах, а WSL отримував доступ через /mnt/c. Їхні bind-монти перетинали межу, і робота була чудово збитою дрібними операціями з файлами.

Виправлення не було «переключити Docker». Це була виняткова політика і зміна робочого процесу: зберігати репозиторії в WSL для активної розробки, зберігати «експортовані» артефакти на Windows і використовувати інтеграцію IDE із WSL. Та сама конфігурація Docker раптом «виглядала» швидшою, бо файловій системі перестали навʼязувати переклади для кожного системного виклику.

Оптимізація, що обернулася проти: позбавлення VM ресурсів заради «економії батареї»

Інша команда хотіла, щоб ноутбуки під час поїздок працювали тихіше й холодніше. Хтось вирішив урізати ресурси WSL2/Docker: менше CPU, мала пам’ять, агресивне звільнення. На папері — менше шуму. На практиці збірки стали азартною грою.

Симптоми були дивні: перша збірка після перезавантаження була нормальною, друга — дуже повільна, потім краще, потім знову стояла. Інженери звинувачували кеші, Docker, гілки — класика.

Прихована поведінка була в тиску пам’яті. З надто малою RAM сторінковий кеш Linux не виконував свою роботу. Тим часом повторні компіляції й обходи залежностей руйнували кеш файлової системи і викликали swap-подібну поведінку всередині VM. Обмеження CPU підсилювали біль: менше паралелізму, довший час виконання, більше шансів на конфлікти фонового процесу.

Вони повернули розумні ліміти, а політику енергозбереження зробили явною та опційною. Мораль: «оптимізація», що прибирає запас потужності, породжує нестабільність, а нестабільність змушує інженерів не довіряти іншим метрикам.

Нудна, але правильна практика, що врятувала ситуацію: зафіксувати робочий процес і вимірювати по одному

У великій організації були користувачі Desktop і ті, хто працював з WSL Engine. Жаліби на продуктивність сипалися, але кожен тікет був неінформативним: «Docker повільний». Дуже корисно.

Інженер з SRE-підходом створив короткий внутрішній «контракт Docker на Windows»: де зберігаються репозиторії, який демон стандартний, як монтувати залежності і мінімальний скрипт бенчмарку, що вимірює обход файлів, час збірки і латентність DNS окремо. Це було не гламурно. Це був чекліст.

Коли стався інцидент — розробники не могли завантажити образи і пайплайни сповільнилися — команда запустила скрипт і одразу побачила сплески латентності DNS всередині контейнерів. Це вказало на зміну корпоративного DNS у взаємодії з VPN split tunneling. Без базових тестів вони витратили б дні на «тонування Docker».

Виправили політику DNS, а не Docker. Нудна практика принесла користь одразу, коли щось пішло не так у великих масштабах.

Поширені помилки: симптом → корінна причина → виправлення

1) «npm install займає вічність у контейнерах»

Симптом: встановлення залежностей у 5–20× повільніше за очікування; CPU низький; постійна диск-активність.

Корінна причина: залежності записуються на Windows-backed bind-монт (/mnt/c), що спричиняє повільні операції з метаданими.

Виправлення: зберігайте репозиторій у файловій системі WSL, або тримайте node_modules у Docker-томі й монтуйте лише вихідний код.

2) «Hot reload не тригериться, тож dev‑сервер опитує і спалює CPU»

Симптом: зміни файлів інколи не доходять; вентилятори шумлять; перезавантаження затримується.

Корінна причина: inotify-події не мостяться коректно через певні шляхи монтування; інструмент переходить на опитування.

Виправлення: перемістіть репозиторій у файлову систему WSL; або налаштуйте працівника спостереження на опитування з розумними інтервалами, якщо лишаєтесь на Windows-шляхах.

3) «Docker build повільний на COPY»

Симптом: COPY . . займає секунди чи хвилини; передача контексту важка.

Корінна причина: величезний контекст збірки через поганий .dockerignore; репозиторій на Windows-шляху; багато дрібних файлів.

Виправлення: покращіть .dockerignore; перемістіть репозиторій; переструктуруйте Dockerfile для максимальних кеш-хітів (копіюйте спочатку маніфести, потім встановлення, а потім код).

4) «Pulls і apt install інколи зависають на VPN»

Симптом: завантаження образів зависає; встановлення пакетів чекає на резолюцію імен.

Корінна причина: DNS всередині контейнерів повільний або зламаний через VPN split-DNS і NAT.

Виправлення: виміряйте латентність DNS; налаштуйте DNS для WSL/Desktop; скоординуйтеся з ІТ для коректної роботи резолверів.

5) «В мене швидко, а в нових співробітників повільно»

Симптом: на одних машинах все нормально, на інших жахливо, той же репозиторій.

Корінна причина: непослідовність у власності демона (Desktop vs WSL Engine), різні місця зберігання файлів, різні обмеження ресурсів.

Виправлення: стандартизувати: одна підтримувана конфігурація, одна рекомендація де зберігати репозиторій, один базовий скрипт діагностики.

6) «Диск зникає і все стає повільнішим з часом»

Симптом: збірки гальмують; диск майже повний; Docker показує багато reclaimable даних.

Корінна причина: кеш збірки і томи ростуть; VHDX WSL розширюється; диск хоста піддається тиску.

Виправлення: очищуйте непотрібні образи/томи/кеш збірки; моніторте диск хоста; не зберігайте нескінченні старі шари локально.

Контрольні списки / покроковий план

План A: ви хочете найшвидший цикл розробки на Windows

  1. Перенесіть активні репозиторії у файлову систему WSL: ~/src всередині вашого дистро.
  2. Використовуйте підтримку IDE для WSL, щоб редагування було зручним.
  3. Використовуйте Docker Engine всередині WSL2, якщо хочете мінімум шарів, або Desktop, якщо потрібна корпоративна інтеграція — але в будь‑якому випадку тримайте файли в WSL.
  4. Монтуйте код через Linux-шлях. Тримайте директорії залежностей у томах.
  5. Вимірюйте: час обходу файлів, час обходу у контейнері, час кроків збірки, латентність DNS.

План B: потрібно зберігати код на C:\ через корпоративну політику

  1. Прийміть, що /mnt/c повільніший для дрібних файлів. Не боріться зі шматком фізики.
  2. Використовуйте томи для важких директорій залежностей: node_modules, .venv, target, vendor, кеші інструментів.
  3. Налаштуйте поведінку спостерігачів: віддавайте перевагу опитуванню з розумними інтервалами, а не надії на inotify.
  4. Покращіть .dockerignore, щоб зменшити передачу контексту.
  5. Слідкуйте за винятками антивірусу/endpoint protection (з погодженням безпеки). Сканери люблять жувати дерева залежностей.

План C: ви оптимізуєте збірки, а не live‑розробку

  1. Увімкніть BuildKit; підтвердіть, що кеш працює.
  2. Переставте Dockerfile для кешування: копіюйте lock-файли першими, встановлюйте залежності, потім копіюйте код.
  3. Мінімізуйте контекст збірки через .dockerignore.
  4. Розділіть мережеві проблеми від дискових за допомогою перевірки DNS.
  5. Використовуйте багатоступеневі збірки там, де це зменшує розмір фінального образу без подовження часу перезбірки.

FAQ

1) Чи Docker Desktop завжди повільніший за Docker Engine у WSL2?

Ні. Для CPU-обмежених задач вони часто схожі. Великі виграші приходять від розміщення файлів у файловій системі WSL і уникнення Windows-backed bind-монтів.

2) Яке одне найсуттєвіше поліпшення продуктивності?

Перемістіть репозиторій з C:\ (доступ як /mnt/c) у файлову систему WSL дистро, а потім монтуйте з неї. Це прибирає шар трансляції з гарячих шляхів.

3) Чому bind-монти повільні у Windows?

Bind-монти, що перетинають межу Windows ↔ Linux, мають транслювати семантику файлової системи. Операції з дрібними файлами з цієї причини дорожчі. Томи уникають цього, перебуваючи в Linux-зберіганні.

4) Чи можна продовжувати користуватися Windows-редакторами, якщо репозиторій у WSL?

Так. Більшість сучасних редакторів мають інтеграцію з WSL. Ключове: зберігайте файли в Linux, редагуйте через міст, призначений для цього, і дозвольте контейнерам доступати до них без переходу NTFS.

5) Чи варто видаляти Docker Desktop, якщо я запускаю Docker Engine у WSL?

Якщо вам не потрібні функції Desktop, видалення може зменшити плутанину і фонову складність. Якщо в організації покладаються на інтеграції Desktop (проксі, сховище облікових даних, підтримка) — тримайте його, але ясно документуйте, який демон використовують.

6) Чому продуктивність змінюється після перезавантаження або сну?

Життєвий цикл WSL2 VM, «теплота» сторінкового кешу і динамічне виділення пам’яті впливають на відчуття швидкості. Холодні кеші завжди гірше виглядають. Обмеження ресурсів роблять поведінку непостійною.

7) Чи Kubernetes у Docker Desktop — проблема продуктивності?

Може бути, головним чином через споживання CPU/RAM і додатковий фоновий шум. Якщо ви не використовуєте його — вимкніть. Якщо використовуєте — виділіть ресурси відповідально, а не як демо.

8) Чи томи Docker завжди швидші за bind-монти?

Не завжди. Томи зазвичай швидші за Windows-backed bind-монти. Але bind-монт всередині файлової системи WSL може бути цілком швидким і зручним для розробки.

9) Як дізнатися, чи вузьке місце — DNS?

Заміряйте nslookup всередині контейнера. Якщо це займає секунди — ваші «повільні pulls» і «повільні installs» ймовірно через резолвер/VPN/проксі.

10) Що робити, якщо команда використовує Compose і воно повільне?

Compose підсилює файлові і watch-проблеми, бо часто монтує кілька сервісів з того самого репозиторію. Виправте монти й розміщення файлів спочатку, потім дивіться на використання ресурсів кожного сервісу.

Наступні кроки, які ви справді можете зробити цього тижня

  1. Визначте базу: вирішіть, чи стандарт для вас — Docker Desktop або WSL Engine. Стандартизujte контексти і скрипти, щоб люди не «випадково» порівнювали різні демони.
  2. Перенесіть один репозиторій у WSL і повторно виміряйте два показники: час обходу файлів за хостом і у bind-монтованому контейнері. Якщо бачите великий спад часу — ви знайшли головний важіль.
  3. Виправляйте монти стратегічно: тримайте код редагованим, але тримайте дерева залежностей у томах. Це кращий компроміс, коли політика змушує зберігати файли на Windows.
  4. Запустіть швидкий план діагностики при наступному скарзі «Docker повільний». Якщо не можете сказати, чи це файлова система, DNS чи обмеження ресурсів — ви не діагностуєте, а просто описуєте симптоми.
  5. Задокументуйте нудні правила (де лежать репозиторії, як монтувати, перевірка DNS, чистота кешу збірки). Це допоможе не витрачати час на ту саму інспекцію при кожному онбордингу.

Якщо хочете одну однозначну рекомендацію: помістіть ваш код у файлову систему Linux WSL2 і припиніть bind-монтувати NTFS у контейнери, якщо це не необхідно. Docker Desktop vs WSL Engine — вторинне; межа файлової системи — це головна битва.

← Попередня
Event Viewer для людей: знайдіть реальні помилки за 5 хвилин
Наступна →
Встановлення Ubuntu Server 24.04 LTS: мінімальна конфігурація, яка справді безпечна

Залишити коментар