Windows+WSL2+Docker構築方法

# この記事でやりたいこと
Windows11にWSL2をインストールし、Dockerコンテナ上に開発環境を構築する方法を記載します。
私用PCでTypeScriptの学習を実施しようと思いましたが、環境を汚したくないためコンテナ上でやろうと思いました。インストールやパス設定関連で少し時間がかかってしまったので備忘録として記載します。
# 前提条件
* Windows 11 Home
* VSCode
# 作業手順
### 1. WSL2のインストール
Windows11ではコマンドプロンプト上で以下コマンドを実行するだけでインストールが完了します。
同時にubuntuもインストールされます。
```
wsl --install
```
[Microsoft公式ドキュメント](https://learn.microsoft.com/ja-jp/windows/wsl/install)
### 2. ubuntuの初期設定
1.の実行時に自動でubuntuがインストールされているので、ubuntuを起動しユーザー名、パスワードを登録する。
### 3. ubuntuにdockerをインストール
ubuntu上で以下コマンドを順に実行
実行時にパスワードを聞かれるので2で設定したパスワードを入力する
```
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
[Docker.docs](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)
### 4. VScodeの設定
拡張機能のRemote Developmentをインストール
* 画面左下の「リモートウィンドウを開きます。」をクリックしウィンドウを開く
* WSLへの接続をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815993/7ea8785e-f347-15c1-4be5-482bfc2c3989.png)
* 下記のようにWSL:UbuntuとなっていればWSLに接続されている状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815993/87e2efe0-de90-2e08-291b-58145f6ab0be.png)
### 5. コンテナの作成
* まずはコンテナ作成に必要なimageを持ってくる
(今回は例としてubuntu)
```
sudo docker pull ubuntu
sudo docker images
```
`sudo docker images`でローカル上にubuntuのimageがあることを確認する
* コンテナを作成
testという名前でコンテナを作成
同時にホスト(ubuntu)側の`project_wsl`ディレクトリとコンテナ側の`project_container`のディレクトリをアタッチする。
```
sudo docker run -it --name test -v /project_wsl:/project_container -u $(id -u):$(id -g) ubuntu
```
オプションの意味
* `--name test`
コンテナの名称を指定
* `-v /project_wsl:/project_container`
ホストのvolume`/project_wsl`と、コンテナのvolume`/project_container`をコロンでつなげることによりアタッチ可能
* `u $(id -u):$(id -g)`
ホスト側からファイル操作権限を与えたい場合のコマンド
### 6. コンテナにroot権限で入る
* `docker run`コマンドでは作成と同時にコンテナ内に入った状態となるので、一度コンテナから抜けてroot権限で入り直す
※TODO: 作成と同時にrootで入る方法は今後調査します。
```
exit
sudo docker start test
sudo docker exec -it -u root test /bin/bash
```
### 7. コンテナ内でライブラリをインストール
今回はコンテナ内でNode環境を構築する
* aptのアップデート
```
apt update
apt upgrade -y
```
* curl,git, brewのインストール
```
apt-get install build-essential procps curl file git -y
# brewのインストール
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
[Homebrew公式ドキュメント](https://brew.sh/)

※実行中に処理が止まったら以下の入力で適宜対応する
`Do you want to continue`→yesを入力して進む
`Press RETURN/ENTER to continue or any other key to abort:`→Enterを押して進む
* brewインストールの実行で下記のようなwarningが出力された場合には`Next steps`以降のコマンドを確認し実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3815993/4cfd6713-946b-e8cd-78f0-7513f2784283.png)
上記画像では以下の2行のコマンドとなる
```
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
apt-get install build-essential
```
上記でパスの設定が完了したので最後にnodeのインストールを行う
```
brew install nodebrew
nodebrew setup
nodebrew install stable
```
正常にインストールされていることを確認する。現在インストール済みのバージョンがリスト形式で表示されるが、初回ではバージョンが1つのみ表示されるはず。
```
nodebrew ls
```
また、初回では`current: none`となっているので使用するバージョンを設定する
```
nodebrew use [バージョンを指定]
```

上記で設定か完了したので、再度`nodebrew ls`を実行すると`current: [バージョン]`が表示される。
* nodeのパスを設定
これを実行することで.bashrcに環境パスが設定される
```
# bashで実行する場合は以下
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
```
### 確認
インストール、設定が完了したので再ログインして反映されていることを確認する。
```
exit
sudo docker start test
sudo docker exec -it -u root test /bin/bash
```

# [備考1] Dockerfileでの実行方法
ここまでは、作成したコンテナに入った状態で個別に必要なライブラリをインストールする方法を記載したが実際にはDockerfileに一通り記載することでコンテナ起動時に一括で実行が可能なimageを作成する。
### 1. ubuntu上で作業用のディレクトリ作成
適当なディレクトリを作成し、作成したディレクトリに移動する
```
sudo mkdir project_wsl
cd project_wsl
```
### 2. DockerFileの作成
作成したディレクトリ内部で以下のファイルを作成する
この内容は記事前半で実施した環境構築とほぼ同様のコマンドを実行している
```dockerfile
FROM ubuntu:20.04

# 必要なパッケージのインストールとシステムの更新
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y build-essential procps curl file git

# Homebrewのインストール
RUN /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# Homebrewの環境変数を設定
ENV PATH="/home/linuxbrew/.linuxbrew/bin:${PATH}"

# nodebrewの設定
ARG NODE_VERSION=16.4.0
RUN brew install nodebrew && \
    nodebrew setup && \
    nodebrew install $NODE_VERSION && \
    nodebrew use $NODE_VERSION

# 環境変数を設定
RUN echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bashrc

# 環境変数を反映させるためのシェル再起動
ENTRYPOINT ["/bin/bash"]
```
※作成する場合は、vscode上で拡張子なしの`Dockerfile`というファイルを作成する
### 3. Dockerfileを使用してimageを作成
コマンドを実行してimageを作成することで個別に実行した結果と同等のコンテナを作成する
```
sudo docker build --build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g) -t test_image .
```
オプションの意味
* `-t test_image`
Dockerfileにより作成されるimageの名称を指定
* `.`
カレントディレクトリにDockerfileがあることを示している
* `--build-arg USER_ID=$(id -u)`
現在のユーザーIDを設定する
* `--build-arg GROUP_ID=$(id -g)`
現在のユーザーグループIDを設定する
### 4. 作成したimageを使用してコンテナを作成する
```
sudo docker run -it --name test -v /project_wsl:/project_container test_image
```
# 注意点
Dockerfileを利用するにあたって最初はパス設定などのコマンドも一つのRUNコマンドに記載していましたが、エラーが発生しました。調査しているとパス設定などは個別にENVを実行しないと反映されないようです。上記のDockerfileでは個別にENVコマンドを実行することで環境設定を反映させるようにしています。
ですので、個別のコマンドをそのままDockerfileにまとめたい場合は環境変数の設定に注意が必要です。
# 今後
ユーザー権限周りについてはあまり設定ができておらず、上記の手順だとコンテナ側で作成したファイルをubuntu上で編集しようとしても権限エラーが出ます。その設定も今後調査したいと思います。