個人で利用する分には Docker Desktop for Windows をフリーでまだ使えます。しかし、同じように有料化の波が来てしまうかもと考えて、代替策を考えておこうと思って支度を始めてみました。
背景
Docker Desktop が一定規模以上の企業で使おうとすると有料サブスクリプションを契約しないとライセンス違反になる、という発表が 2021/09/01 (現地時間では 8/31) にあったためです。周辺環境も整備され便利に簡単に使えるようになってきた Docker Desktop で、利用していた人も多いと思います。会社の中で、使用している人も多かったと思います。
Docker Desktop は使用せずに、Docker の便利な性質は開発で使いたい!というちょっとしたワガママを解決できるかなと興味があったので、少しトライしてみることにしました。
Docker Desktop をアンインストール
Windows 10 では WSL (Windows Subsystem for Linux) が使えます。これを用いて Docker を動かそうというのが最初の目標です。最終的には VS Code の Remote Development を使って開発に使えるか?というところをゴールにします。
この記事では WSL2 を有効化した Ubuntu 20.04 が動いているという状況で書いています。そこまでのセットアップ手順は割愛しているので、他のサイトを参考にしてもらえたらと思います。
まずは Docker Desktop for Windows をアンインストールしましょう。
アンインストールすると、 WSL からも docker コマンドが打てなくなるので、確認しておきましょう。
(Docker Desktop for Windows がインストール時には、実体として /mnt/c/Program Files/Docker/Docker/resources/bin/docker にアクセスしていました)。
Docker CE をインストール
WSL2 の Ubuntuに Docker CE をインストールします。いくつかの Web サイトではこのやり方が紹介されているので、そちらを参照してもよいでしょう。自分は以下の手順で作業を行いました。
apt が https でも動作するようにパッケージを追加
以下のコマンドでパッケージを追加します。
$ sudo apt install apt-transport-https ca-certificates curl software-properties-common
dockerのリポジトリを使うためGPG登録
以下のコマンドで登録します。
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
リポジトリの登録
以下のコマンドで Docker のリポジトリを登録します。
$ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
$ sudo apt update
将来的にUbuntu のバージョンが変わったら focal の部分を適切なものに変更する必要があります。
Docker CE をインストール
以下のコマンドを実行してインストールします。
$ sudo apt install docker-ce
通常の Linux 環境であれば Docker がこれで動き出すのですが、 WSL の環境では systemd が動いておらず、また このあと systemd プロセスを動かしても PID 1 ではないという状況などがあるため、 systemctl 経由での docker デーモンが動いていない状態となっています。
systemd を動作させる
sytemd を動作させるために、genie というツールを使用します。これによりプロセスの名前空間を PID 1 として systemd が動作するようにできます。
Genie を動かす前の準備
以下のコマンドを実行して、Genie を動かすのに必要となるパッケージをインストールします。
$ curl https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -o packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb
$ sudo apt update
dotnet-runtime-5.0をインストールします。
$ sudo apt install -y daemonize dbus dotnet-runtime-5.0 gawk libc6 libstdc++6 policykit-1 systemd systemd-container
sudo -s などで管理者権限ありのシェルで、以下のコマンドを実行して、wsl-transdebian をインストールします
# wget -O /etc/apt/trusted.gpg.d/wsl-transdebian.gpg https://arkane-systems.github.io/wsl-transdebian/apt/wsl-transdebian.gpg
# chmod a+r /etc/apt/trusted.gpg.d/wsl-transdebian.gpg
# cat << EOF > /etc/apt/sources.list.d/wsl-transdebian.list
deb https://arkane-systems.github.io/wsl-transdebian/apt/ bullseye main
deb-src https://arkane-systems.github.io/wsl-transdebian/apt/ bullseye main
EOF
# apt update
ここで root シェルからは抜けておきます。
Genie のインストール
以下のコマンドを実行してインストールします。
$ sudo apt install -y systemd-genie
インストール後、以下のコマンドを実行してみます。
$ genie -s
このように Waiting の状態が続いている場合、 systemctl で状態を確認してみます。
このように起動に失敗しているサービスらがいるので、これを修正します。どこでエラーが出ているか、を見るには systemctl を実行してみて、赤色でマークされているサービスを探します。
これらのサービスを起動しないようにするため、以下のコマンドを実行します。
$ genie -s
$ sudo systemctl disable ssh.service
$ sudo systemctl disable multipathd.service
$ sudo systemctl disable systemd-networkd-wait-online.service
$ sudo systemctl mask systemd-modules-load.service
$ sudo systemctl mask systemd-remount-fs.service
各自の環境によってこの状態は変わるかもしれないので、systemctl の状態を確認しつつ無効化の処理を行って下さい。自分の場合には、試している間に systemd-networkd-wait-online.service のエラーが増えたので無効化した次第です。
以下のように systemctl でエラーが発生しておらず、正常に running 状態となるようにします。
Genie を毎回起動するために
WSL2 (Ubuntu) を起動するたびに、手動で genie -s コマンドを打ち込んで始めるのは少々手間です。Docker がスムーズに使えるように、自動で genie コマンドが実行されるようにする方法を2つ紹介します。
.bashrc に記載する方法
ホームディレクトリにある .bashrc ファイルを編集して、WSL2 のシステムにログインしたときに実行されるようにしてしまうという方法です。このファイルの末尾あたりで、以下のスクリプトを追記します。
if [[ ! -v INSIDE_GENIE ]]; then
echo "Starting genie:"
exec /usr/bin/genie -s
fi
タスクスケジューラを使う方法
Windows の起動時、ユーザーのログイン時など、Windows のタイミングに合わせて起動させてしまうという方法です。これにはタスクスケジューラを使用します。
コンピュータの管理(ショートカットは Win+x) を開いて、システムツールのタスクスケジューラを開きます。ここで、操作として「基本タスクの作成」を行います。
いつタスクを開始するか、についてですが、状況に応じて
- ログオン時
- コンピュータの起動時
あたりを選択するとよいです。最初はログオン時で試してみるのがよいでしょう。
タスクにやらせるのはプログラムの開始で、以下の設定とします。
- プログラム:C:\Windows\System32\wsl.exe
- 引数:-d Ubuntu-20.04 — /usr/bin/genie -i
これでタスクの生成を完了させます。タスクスケジューラーライブラリの項目で、今追加したタスクが出現していることを確認しておきましょう。
コンピュータの起動時にプログラムを動かす場合、普段使用するアカウントを使用するのがトラブルを避けるポイントです。先ほどのタスクをダブルクリックで開き、ユーザーの設定を行っています。ユーザーの設定をする部分は以下の画面を参考にしてください。
動作の確認
PC を再起動して、Ubuntu on WSL2 の環境で Docker コンテナを動かして動作を確認してみましょう。
うまく動作していれば、 Ubuntu (WSL2) のコンソールを開いたときに、“ホスト名-wsl” という名前がホスト名として表示されていると思います。また以下のコマンドを実行しても、正常に状態が返ってくることでしょう。
sudo docker ps
もし、 docker サービスが動いていない、という意味合いのエラー表示が出るのであれば、 genie の起動部分で失敗しています。
イメージ取得して動くかを試すのに、以下のコマンドを実行してみます。
sudo docker run hello-world
これでいつもの Hello World が表示されれば WSL2 上での Docker の支度は完了です。
まとめ
長くなってきたのでまずはここで区切ります。今回は WSL2 を用いて Docker を systemctl 経由で動作させるための手順を説明してきました。 Docker Desktop はインストールすればすぐに Windows システムが起動した段階で動作を開始し、すぐに Docker を使える状態を提供してくれました。それを同じようなことを実現するために、今回の手順が必要でした。
次回はこの環境を用いて、WSL2 上で動かしているコンテナにアクセスしたり、他のPCからのアクセスについて説明します。
第2回はこちら、VS Code の DevContainer 使える?なども試してみました。
単純に開発環境として Docker を使いたい、ならば手動で service docker start コマンドを叩くでも良い場面はあると思います。
しかし、コンテナの中でサーバーを動かして他からもアクセスを受け付けるというのもゴールの1つとして考えています。Docker Desktop を用いてそのようにサーバーを動かしているケースも十分に考えられるからです。
ここまでの自分の感想としては、Docker Desktop を使い続けられる場合は、そのまま使い続けた方がとても楽なのは間違いないようです。