Docker Desktopに依存しない、WindowsでのDocker環境


もろもろの事情でDocker Desktopを使いたくなくなったため、Docker Desktop for Windows無しに、似たようなDocker環境をWindowsに構築する手順を確認しました。

(2021-09-05追記) 私はWSL2をDocker以外の目的で使用していないので気にしませんが、他の目的にも使っているという方は 「(おまけ) Docker用のディストリビューションを分ける」 を先に参照したほうが良いかもしれません。

(2022-01-29追記) Visual Studio Code (VSCode) に、WSL環境内の docker コマンドを直接使用できるオプションが追加されました。この機能を有効にすると、VSCodeからコンテナを使用するために一旦WSLに接続したり、Windows側にDocker CLIをインストールしたり、というステップが不要になります。詳細は (おまけ2) VSCodeからWSL上のdockerコマンドを直接使用する を参照してください。

1. Dockerのインストール

WSL2のディストリビューション上にDockerをインストールします。

WSL2にUbuntu 20.04のディストリビューションを導入

以下の「手動インストールの手順」そのままです。

ディストリビューションとして Ubuntu 20.04 LTS をインストールします。

以降の手順は、特に記載がない限りこのWSLディストリビューション内で行います。

Ubuntu上にDocker Engineをインストール

以下の Install using the repository の手順そのままです。

書かれているコマンドを上から実行していけばOKですが、以下の部分は不要です。

  • Install Docker Engine2. To install a specific version of Docker Engine, ... の部分(最新以外のバージョンをインストールしたい場合の手順なので)
  • 最後の Verify that Docker Engine is installed correctly ... の部分(この時点ではまだ動きません)

一般ユーザーへの権限付与

WSLで使う一般ユーザーから docker コマンドが使用できるようにするため、以下のコマンドでWSL用ユーザーを docker グループに所属させます。

sudo usermod -aG docker $USER

Docker Daemonの起動・自動起動の設定

WSLにインストールした場合、Docker Daemon は自動的に起動しないので、以下のコマンドで手動起動します。

sudo /etc/init.d/docker start

また、WSLで使うユーザーの .bashrc に以下を追記しておくと、ディストリビューションが再起動された後も、一度 wsl コマンドで接続するだけで自動的に起動できます。

# Start dockerd
sudo /etc/init.d/docker start

このときパスワードを聞かれるのが煩わしい場合は、以下のコマンドを実行し、sudoers ファイルを編集します。

sudo visudo

nanoエディタが起動するので、末尾に以下を追加した後、 Ctrl+X -> Y -> Enter で保存・終了します。

%docker ALL=(ALL)  NOPASSWD: /etc/init.d/docker

これにより、上記の起動コマンドを実行した場合だけはパスワードが不要になります。

動作確認

以下のように Hello World イメージを実行します。

docker run hello-world

Hello from Docker! と表示されれば正しくインストールできています。

2. Docker Compose (v1) のインストール

Visual Studio Code の Remote Containers 拡張では docker-compose コマンドも必要になるため1、インストールします。以下の Install Compose on Linux systems の手順そのままです。

3. Dockerコマンドの利用

今後の docker コマンドの実行は、 wsl コマンドでいったんLinuxに入ってから行うようにします。

ただし、Docker Desktop for WindowsのようにWindowsのパスをそのまま使用はできないので、 -f C:\src\test\Dockerfile のようにパスが出てくる個所は、 -f /mnt/c/src/test/Dockerfile のようにLinux側からみたパスに置き換える必要があります。

追加情報

以下にあるようにバッチやPowerShellスクリプトを作成することで、Windowsから docker コマンドをそのまま実行できるようにすることもできます。

ただし、上記のパスの問題や、 --mount オプションのようなカンマ区切りパラメータの問題(PowerShellではエスケープが必要)もあり、バッチやPowerShellだけではDocker Desktopと全く同じ動作にするのは厳しそうです。

4. Visual Studio Code からの利用

(2022-01-29追記) Visual Studio Code v1.61から、この操作は不要になりました。詳細はおまけ2を参照ください。

Windowsから起動したVisual Studio Codeでは、Docker DesktopのようにRemote Containers拡張の機能をそのまま使用することはできません。

WSL内から

# カレントディレクトリを開く
code .

のようにVisual Studio Codeを起動し、WSLに接続された状態にする必要があります。

接続した後は、Docker Desktop の場合と同じように Open Folder in Container... などのメニューが動作するようになります。

参考情報

5. ダッシュボードの代替

Docker DesktopのダッシュボードのようにGUIでのDocker環境管理を行いたい場合、Portainerを使用するのが簡単そうです。

インストール

以下のドキュメントページを

以下のようにたどり2

  • Portainer Community Edition
  • Install Portainer CE
  • Set up a new Portainer Server installation
  • Docker Standalone
  • Install Portainer with Docker on WSL / Docker Desktop

Deployment に記載のコマンドをWSL内から実行すればインストールは完了します。

起動したら、ブラウザから https://localhost:9443 にアクセスすると(ブラウザで自己署名証明書を受け入れる必要があります)、初期ユーザー登録画面になります。

適当なパスワードで Create user ボタンで登録します。

次の画面では、local environment を使う方 (Get Started) を選択します。

local がWSL内のDocker環境を表しています。

この中を確認すると、Docker Desktop のダッシュボードで提供されているようなコンテナ・イメージ・ボリュームなどの状況の確認や操作ができます。

ログの確認やコンソールアクセスなども可能です。

6. (おまけ) Docker用のディストリビューションを分ける

Ubuntuのディストリビューションを別の目的で使っていて、Docker環境に汚染されたくない、ディスク肥大化時に消したりできないのが気になる、という場合は、ディストリビューションを分けたほうが良いでしょう。

Docker用のディストリビューション作成

Windows上で、以下のようなコマンドで既存のディストリビューションをエクスポートします。 D:\backup\Ubuntu-20.04.tar の部分はエクスポート先の任意のパスです。

wsl --export "Ubuntu-20.04" D:\backup\Ubuntu-20.04.tar

続けて、以下のようなコマンドで新しいディストリビューションとしてインポートします。

wsl --import docker D:\wsl\docker D:\backup\Ubuntu-20.04.tar
  • docker の部分は、新しいディストリビューションに付ける名前です。
  • D:\wsl\docker の部分は、新しいディストリビューション用のディスクイメージを配置したいフォルダです。
  • 最後のパラメータは、さきほどエクスポートしたファイルのパスです。

この後、以下のコマンドでディストリビューションの一覧を確認すると、インポートしたものが追加されています。

wsl -l -v

結果:

  NAME            STATE           VERSION
* Ubuntu-20.04    Stopped         2
  docker          Stopped         2

これで、以下のコマンドのように新しいディストリビューションを指定してWSLを起動できるようになります。

wsl -d docker

デフォルトユーザーの変更

インポートしたディストリビューションでは、上記のように起動するとデフォルトユーザーが root になっているので、元のユーザーと同じになるようにします。

まず、以下のコマンドで元のディストリビューションのデフォルトユーザーのUIDを確認します(おそらく 1000 のはず)。

wsl -d "Ubuntu-20.04" id -u

確認できたら、PowerShellで以下のコマンドを実行します。

# さっき確認したUID
$uid = 1000
# 新しいディストリビューションの名前
$to_dist = 'docker'
Get-ItemProperty Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss\*\ DistributionName | Where-Object -Property DistributionName -eq $to_dist | Set-ItemProperty -Name DefaultUid -Value $uid

これは、ディストリビューション用のレジストリの DefaultUid を設定しているのと同じです。

この後は、以下のコマンドで一般ユーザーとして新しいディストリビューションを起動できます。

wsl -d docker

この後

あとは、このディストリビューションの中で 1~4 の手順と同様にDocker環境を構築していきます。

ディスクが肥大化したりしてディストリビューションを消したくなったら、以下のようなコマンドで消せます。

wsl --unregister docker

7. (おまけ2) VSCodeからWSL上のdockerコマンドを直接使用する

VSCodeのv1.61で、VSCodeがDocker機能を呼び出すときにWSL上の docker コマンドを使うようにするオプションが追加されました。

VSCodeで以下のオプション "Execute In WSL" (remote.containers.executeInWSL) にチェックを入れて有効にすると、

Open Folder in Container などでRemote Containers拡張がdockerコマンドを実行するときに、自動的にWSL内のDockerで実行してくれるようになります。

これにより、WSL上だけにDockerをインストールすれば、(VSCodeの操作の上では)Docker Desktopと全く同じ感覚で Remote Containers を使えるようになりました。

ログを見ると、以下のようにwsl上でコマンドを実行し、パスも自動的に変換してくれています。

[55 ms] Remote-Containers 0.209.6 in VS Code 1.63.2 (899d46d82c4c95423fb7e10e68eba52050e30ba3).
[54 ms] Start: Resolving Remote
[60 ms] Start: Run: wsl -l -v
[91 ms] Start: Run: wsl -d docker -e wslpath -u d:\src\sandbox
[162 ms] Start: Run: wsl -d docker -e /bin/sh -c cd '/mnt/d/src/sandbox' && /bin/sh

VSCode v1.64 以降では、設定 "Execute In WSLDistro" (remote.containers.executeInWSLDistro) で対象のディストリビューションを指定することもできます。何も指定しないとデフォルトのディストリビューションが使われます。

8. 結論

金を払えるなら払ったほうが楽ですね。


  1. Remote Containersの設定 Docker Compose Path (remote.containers.dockerComposePath) を docker compose に設定すれば v2 でも動作する可能性はありますが、未検証です。 

  2. 最新バージョンを指せるURLがないため、このようなまわりくどい書き方になってしまっています。