WSL2 Ubuntu に Docker 導入(Docker Desktop for Windows に変えて)

f:id:Naotsugu:20200517212714p:plain


はじめに

Docker Desktop for Windows の代替として、WSL2 上の Ubuntu-20.04 に docker を導入する手順です。

short version は以下となります。

# 事前準備
$ sudo apt update
$ sudo apt install -y apt-transport-https

# dockerパッケージリポジトリ追加
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# dockerインストール~デーモン起動~コンテナ実行
$ sudo apt update
$ sudo apt install docker-ce

$ sudo service docker start
$ sudo docker run --rm hello-world


Convenience Script を利用したインストール

Docker のインストール用のシェルスクリプト(convenience script)が用意されています。

$ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh

ただ、公式ドキュメントでは以下のような説明がされています。

convenience script は本番環境には推奨されませんが、お客様のニーズに合わせたプロビジョニングスクリプトを作成するための例として利用できます

ということで、ここでは convenience script ではなく、個別の手順で進めることとします。たいした手順ではないので。


インストールに必要なパッケージ導入

インストール時に必要となるパッケージを apt (Advanced Packaging Tool) でインストールします。

$ sudo apt update
$ sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release

公式では apt-get ですが、Ubuntu 14.04 以降で推奨の apt を利用します。

それぞれのパッケージは以下となります。

  • apt-transport-https は apt で https を利用可能とする
  • ca-certificates CA証明書を可能とする(Ubuntu-20.04では導入済みのはず)
  • curl curl コマンド(Ubuntu-20.04では導入済みのはず)
  • gnupg GNU Privacy Guard(Ubuntu-20.04では導入済みのはず)
  • lsb-release ディストリビューションのバージョン確認コマンド(Ubuntu-20.04では導入済みのはず)

ということで、Ubuntu-20.04 では、sudo apt install -y apt-transport-https だけでも大丈夫です。


docker パッケージリポジトリの登録

apt で docker のパッケージをインストールしますが、事前に docker のパッケージリポジトリの公開鍵を GPG でキーリングに追加します。

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

続いて dockerのパッケージリポジトリを apt の sources.list として追加します。

$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

/etc/apt/sources.list に加え、sources.list.d 配下のリストが apt によるパッケージの検索対象となります。

docker パッケージのリリースチャネルは stable を指定しています(その他のリリースチャネルには、testnightly があります)(現在は edge はありません)。


dockerEngineのインストール

docker パッケージリポジトリを追加したので、後は apt でインストールするだけです。

$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io

それぞれのパッケージは以下です。

  • docker-ce docker エンジン
  • docker-ce-cli docker コマンドラインインターフェース
  • containerd.io docker コンテナランタイム

docker-ce は以下の依存関係となっています。

$ apt-cache depends docker-ce
docker-ce
  Depends: containerd.io
  Depends: docker-ce-cli
  Depends: iptables
  Depends: libseccomp2
  Depends: libc6
  Depends: libdevmapper1.02.1
  Depends: libsystemd0

そのため、docker-ce-clicontainerd.io は明示的に指定せず、sudo apt install docker-ce だけでも大丈夫です。


docker デーモンの起動

Linux における init デーモンは、SysVInit → Upstart → Systemd と変遷しており、現在は Systemd が主流です。

一方 WSL2 では、Windowsとの相互運用のために、独自の initデーモンが使われており、Systemd は存在こそしますが無効化されています。 起動しようとすると「System has not been booted with systemd as init system (PID 1)」というエラーになります(systemd-genie などのツールを使うなどして Systemd を動かすことはできます)。

apt により docker-ce をインストールすると、通常の Linux であれば systemd からデーモンが起動し、sudo systemctl status docker として確認できますが、WSL2 ではデーモンが起動しません。ですので、デーモンを手動で起動する必要があります。

$ sudo service docker start

これは、Upstart 用の起動スクリプト(/etc/init.d/docker)からデーモンを起動する操作となります。


docker イメージのリポジトリへProxyを経由する必要がある場合は、/etc/default/docker に Proxy サーバの設定を書いておきましょう。

export HTTP_PROXY=http://172.xx.0.1:8888
export HTTPS_PROXY=http://172.xx.0.1:8888
export NO_PROXY=localhost,127.0.0.1,docker-registry.example.com

Systemd の場合に /etc/systemd/system/docker.service.d/http-proxy.confEnvironment として定義することと同じです。


docker デーモンが起動すれば、バージョン確認は以下のように表示されます。

$ sudo docker version
Client: Docker Engine - Community
 Version:           20.10.9
 API version:       1.41
 Go version:        go1.16.8
 Git commit:        c2ea9bc
 Built:             Mon Oct  4 16:08:29 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.9
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.8
  Git commit:       79ea9d3
  Built:            Mon Oct  4 16:06:37 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.11
  GitCommit:        5b46e404f6b9f661a205e28d59c982d3634148f8
 runc:
  Version:          1.0.2
  GitCommit:        v1.0.2-0-g52b36a2
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0


docker コンテナの実行

ここまでで、後は普通にコンテナ操作ができます。

$ sudo docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
2db29710123e: Pull complete
Digest: sha256:...
Status: Downloaded newer image for hello-world:latest

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

なお、Docker Desktop for Windows では、C:\Users のようにWindowsパスをそのまま使えましたが、WSL2 からは /mnt/c/Users のようなマウントパスに置き換える必要があります。


一般ユーザで docker コマンドを利用する

docker コマンドは root ユーザー、または Docker のインストールプロセス中に自動的に作成される docker グループのユーザーのみが実行できます。

sudo なしで docker コマンドを実行するには、ユーザーを docker グループに追加します

$ sudo usermod -aG docker ${USER}

変更を直ちに反映するには su - ${USER} とするか、再度ログインします。

以下のように sudo なしでコンテナ操作が可能となります。

$ docker run --rm hello-world


docker-compose のインストール

docker-compose は以下で導入できます。が少し古いです。

$ sudo apt install docker-compose

現在、docker-compose は 2系になっており、Python から Golang に一からリライトされました。 1系と2系では、インストール方法も違い、いくつかのコマンドも変わっています。

ここでは、docker-compose の Github リリースから直接2系をインストールします。

https://github.com/docker/compose/releases/ から最新のリリースパッケージを取得します。

$ mkdir -p ~/.docker/cli-plugins/
$ curl -SL "https://github.com/docker/compose/releases/download/v2.0.1/[docker-compose-$](https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$)(uname -s)-$(uname -m)" -o ~/.docker/cli-plugins/docker-compose

v2.0.1 はインストールしたいバージョンに合わせて変更してください。

ダウンロードしたファイルに実行権限を付けます。

$ chmod +x ~/.docker/cli-plugins/docker-compose

インストール完了したのでバージョンを確認しておきましょう。

$ docker compose version
Docker Compose version v2.0.1

1系では docker-compose ですが、2系からは docker compose という書式になります。

アンインストールする場合は以下です。

$ sudo rm ~/.docker/cli-plugins/docker-compose


docker デーモンの起動

先に述べた通り、WSL2 では、デフォルトで Systemd が無効化されています。

無理やり Systemd を動かす方法もありますが、Windows11 または、(まだ正式リリースされていませんが)Windows10 21H2 からは、/etc/wsl.conf にコマンドを指定することで、WSL起動時に自動実行することができます。

/etc/wsl.conf を編集します(デフォルトではこのファイルは存在しません)。

$ sudo vi /etc/wls.conf

/etc/wsl.conf に以下のように記載することで、起動時にコマンドが実行できます。

[boot]
command="service docker start"

ここで定義したコマンドは、ルート ユーザーとして実行されるため、sudo する必要はありません。WSL 起動時に実行されるため、設定後は wsl --shutdown などで一度WSLを停止する必要があります。


Windows10 21H1 などの場合は、/etc/wsl.conf によるコマンドの自動実行がサポートされていません。その場合は、.bashrc などでデーモンを起動するのが簡単です。

sudo でパスワード無しでデーモンを起動できるよう、 /etc/sudoerssudo の設定を変更します。この設定変更は visodo により sudo 用のエディタを起動して行います。visodo は設定の書式をチェックして不正な定義が出来ないようになっているため、必ず visodo を使いましょう。

$ sudo visudo

f:id:Naotsugu:20211026210145p:plain

以下のような内容を追加します。

%docker ALL=(ALL)  NOPASSWD: /usr/sbin/service docker start

これにより、docker グループに所属するユーザに対して指定したコマンドがパスワード無しで実行できるようになります。特定ユーザに限定するには、%docker に変えて username のように指定することができます。コマンドは絶対パスで指定する必要があります。

編集終了後は Ctrl + X -> Y -> Enter で抜けます。

なお、sudo で引き継ぐ環境変数を指定する場合は、以下のように指定します。

Defaults  env_keep += "http_proxy"
Defaults  env_keep += "https_proxy"
Defaults  env_keep += "HTTP_PROXY"
Defaults  env_keep += "HTTPS_PROXY"

この例では、proxy の環境変数を sudo 時に引き継いで利用できるようになります。


~/.bashrc に以下を追加します。

if [ $(service docker status | awk '{print $4}') = "not" ]; then
  sudo service docker start > /dev/null
fi

これにより、docker デーモンの起動を自動化できます。

後は、普通に docker を使うだけです。



Docker

Docker

Amazon