Přeskočit na obsah

IntelliJ Xdebug s Dockerem na WSL 2

Publikováno 4 min čtení

Ilustrace Microsoft miluje Linux s logem Microsoftu, srdcem a linuxovým tučňákem Tuxem

S vydáním Docker Desktop WSL 2 Backendu můžete výrazně zlepšit výkon svých projektů. Můžete je spouštět s výkonem téměř jako na Linuxu i na Windows, což je zásadní věc a řeší to spoustu problémů s provozem Dockeru na Windows. Jedním z častých problémů s Dockerem na Windows bývalo, že Windows Home neuměl spustit Hyper-V. Potřebovali jste alespoň licenci Windows Pro. S WSL 2 si můžete všechny výhody užít i na Windows Home. Existovala i řada dalších problémů, jako slabý IO výkon přes protokol Samba nebo chybějící mapování některých systémových volání, například inotify.

Chtěl jsem WSL 2 vyzkoušet, abych viděl ten rozdíl na jednom ze svých PHP projektů. Cíl byl jednoduchý — chtěl jsem projekt spustit v Dockeru a umět ho vzdáleně ladit pomocí Xdebugu v IntelliJ. Cestou ale bylo pár překážek, které jsem musel překonat. Proto jsem se rozhodl napsat tento článek a podělit se o to, co jsem se při hraní s WSL 2 naučil, abyste na všechno nemuseli přicházet sami.

Předpokladem je, že máte nainstalované WSL 2 se svou oblíbenou linuxovou distribucí. Je to docela přímočaré, můžete se řídit instrukcemi zde. Jako ukázkový projekt použiju demo projekt Symfony s několika úpravami, ale klidně použijte jakýkoli projekt chcete. Pokud si to chcete jen vyzkoušet a nechcete používat vlastní projekt, můžete použít můj upravený demo projekt na mém Githubu. Dále musíte přepnout Docker Desktop na WSL 2 Backend. Můžete se řídit instrukcemi zde. Zase je všechno docela přímočaré.

Překážka č. 1 Jedna věc, která dávala smysl, ale zpočátku byla matoucí, je, že po přepnutí Docker backendu na WSL 2 už ze standardního enginu nebudete mít přístup ke svým images, volumes, kontejnerům atd. Pokud to s přechodem myslíte vážně, doporučuji udělat prune nepoužívaných Docker objektů. Uvolníte tím desítky až stovky GB paměti, kterou po přechodu na WSL 2 Backend stejně nevyužijete.

Překážka č. 2 Důležité je, že zdrojové soubory musíte mít uvnitř souborového systému WSL 2!! Popisují to Docker best practices. Mít soubory na souborovém systému Windows bude ve skutečnosti pomalejší než WSL 1.

Po instalaci projektu ho můžete v IntelliJ otevřít přes cestu \\wsl$. Teď je potřeba nakonfigurovat IntelliJ, aby podporoval Xdebug. Nastavte Run configuration takto

Run/debug konfigurace PHP projektu v IntelliJ

Hodnota IDE key (session id) závisí na vašem souboru xdebug.ini (viz můj níže). Server by měl být nakonfigurovaný nějak takto

Konfigurace serveru v IntelliJ s hostitelem, portem a path mappings

Nezapomeňte přidat path mappings a nastavit Absolute path on the server na /var/www/html.

Pro ladění používám vlastní port 9005 definovaný v xdebug.ini, takže musím v IntelliJ změnit nastavení takto

Nastavení portu Xdebugu v předvolbách IntelliJ

Můj vlastní xdebug.ini najdete zde. V zásadě to je

xdebug.remote_enable=1
xdebug.remote_handler=dbgp
xdebug.remote_port=9005
xdebug.remote_autostart=1
xdebug.remote_connect_back=0
xdebug.idekey=docker

Možná vás napadne, proč tam není xdebug.remote_host. To nás přivádí k

Překážka č. 3 WSL 2 mění IP adresu Windows hostitele pokaždé, když restartujete PC (nejspíš). Tuto IP najdete ve své linuxové distribuci takto

$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.22.48.1

Problém je, že když tuto IP adresu napevno nastavíte v konfiguraci Xdebugu, nemusí fungovat, když projekt spustíte podruhé. Proto ji musíte definovat dynamicky. Tento problém můžete vyřešit mnoha různými způsoby — od ručního měnění remote_host pokaždé, když se změní, po jeho aktualizaci skriptem. Já jsem se rozhodl použít proměnnou prostředí při spouštění Docker Compose a upravit entrypoint pro Apache.

V entrypointu používám sed, abych odstranil řádek s remote_host, a echo, abych připojil nový remote_host z proměnné prostředí WSLIP definované v docker-compose.yml. Projekt spustím prostě takto:

WSLIP=$(grep nameserver /etc/resolv.conf  | cut -d ' ' -f2) docker-compose up

Překážka č. 4 I když ladění spustíte, breakpointy se nikdy nezastaví. To proto, že Windows Defender Firewall považuje WSL ve výchozím nastavení za veřejnou síť a blokuje přístup. Firewall můžete nakonfigurovat pomocí PowerShellu a přidat povolující pravidlo, které tento problém vyřeší. Stačí spustit

New-NetFirewallRule -DisplayName "WSL" -Direction Inbound  -InterfaceAlias "vEthernet (WSL)"  -Action Allow

Vysvětlení najdete v tomto issue.

Možná se také ptáte, proč vůbec z WSL 2 potřebujete přistupovat k Windows hostiteli? Protože přesně tak funguje vzdálené ladění v Xdebugu. Podívejte se na Communication Set-up v dokumentaci Xdebugu.

Překážka č. 5 Když přejdete na http://localhost:8000/en/blog (pokud používáte můj projekt) a máte breakpoint v BlogController.php v metodě index, uvidíte v IDE následující chybu (s trochu jinými cestami)

Chyba v IntelliJ způsobená špatnými path mappings pro Xdebug

Je to bug v IntelliJ, sledovaný zde. Jako workaround musíte namapovat mount \\wsl$ na síťovou jednotku. Stačí kliknout pravým tlačítkem na Tento počítač ve Windows, vybrat Připojit síťovou jednotku… a vyplnit to podobně jako tady

Dialog Windows Připojit síťovou jednotku ukazující na WSL mount

Hodnoty závisí na vaší linuxové distribuci a jako písmeno jednotky si můžete zvolit cokoli chcete. Až budete mít WSL namapované na síťovou jednotku, otevřete projekt v IntelliJ přes tuto novou síťovou jednotku a spusťte ladění.

Gratuluji, teď už by mělo všechno fungovat! I když chvíli trvalo, než jsem Xdebug rozchodil, jak jsem potřeboval, pro mě to rozhodně stálo za tu námahu. Výkon je u mých projektů 5–10krát lepší a můžu ho vřele doporučit. Snad už s WSL 2 a Dockerem v budoucnu na žádné další překážky nenarazím, ale pokud ano, článek aktualizuji. Pokud máte jiné problémy a chcete se podělit o své řešení, dejte mi vědět v komentářích.

← Zpět na blog