Якщо ваші контейнери працюють ніби крізь мокрий цемент у 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, не перевіривши, де лежить ваш код — це як вимірювати час спортивного авто з затягнутим ручним гальмом. Ви отримаєте число, звісно.
Кілька фактів та історичний контекст для аргументів
Це не жарти для вікторин. Вони пояснюють, чому профіль продуктивності виглядає так, як виглядає.
- Docker на Windows спочатку сильно опирався на Hyper-V для запуску Linux VM, бо контейнери потребують Linux-ядра. Ранні налаштування мали помітніші накладні витрати і менш надійну мережу.
- WSL1 не був VM; він транслював виклики системи Linux у поведінку Windows. Це було хитро, але це не було «справжнім Linux», і багато контейнерних поведінок були незручними або неможливими.
- WSL2 перейшов на справжнє Linux-ядро в легкій VM, що зробило Linux-контейнери суміснішими — і часто швидшими для операцій у файловій системі, природних для Linux.
- Проблеми з файловою продуктивністю часто походять від перетину Windows/Linux (наприклад, доступ до
/mnt/cз Linux). Ця межа має транслювати метадані, права і семантику повідомлень про зміни. - Bind-монти не є за визначенням повільними; повільними є ті bind-монти, що проходять через віртуалізаційну межу. Linux-bind-монт всередині Linux-файлової системи зазвичай працює добре.
- Docker Desktop виріс у платформу, а не просто запуск демона. Додаткові функції корисні, але вони додають рухомих частин, які можуть вплинути на продуктивність і ускладнити діагностику.
- BuildKit змінив характеристики побудови Docker, покращивши кешування, паралелізм і кроки з mount. Але він також зробив певні файлові вузькі місця більш помітними.
- Сповіщення про зміни файлів у 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
- Перенесіть активні репозиторії у файлову систему WSL:
~/srcвсередині вашого дистро. - Використовуйте підтримку IDE для WSL, щоб редагування було зручним.
- Використовуйте Docker Engine всередині WSL2, якщо хочете мінімум шарів, або Desktop, якщо потрібна корпоративна інтеграція — але в будь‑якому випадку тримайте файли в WSL.
- Монтуйте код через Linux-шлях. Тримайте директорії залежностей у томах.
- Вимірюйте: час обходу файлів, час обходу у контейнері, час кроків збірки, латентність DNS.
План B: потрібно зберігати код на C:\ через корпоративну політику
- Прийміть, що
/mnt/cповільніший для дрібних файлів. Не боріться зі шматком фізики. - Використовуйте томи для важких директорій залежностей:
node_modules,.venv,target,vendor, кеші інструментів. - Налаштуйте поведінку спостерігачів: віддавайте перевагу опитуванню з розумними інтервалами, а не надії на inotify.
- Покращіть
.dockerignore, щоб зменшити передачу контексту. - Слідкуйте за винятками антивірусу/endpoint protection (з погодженням безпеки). Сканери люблять жувати дерева залежностей.
План C: ви оптимізуєте збірки, а не live‑розробку
- Увімкніть BuildKit; підтвердіть, що кеш працює.
- Переставте Dockerfile для кешування: копіюйте lock-файли першими, встановлюйте залежності, потім копіюйте код.
- Мінімізуйте контекст збірки через
.dockerignore. - Розділіть мережеві проблеми від дискових за допомогою перевірки DNS.
- Використовуйте багатоступеневі збірки там, де це зменшує розмір фінального образу без подовження часу перезбірки.
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-проблеми, бо часто монтує кілька сервісів з того самого репозиторію. Виправте монти й розміщення файлів спочатку, потім дивіться на використання ресурсів кожного сервісу.
Наступні кроки, які ви справді можете зробити цього тижня
- Визначте базу: вирішіть, чи стандарт для вас — Docker Desktop або WSL Engine. Стандартизujte контексти і скрипти, щоб люди не «випадково» порівнювали різні демони.
- Перенесіть один репозиторій у WSL і повторно виміряйте два показники: час обходу файлів за хостом і у bind-монтованому контейнері. Якщо бачите великий спад часу — ви знайшли головний важіль.
- Виправляйте монти стратегічно: тримайте код редагованим, але тримайте дерева залежностей у томах. Це кращий компроміс, коли політика змушує зберігати файли на Windows.
- Запустіть швидкий план діагностики при наступному скарзі «Docker повільний». Якщо не можете сказати, чи це файлова система, DNS чи обмеження ресурсів — ви не діагностуєте, а просто описуєте симптоми.
- Задокументуйте нудні правила (де лежать репозиторії, як монтувати, перевірка DNS, чистота кешу збірки). Це допоможе не витрачати час на ту саму інспекцію при кожному онбордингу.
Якщо хочете одну однозначну рекомендацію: помістіть ваш код у файлову систему Linux WSL2 і припиніть bind-монтувати NTFS у контейнери, якщо це не необхідно. Docker Desktop vs WSL Engine — вторинне; межа файлової системи — це головна битва.