Windows 10 + WSL 2 でDocker環境を構築する(Docker Desktop有料化対策)

はじめに


f:id:ecb_mkobayashi:20210906140918p:plain

こんにちは、アーキテクトの小林です。

Docker Desktopが有料化することになりましたね。 従業員が251人以上もしくは売上約11億円以上の企業でDocker Desktopを利用する場合に、今後は有料プランが必要ということになりました。

個人的には、これだけのツールがこれまで無料で利用できたことが不思議でしたし、有料化によって母体の経営が安定化してプロダクトの健全な成長とサポートが得られるのであれば、歓迎すべきことかなと思っています。

でも...一応無料で使いつづける抜け道を見つけておきたいと思ってしまうのはエンジニアの性なのでしょうか。こういう小さな障壁をきっかけに週末にやる気が沸いてしまったので、超絶便利だったDocker Desktopに頼らずにWindows 10にDockerの環境を整えてみました。

環境を構築するにあたって、ちょっとしたつまづきもありましたので、その回避策を含めてご紹介したいと思います。

WSL 2の要件

すでにDocker Desktopの環境を構築している方であれば、必要な環境は整っていると思いますが、最初からインストールしなおす場合にも役に立つ記事にしておきたいので、インストール手順と参考となる記事へのリンクを記載しておきます。

まずWSL 2(Windows Subsystem for Linux 2)の環境を構築します。WSL 2はHyper-Vを利用した完全なエミュレーションとなっていて軽量かつ高速に起動してくれる、理想的な環境です。WSL 2の環境構築に必須となる要件は以下の通りです。

  • Windows 10(64bit) バージョン2004以上
  • パソコンのハードウェアがHyper-Vに対応している

WSL 2のインストール

最初にWSL 2をインストールします。 Microsoftの公式ドキュメントがありますので、こちらの内容に沿ってインストールしましょう。

docs.microsoft.com

  1. 手順 1 - Linux 用 Windows サブシステムを有効にする
  2. 手順 2 - WSL 2 の実行に関する要件を確認する
  3. 手順 3 - 仮想マシンの機能を有効にする
  4. 手順 4 - Linux カーネル更新プログラム パッケージをダウンロードする
  5. 手順 5 - WSL 2 を既定のバージョンとして設定する
  6. 手順 6 - 選択した Linux ディストリビューションをインストールする

手順 6ではLinux ディストリビューションを選択することができますのでUbuntuかDebianを選びましょう。Microsoftの公式ドキュメントに「Ubuntu と Debian だけがテストされており、サポートされています」と書かれているものがありますので、今後余計な苦労をしないためです。この記事ではDebianを選んだものとして進めます。UbuntuもDebian系ですのでほぼ同じ手順で進められると思います。

省略可能となっていますがWindows Terminalも入れましょう。起動するといきなりLinuxのコンソールにつながり、コマンドを実行できるように設定できますので、非常に便利です。

WSL 2の設定

インストールが終わったらWindowsのコマンドプロンプトから以下のコマンドを実行しましょう。

wsl --list --verbose

コマンドを実行するとディストリビューションの一覧が表示されます。

  NAME                   STATE           VERSION
* docker-desktop         Stopped         2
  Debian                 Running         2
  docker-desktop-data    Stopped         2

アスタリスクがついているものがデフォルトのディストリビューションです。 docker-desktopが選択されているようでしたら、Debianに変更しましょう。 以下のコマンドでデフォルトを変更できます。

wsl --set-default Debian

また、右の列のVERSIONが1になっている場合はWSL 2になっていませんので以下のコマンドを実行しましょう。

wsl --set-version Debian 2

※記事公開時「wsl --set-default-version 2」とコマンドを記載する間違いがありましたので修正いたしました。

wsl --list --verboseの結果が以下のようにDebianが選択されていて、VERSION 2になっていれば準備完了です。

  NAME                   STATE           VERSION
* Debian                 Running         2
  docker-desktop         Stopped         2
  docker-desktop-data    Stopped         2

Docker Engineのインストール

つづいてDocker Engineをインストールしましょう。 Dockerの公式ドキュメントに手順が乗っています。手順は英語ですが、とくに難しいことはありませんのでどんどん進めていきましょう。 基本的には記載されているコマンドをDebianのコンソールから実行していくだけです。

docs.docker.com

  1. OS requirements
    • 書いてある内容を確認するだけです
  2. Uninstall old versions
    • 書いてあるコマンドを実行します
  3. Installation methods
    • 「This is the recommended approach」となっている手順を進めましょう
  4. Set up the repository
    • 書いてあるコマンドを実行します
  5. Install Docker Engine
    • 1.のコマンドを実行します
    • 2.のコマンドはバージョンを指定したい場合の手順です(実行不要)
    • 3.のコマンドhello-worldはエラーになります

Docker Engineが起動しない

hello-worldのコマンドが失敗してしまいました。 Dockerサービスをスタートすると以下のようなエラーになります。

sudo service docker start
grep: /etc/fstab: No such file or directory
Starting Docker: docker.

/etc/fstabが見つからないというエラーなので該当ファイルを作成しました。

sudo touch /etc/fstab

再びsudo service docker startを実行すると成功したような反応ですが、実は内部エラーになっていて起動していません。 以下のコマンドでDockerサービスのステータスを確認すると失敗しているようです。

sudo service docker status
Docker is not running ... failed!

エラーの原因はDockerのログに記載されていました。tail /var/log/docker.logのコマンドでエラーの内容を確認できます。二つの環境で試しましたが別々のエラーが出ていました。

failed to start daemon: Error initializing network controller: error obtaining controller instance: unable to add return rule in DOCKER-ISOLATION-STAGE-1 chain:  (iptables failed: iptables --wait -A DOCKER-ISOLATION-STAGE-1 -j RETURN: iptables v1.8.7 (nf_tables):  RULE_APPEND failed (No such file or directory): rule in chain DOCKER-ISOLATION-STAGE-1
 (exit status 4))
failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: iptables failed: iptables --wait -t nat -N DOCKER: iptables v1.8.2 (nf_tables):  CHAIN_ADD failed (No such file or directory): chain PREROUTING
 (exit status 4)

エラーメッセージにはネットワークコントローラーの初期化の失敗したというメッセージですね。 このエラーの詳細はわかりませんがWSL2のバグらしいです。

Some further investigation founds that it is related to WSL2 Kernel issue, as starting from Ubuntu 20.10 uses nftables that requires Linux Kernel 5.8 while Microsoft uses 5.4 for now. I will close here and forward the bug report to microsoft/WSL repository.

こちらの記事を参考に以下のコマンドを実行してレガシー設定となる 1 を選択します。

sudo update-alternatives --config iptables
  Selection    Path                       Priority   Status
* 0            /usr/sbin/iptables-nft      20        auto mode
  1            /usr/sbin/iptables-legacy   10        manual mode
  2            /usr/sbin/iptables-nft      20        manual mode
Press <enter> to keep the current choice[*], or type selection number: 1
update-alternatives: using /usr/sbin/iptables-legacy to provide /usr/sbin/iptables (iptables) in manual mode

これでようやく準備完了です。sudo service docker startを実行してsudo service docker statusを実行すれば、以下のように表示されます。

Docker is running.

Dockerの準備ができました。エラーになったhello-worldコマンドを再度実行してみましょう。

sudo docker run hello-world

以下のメッセージを含む結果が返れば正常に動作しています。

Hello from Docker!
This message shows that your installation appears to be working correctly.

sudoなしでdockerコマンドを実行できるようにする

dockerコマンドを実行するとき毎回sudoを入れるのも面倒ですのでdockerグループに自分のユーザーを追加しましょう。 以下のコマンドの<USER>を自分のユーザーに置き換えて実行してください。

sudo usermod -aG docker <USER>

このコマンドを実行したあとは一旦 exit でログアウトしてから、sudoなしで以下のコマンドを実行します。

docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    d1165f221234   6 months ago   13.3kB

無事にdockerコマンドを実行できるようになりました!

DockerでMariaDBを入れてみる

それでは、Dockerをつかって試しにMariaDBを起動してみましょう。 MariaDBの起動はdocker-composeをつかうと便利ですので、まずはdocker-composeを入れましょう。

docs.docker.com

Install Compose on Linux systems に書いてあるコマンドを実行していきます。

sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose --version
docker-compose version 1.29.2, build 5becea4c

続いて、docker-compose.ymlファイルを作りましょう。 コマンドからつくっても良いですが、Windowsのエクスプローラーからファイルシステムを直接操作できちゃいます。 以下のフォルダにファイルを作成しましょう。

\\wsl$\Debian\home\<USER>\mariadb\docker-compose.yml

ファイルの内容は以下です。

version: '3.1'
services:
  db:
    image: mariadb
    container_name: mariadb
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
    volumes: 
      - ${HOME}/mysql_data:/var/lib/mysql
      - ${HOME}/mysql_backup:/tmp/backup/mysql
    ports:
      - 3306:3306

ファイルを作成したらDebianのコンソールから以下のコマンドを実行してみましょう。

cd ~/mariadb
docker-compose up

ズラズラとメッセージが表示されてエラーが表示されていなければ、もう接続できる状態になっているはずです。

f:id:ecb_mkobayashi:20210906115005p:plain
HeidiSQLで接続してみる

  • ホスト名: localhost
  • ユーザーとパスワード: root / root
  • ポート: 3306

で接続します。HeidiSQLで無事に接続を確認できました。

f:id:ecb_mkobayashi:20210906115455p:plain
HeidiSQLで接続成功

最後に

無事にWindows 10にWSL2+Debian+Dockerを入れてコンテナーが起動できる状態になりました。 バグの存在によってちょっとつまづいてしまいましたが、思ったよりも簡単に構築できてよかったです。 Windows 10とDebianのファイル転送はエクスプローラーから簡単に操作できますし、Debianからも/mnt/c/にアクセスすれば、WindowsのCドライブにアクセスできます。 Windows Terminalによって簡単にDockerコマンドも実行できるので一般的な用途であれば支障はなさそうですね。

これで万事OKか...というと実は難点がありまして、これまで使っていたVisual Studio CodeのRemote ContainersがDocker Desktopを必須としているので、利用できなくなってしまいました。ここの抜け道はもう少し調べる必要がありそうですね。

ということで今回は「Windows 10 + WSL 2 でDocker環境を構築する」という内容で、手順をご紹介しました。 参考にしていただけますと幸いです。

ebeingではコンテナーを使いこなして、クラウドネイティブな開発がしたい人を募集してます! careers.ecbeing.tech