前回の Docker on Ubuntu on WSL2 の環境を用いて、Visual Studio Code の Remote Development 拡張機能を使って、開発やサーバー稼働といったことがどのくらいできるのかを試してみます。結論としては、手間は掛かるけどもある程度の動作が可能といったところです。
nginx をコンテナで動かして外部からアクセスする
コンテナとして nignx を動かし、他の PC からもアクセスするという状況を考えてみます。普通に以下のコマンドで WSL 上のシェルで実行します。
$ docker run -p 80:80 -d nginx
毎回 sudo 付きで docker コマンドを発行するのが手間だったので、作業ユーザーは docker グループに追加している状況としています。
このとき、作業PCからであれば、http://localhost/ でアクセスできます。
この状態では、 127.0.0.1 のアドレスで Listen している状態であり他の PC からアクセスすることができません。これをどうにかするためには、Windows 側でポートフォワードの設定を行うことが必要となります。
ポートフォワードの設定
管理者として、PowerShell を開き、netsh を実行してポートフォワードの設定を行います。
PC として受け付けるポートを listenport で指定し、コンテナ側(WSL2)で待ち受けているポートを connectport で指定します。
netsh interface portproxy add v4tov4 listenport=80 connectaddress=172.31.176.1 connectport=80
ここで接続するアドレスの指定が必要で、WSL2 側に付いているアドレスを指定します。コントロールパネルから辿って見えるこのアダプタが該当します。 ipconfig を実行して、 vEthernet (WSL) の部分を確認するという方法でもよいでしょう。
ポートフォワードが正しく設定できると、他のPCからコンテナで動かしている nginx のページを表示が出来るようになります。
注意点として、 WSL2 側のアドレスというのが固定されないということです。そのためこのポートフォワードの設定は必要に応じて毎回行うことが求められます。
ポートフォワードの設定の削除は以下のコマンドです。(削除してからでないと新しい設定をすることができないので、この処理が必要です)。
netsh interface portproxy delete v4tov4 listenport=80
VS Code で DevContainer として使う
DevContainer として準備が整っているファイル構造で簡単にテストしてみます。
開発用コンテナを作るための Dockerfile、簡単なアプリとして Flask を使ったアプリを使っています。
Dockerfile の中身は以下の通りで最低限となっています。
FROM python:3.8.4-slim
ADD requirements.txt /tmp/requirements.txt
RUN pip3 install -r /tmp/requirements.txt --no-cache-dir
EXPOSE 5000
また、Python の開発環境として Pylance を 、アプリを動かすポート転送の設定を devcontainer.json に設定しています。その箇所のみを以下に抜粋で表示します。
// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
"dockerFile": "../Dockerfile",
// Set *default* container specific settings.json values on container create.
"settings": {},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-python.vscode-pylance"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [
5000
],
現在試してみた感じでは、VSCode の拡張機能を直接 extensions に足す部分が機能しませんでした。WSL 経由でなければ動作していた記憶があるので、いつかは対応されるかもしれません。
現時点では、手動で拡張機能のIDをコピー、ペーストで対応する必要ありです。
コンテナで開く
このフォルダを右クリックして Code から開くと、以下に示すように コンテナで開く?と聞かれます。
そしてコンテナで開いて、拡張機能などがインストールされ、開いた状態が以下の通りです。
ステータスバー付近をキャプチャしたものが以下の通りです。Dev Container として開かれており、 WSL2 上でも DevContainer が使えているようです。
デバッグの確認
launch.json も適切に記述してある状態で、デバッグ実行を開始し、同一PCのブラウザからアクセスも可能でした。以下の画面は、2度目のアクセスでブレークポイントで停止させているときの様子です。
このように VSCode の Remote-Containers 拡張機能を使って WSL2 上のコンテナでも開発コンテナ(DevContainer) として使ってアプリケーションの開発に使えそうです。
WSL2 側のファイルシステムにコードを配置するとうまくいくようでした。
通常の Windows ファイルシステム側にコード類をおいた場合、うまく DevContainer として開くことができませんでした(現時点では)。
注意点
注意点として、こちらの場合でも localhost で動いている分には自身からのアクセスは問題なくできるようですが、他の PC からのアクセスはできません (listenポートの都合)。ここでもポートフォワードの設定が必要ですが、WSL側のIPを宛先として設定するポートフォワードでは、うまく動作しませんでした。
そこれ自分の手元でうまくいった方法としては、 転送アドレスを WSL の IP ではなく、自身のローカルアドレスに対して設定するという方法でした。
netsh interface portproxy add v4tov4 listenport=5000 connectaddress=127.0.0.1 connectport=5000
ポート転送を失敗してうまく繋がないとき、試行錯誤することがあると思います。このとき、直前の状態で一度 netstat でどのようにポートが使われているかを確認してみてください。異常に接続が消費されている状況では、その状況を回避して落ち着いた状態で次の設定を試すようにしましょう。
VS Code に Docker 機能拡張をインストール
Remote-Containers から離れて、普段使いの VS Code に Docker 機能拡張をインストールしたときの様子が以下のものです。ちゃんと各種コンテナの様子が分かりますし、起動終了といった操作もできるようです。
Docker Desktop のダッシュボードのようにわかりやすいとはいえないですが、そこそこには使えそうな印象です。
Docker Compose は動く?
Docker compose で設定を記述して動かしている場合もあるので、それを最後に確認します。
Docker Compose のインストール
Docker compose についてはまだインストールしていなかったので、以下のコマンドで準備します。
$ curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > ~/docker-compose
$ chmod +x ~/docker-compose
$ sudo mv ~/docker-compose /usr/local/bin
docker-composeによるnginx
nginx を起動する compose ファイルを用意してみました。ここではシステムの起動時に自動的に起動するかを見たいので、restart 指定を追加しています。
システムにログインせずに docker が動く必要があるので、タスクスケジューラでシステム起動時に genie が動くようにしておく必要はあります。
ポートフォワードの設定
ポートフォワードの設定が必要です。問題なのは再起動のたびにアドレスが変わるので、これに対応する必要があります。
システムを PowerShell のスクリプトを実行可能な状態に設定しておきます。
そして以下のスクリプトを準備して、これをタスクスケジューラで起動時に設定しておくようにします。
netsh interface portproxy delete v4tov4 listenport=80
netsh interface portproxy add v4tov4 listenport=80 connectaddress=(wsl hostname -I).split()[0].trimend() connectport=80
ここで wsl hostname -I をそのまま使えない理由は、WSL側のIPの他、docker0 のインターフェース IP が返ってくるためです。手元では最初のアドレスが WSL 側IPとなっていたので決め打ちで使用しています。
タスクスケジューラには以下の設定で作成しています。システムの起動時に適用されるようにしていますが、少しだけ実行遅延をいれています。
- プログラム:%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe
- 引数: -Command “d:\set_portproxy.ps1”
- 作成したスクリプトファイル名を指定します
動作チェック
まずポートフォワードの設定スクリプトを実行します。そして、WSL2 側で docker-compose.yml ファイルを配置した場所をカレントに設定して、以下のコマンドで nginx を起動します。
docker-compose up -d
この状態で、自分のPC および、他のPC から Web ページが正常に表示されるのを確認しておきます。
うまく動いていたら、PCを再起動してログインせずに、他のPCなどからWebページにアクセスをしてみましょう。自分の場合には、この状態で正常にページが表示され、想定通り Docker がサービスとして動いている状態であり、restart 設定もちゃんと解釈されてシステムの起動と同時に動き出していることがわかりました。
まとめ
ポートフォワードの設定が手間が掛かって大変なポイントですが、一応はシステムの再起動後であってもうまく動作できる仕組みが整いました。これならば docker-compose を使ってサービスを動かしたり、開発に使ったりと現状維持はできそうです。
その他
Docker Desktop のようなダッシュボードについては、Portainer というもの(オープンソース版)を入れて管理するというものアリかもしれませんね。
Qiita のページ(Docker Desktopに依存しない、WindowsでのDocker環境) をみて、この存在を知りました。
コメント