トップ 最新

ただのにっき

2020-07-23(木) [長年日記]

WSLの代わりにDockerを使う

自宅で仕事をするようになって、さすがにWSLのI/Oの遅さに嫌気が差してきた今日このごろ。

世間的にはWindows10 2004*1のWSL2がたいへん評判が良くて、おれもはやく移行したいんだけど、2004にまだけっこう致命的なバグがあって、関係するデバイスを持つうちのPCにはまだ当てられそうにない。PCも古いので買い換える予定なんだけど、まだ機種選定中なものだから、WSL2までのつなぎとして、同じHyper-V上の仮想環境であるDockerをWSLの代わりに使うことにした。

といってもやったことはそんなに難しくはない。ちょっとした自作ツールはだいたいRubyで書いてあるので、ベースにするイメージを「ruby:2」にしてDockerfileを書く。rubyの公式イメージは使い慣れたdebianをベースにしているので都合がいい:

FROM ruby:2
ENV USER tdtds
ENV LANG ja_JP.UTF-8
RUN apt-get update && apt-get upgrade -y && \
    apt-get install -y sudo docker ...【必要なパッケージ諸々】 && \
    apt-get clean && apt-get autoremove -y && \
    echo Asia/Tokyo > /etc/timezone && \
    dpkg-reconfigure -f noninteractive tzdata && \
    sed -i "s/# $LANG/$LANG/" /etc/locale.gen && \
    dpkg-reconfigure --frontend=noninteractive locales && \
    update-locale LANG=$LANG && \
    gem install 【必要なgem諸々】
RUN useradd -m -u 1000 $USER && \
    usermod -aG sudo $USER && \
    chsh -s /usr/bin/zsh $USER
COPY docker-init.sh /usr/local/bin/
USER $USER
CMD /usr/local/bin/docker-init.sh

docker-init.shの中身は基本的に「sleep infinity」でいいんだけど、docker run後にマウントされたホスト側のファイルをコピーしたり、ユーザ権限で一度だけ走らせたい諸々の設定なんかを書いてもいい。おれはホスト側にあるdotfilesをホームディレクトリにコピーするコマンド群を書いてる。

これをビルド:

docker build . -t debian

入れるパッケージが多くなると、さすがにそこそこ時間がかかる。いままでこの手の設定はAnsibleでコツコツ書いてメンテしていたのに、Dockerfileでは冪等性を気にせずダラダラ書けてしまって、堕落もいいところだ。うっかり変なものを入れて環境を汚してしまってもビルドし直せばいいというのは、精神的な安定が得られて良い。

ビルドできたらdetachモードで実行する:

docker run -d -v C:/:/mnt/c \
-v /var/run/docker.sock:/var/run/docker.sock \
--restart=always --name debian debian

C:をまるごとマウントするのは大胆すぎるかも知れないので、使いながら絞っていく予定。/var/run/docker.sockをマウントすると中からdockerコマンドでホスト側のdockerを呼び出せる。あと--restart=alwaysでホストOS再起動時とかにこのコンテナを自動実行してくれるようにする。

ところで、なにか変更を加えるたびにDockerfileを修正してビルドし直すのは馬鹿げているので、ベースイメージが変わったとき以外はこれでごまかす:

docker commit debian debian

あとはWindows Terminalに*2こんなセクションを作ればOK:

{
   "guid": "{afde4fd8-6a2e-44bf-869d-548dd9a859f2}",
   "name": "Docker shell",
   "commandline": "wsl docker exec -it debian zsh -l",
},

commandlineには最初、「docker exec ~」とだけ書いていたんだけど、これだとサスペンドするつもりでCtrl+Zを入力するとシェルが死んでしまう。どうやらDockerが提供するttyは端末制御が不完全? wslコマンドでラップすることでこの問題は抑制できたので、当面はこれで。「脱WSLする」という当初の目的が最後の最後で崩れているが見なかったことにする。

で、使ってみるとかなり快適なので、これはひょっとして、WSL2いらないんじゃね? みたいな気分になってる。もちろんホスト側のファイルシステムにアクセスするのはやや待たされるんだけど、それはたぶんWSL2でも同じだしなぁ。メモリ食いと言われているWSL2に比べて、Dockerではリソースの制限できるし。

*1 後世のためのメモ: 2004年版の古いエディション、という意味ではない(Windows Serverのネーミングとかぶるのでややこしい)。Windows10においては2020年4月のアップデートという意味である。

*2 ターミナルも最近Windows Terminalに移行した。開発環境もvscodeだし、なんかMicrosoft大スキ人間みたくなってる(笑)。