タイトル通り。
- WSL2導入、設定。
- Windows Terminal導入、設定。
- Docker、DockerCompose導入。windows->WSL2へのポートフォワーディング設定
- (その他)Dockerのユーザ定義ネットワークの謎の名前解決不具合対処。
WSL2導入
やった事がこちらの記事にほぼ載ってたので割愛。
完全新規に導入する場合は、WSL2の設定後に、CMD
かPowerShell
から、wsl --set-default-version 2
を実行後に、Microsoft Storeからインストールする。
WSL2設定
メモリ上限設定、localhostでの通信許可設定
デフォルトだと、WSL2が無限にメモリを食い尽くそうとしてきた。
あと、WindowsからWSL2環境にアクセスするときにlocalhost
を使いたい。
C:\Users\<yourUserName>\.wslconfig
をつくって、設定をする。
memory=2GB
とlocalhostForwarding=true
だけ作って、あとは未検証。
日本語化
WSL2関係ない普通のubuntuの日本語化だけど、一応。
Linuxの日本語化の仕組みを良く分かってないから、言われた通りにしただけ。
Ubuntu用ファイルへのショートカットを作成
\\wsl$\[ディストリビューション名]
で、ディストリビューションのディレクトリを見る事が出来る。デスクトップにショートカットを作っておくと、何かと便利。
Windows Terminal導入
ここ
Microsoft謹製の、Linuxのターミナルっぽい奴。タブも分割表示もできるし、CMD
もPowerShell
も一緒に扱えるんで、便利。
フォントも指定できるんで、Source Han Code JPを入れてみた。OSにインストールしてから、Windows Terminal
の設定を選択するとひらくsettings.json
のprofiles: defaults:
に`"fontFace" : "Souce Han Code JP"を指定。
Docker、DockerCompose導入
Dockerを、公式に言われるがままにインストール。
DockerComposeを、公式に言われるがままにインストール。
Dockerデーモンについての 注意点
WSL2では、systemd
が使えない(原理的にpid 1 が占有されるから使えない、とかなんとからしい)から、Dockerデーモンは自分で起動させる必要がある。
立ち上げるたびにsudo service docker start
してるけど、大変面倒臭いんで、その内自動化したい。
Windows -> WSL2のポートフォワーディング設定
今の状態でも、WindowsからWSL2へのアクセスは、localhost
を使えば出来る様になっているのだけれど、直接127.0.0.1
を使いたい事もある。
なので、Windowsへの特定のポートへのリクエストを、WSLにポートフォワードさせる設定をする。
問題になった事例(飛ばしてよい)
AndroidStudio
で立ち上げたエミュレーターから、WSL2のDockerComopse
で立ち上げたサーバに通信したい時に問題が発生。
AndroidStudio
のエミュレーターから、ホスト機(Windows)への通信は、10.0.2.2
を使って実現出来るのだけれど、、この通信はホスト機側では127.0.0.1
として解釈されるっぽい。
WindowsからWSL2にアクセス出来るのがlocalhost
だけのままだと、当然エミュレータ(10.0.2.2)⇒Windows(127.0.0.1、not localhost)だから、Dockerで立ち上げたサーバまでは届かない。
なので、127.0.0.1
が来た場合でもWSL2側にポートフォワードさせる必要があった。
設定
こちらを参照させてもらって、スクリプトを作成。
-
listenport
を開発中サービスの待ち受けポートに変更。 - ついでに
ifconfig
をip a
に合わせて変更 - 開発用の設定は開発用のgitの中に閉じ込めたいので、windowsでのタスクスケジューラの設定は無しにして、
docker-compose up
前に手でスクリプトを叩く運用にする。
#!/bin/bash -x
# !注意!:実行には管理者権限が必要なので、ターミナルを管理者権限で立ち上げる事。
# WSL2での起動時に、windows側から'127.0.0.1'でもアクセス可能にするための設定。
IP=$(ip -4 addr show dev eth0 | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1)
netsh.exe interface portproxy delete v4tov4 listenport=3000
netsh.exe interface portproxy add v4tov4 listenport=3000 connectaddress=$IP
netsh.exe interface portproxy show v4tov4
注意点
WSL2のアドレスは再起動の度に変わるから、スクリプトをしょっちゅう叩かないといけない。大変面倒なんで自動化したい。
(その他)Dockerの名前解決不具合の対処
WSL2とは関係ないかもしれないけど、コンテナからの名前解決時に変な挙動が発生して、githubとの連携が出来ない現象が発生した。
開発環境としては致命的なんで、是が非でも解決する必要がある。
結論としては、Dockerに追加DNSサーバとしてパブリックなもの(8.8.8.8とか)を設定して回避可能。
現象
- ユーザ定義ネットワークを使ったコンテナ内からの、
github.com
の名前解決をする時にだけ、挙動がおかしい。google.com
とかは大丈夫。 -
dig
では普通に名前解決が出来る。curl
やping
やgit clone
では、出来たり出来なかったりする。(大抵はCould not resolve host: github.com
で出来ない) -
tcpdump
でパケットを確認すると、ユーザ定義ネットワーク用の内部DNSサーバまでは、ちゃんとレコードが帰って来てるのに、内部DNSサーバでレコードだけが消滅している。DNSのレスポンス自体は返ってくる。 - 内部DNSのキャッシュ機能があるなら変な動きをしてそう。が、内部DNSなんで細かいところが見えず、これ以上は追えない。
WSL2というより、Dockerの内部DNSのバグなんじゃないかって気がする。
バージョンはDocker version 19.03.9, build 9d988398e7
以下の手順で再現出来る(かもしれない)
docker network create test
docker run --net="test" -it ubuntu:16.04 /bin/bash
apt update && apt install curl -y
curl github.com
最初は成功したりもするが、何度か繰り返したり時間をおいてから再実行したりすると、curl: (6) Could not resolve host: github.com
が出る。
解決
理由は全くわからないから追うのを諦め、必要な機能が達成出来ていれば良い事にした。
ユーザ定義ネットワークは、DockerCompose
で立ち上げた各コンテナ同士が、サービス名で名前解決して連携するために使うから、必須。
ただ、怪しい動きをしてるユーザ定義ネットワークの内部DNSサーバーは、最低限サービス名での名前解決機能だけ提供してくれれば良いので、内部DNSサーバが名前解決(この場合はgithub.com)に失敗した時用に、別途ちゃんとしたDNSサーバを追加すれば良い。(今回は8.8.8.8)
Dockerなら、docker run --net="test" --dns=8.8.8.8 -it ubuntu:16.04 /bin/bash
、DockerComposeならymlにdns: 8.8.8.8
を追加する事で、問題を回避出来た。
WSL2開発環境所感
これまでの環境が、Vagrant -> virtualbox -> centos -> DockerCompose
だったんで、1段階減って、Windowsとの連携がしやすくなっただけでもとても便利。
Windows側のリソースもあんまり取らないし、体感速度も大分上がってる。
今のところVimでしか触ってないんだけど、Docker for Desktop
とかVSCode
を連携す有ればさらに快適になるのかもしれないという予感は抱かせてくれる。
Windows Terminal
も良い感じだし、今のMicrosoftはほんと良いなぁ。