WSL2でLinux開発環境を構築する

# はじめに

Windows でWSL2を使ったLinux開発環境を構築してみる。(所要時間: 60分)

**追記: 2021/12/18**

WSL2がコマンド一発で入れられるようになったり、Windows Terminalの設定画面がGUIになったりしたので、古い手順を一新した。

**修正: 2024/04/18**

GPGキーのインポートで`apt-key` は非推奨になったため、代替の手段に修正。

**修正: 2024/07/05**

Windows 11だとデフォルトで `systemd` が有効になり、Dockerが起動しなくなるため回避策を追加。

**修正: 2024/11/28**

Ubuntuのバージョンを24.04に更新。

# 必要環境

* Windows 10
  * Version 1903 (OS Build 18362.1049以降)
  * Version 1909 (OS Build 18363.1049以降)
  * Version 2004以降

* Windows 11

# 1.&nbsp;WSL2 環境のセットアップ

WSL の詳細は Microsoft の[公式ドキュメント](https://docs.microsoft.com/ja-jp/windows/wsl/)を参照。

管理者権限でPowerShellを起動して以下のコマンドを実行する。

```bash:powershell
wsl --install -d Ubuntu-24.04
```

PCの再起動を促されるので再起動する。


## Linux ディストリビューションのインストール

再起動するとOSのインストール作業が始まる。
しばらくすると、ユーザーを作成するプロンプトが表示されるので、適当なユーザー名とパスワードを入力する。
![2020-09-16_11h55_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59531/0c3949b0-3b16-6a7e-8962-2ec98d90b92e.png)

**Windows → WSL へのアクセス**

エクスプローラーで `\\wsl.localhost\Ubuntu-24.04` を表示するとルートディレクトリ `/` が表示される。

**WSL → Windows へのアクセス**

WSL ターミナルで `/mnt/c` でCドライブの内容が表示できる。


# 2.&nbsp;Windows側の作業

開発に必要なアプリケーションをインストールする。

## Windows Terminal

1. Microsoft Storeからインストールする。
https://www.microsoft.com/store/apps/9N0DX20HK701

## Visual Studio Code

1. Microsoft Storeからインストールする。
https://apps.microsoft.com/store/detail/XP9KHM4BK9FZ7Q

1. Windows 側にインストールされた VSCode から WSL上のディレクトリを開くための設定をする。

1. VSCodeの拡張機能で [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) をインストールする。

1. WSL ターミナルで `code` を実行する。
VSCodeが起動し、左下のステータスが「WSL: Ubuntu」と表示されていれば成功。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59531/3a3347b9-7c0b-19b6-05dc-4a5bd9c881aa.png)


# 3.&nbsp;Linux(WSL) 側の設定

## 日本語ロケールの設定

パッケージを最新にする

```bash
$ sudo apt update && sudo apt upgrade -y
```

日本語言語パックのインストール

```bash
$ sudo apt install -y language-pack-ja
```

ロケールを日本語に設定

```bash
$ sudo update-locale LANG=ja_JP.UTF-8
```

日本語マニュアルのインストール

```bash
$ sudo apt install -y manpages-ja manpages-ja-dev
```

日本語フォントのインストール

```bash
$ sudo apt install -y fonts-noto
```

<kbd>Ctrl + D</kbd> でターミナルを終了し、再起動する。
ロケールが日本語に設定されていることを確認する。

```bash
$ date
2020年  9月 15日 火曜日 15:59:05 JST
```

```bash
$ locale
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=
```

## Gitの設定

ユーザー名とメールアドレスを設定する(スペースを含む場合はダブルクォーテーションで囲む)

```bash
$ git config --global user.name "ユーザー名"
$ git config --global user.email "メールアドレス"
```

その他Gitのオススメ設定

```bash
$ git config --global core.autocrlf input # コミット時に改行コードをCRLFからLFに変換する
$ git config --global core.quotepath false # 日本語ファイル名をエスケープする
$ git config --global color.ui true # コマンドに色をつける
$ git config --global url."https://".insteadOf git:// # gitプロトコルの代わりにhttpsプロトコルを使用する
$ git config --global credential.helper store # Gitの認証情報をファイルに保存する
$ git config --global fetch.prune true # git pull時に常にpruneする
$ git config --global grep.lineNumber true # git grep時に行番号を表示する
$ git config --global color.grep.filename cyan # git grepの結果のファイル名の色をcyanに設定する
$ git config --global color.grep.lineNumber magenta # git grepの結果の行番号の色をmagentaに設定する
$ git config --global init.defaultBranch main # git init時に作成されるデフォルトブランチをmainにする
```

## Linuxパッケージのインストール

gccやg++等C関連のコンパイラを含むパッケージをインストールする (RubyやPythonなどでCネイティブの拡張ライブラリをビルドする際に必要となる)

```bash
$ sudo apt install -y build-essential
```

## Homebrewのインストール

[Homebrew](https://brew.sh/ja/)のインストール

```bash
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

シェルにパスを通す

```bash
$ echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> ~/.bashrc
$ source ~/.bashrc
```

バージョンを表示してみる

```bash
$ brew -v
Homebrew 4.4.24
```

## anyenvのインストール

プロジェクト毎のプログラムのバージョンの競合を避けるために異なるバージョンをインストールし、管理できる \*\*env (Rubyならrbenv、Pythonならpyenvなど) というツールがあるが、扱う言語自体が増えてくると \*\*env 自体の管理が煩雑になるため、さらにそれをまとめて管理できる [anyenv](https://github.com/anyenv/anyenv) をインストールする。

**GitHubからリポジトリをクローンする**

```bash
$ git clone https://github.com/anyenv/anyenv ~/.anyenv
```

**シェルにパスを通す**

```bash
$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(anyenv init -)"' >> ~/.bashrc
$ source ~/.bashrc
```

**インストールマニフェストディレクトリを初期化する**

> ANYENV_DEFINITION_ROOT(/home/user/.config/anyenv/anyenv-install) doesn't exist. You can initialize it by:
> anyenv install --init

と表示されるので、その通り実行する。

```bash
$ anyenv install --init
```

**プラグインのインストール**

すべての **env を横断してアップデートできる[anyenv-update](https://github.com/znz/anyenv-update.git)をインストールする

```bash
$ git clone https://github.com/znz/anyenv-update.git ~/.anyenv/plugins/anyenv-update
```

## **env のインストール

anyenv がサポートしている言語は以下のとおり。

| **env | 対応言語 |
|:-:|:-:|
|Renv|R|
|crenv|Crystal|
|denv|D|
|erlenv|Erlang|
|exenv|Elixir|
|goenv|Go|
|hsenv|Haskell|
|jenv|Java|
|jlenv|Julia|
|luaenv|Lua|
|nodenv|Node.js|
|phpenv|PHP|
|plenv|Perl|
|pyenv|Python|
|rbenv|Ruby|
|sbtenv|sbt|
|scalaenv|Scala|
|swiftenv|Swift|
|tfenv|Terraform|

**env のコマンドはほとんど同じ体系で使うことができる。

```bash
# インストール可能なバージョンを表示する
$ **env install -l
# インストールされているバージョンを表示する
$ **env versions
# 特定のバージョンをインストールする 
$ **env install ...
# 特定のバージョンをアンインストールする
$ **env uninstall ...
# グローバル(システム全体)で利用するバージョンを指定する
$ **env global ...
# 実行したディレクトリ以下で利用するバージョンを指定する(.**-versionファイルが生成される)
$ **env local ...
# **env自身のバージョンを表示する
$ **env -v
```

以下はRuby, Python, Node.jsをインストールする場合

```bash
$ anyenv install rbenv
$ anyenv install pyenv
$ anyenv install nodenv
$ exec $SHELL -l # シェルを再起動する
```

各 `**env -v` でインストールされたことを確認した後で、実際のプログラム環境をインストールする。

## DBクライアント、開発パッケージのインストール

開発に利用するDBに合わせてインストールする。

### MySQL

```bash
$ sudo apt install -y mysql-client # mysqlコマンドが利用できるようになる
$ sudo apt install -y libmysqlclient-dev # RubyのGemをビルドする際に必要
```

バージョン情報を表示してみる。

```bash
$ mysql --version
mysql  Ver 8.0.28-0ubuntu0.20.04.3 for Linux on x86_64 ((Ubuntu))
```

### PostgreSQL

```bash
$ sudo apt install -y postgresql-client # psqlコマンドが利用できるようになる
$ sudo apt install -y libpq-dev # RubyのGemをビルドする際に必要
```

バージョン情報を表示してみる。

```bash
$ psql --version
psql (PostgreSQL) 12.9 (Ubuntu 12.9-0ubuntu0.20.04.1)
```

### Microsoft SQL Server

パブリック リポジトリの GPG キーをインポートする。

```bash
$ curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc
```

リポジトリを追加する。

```bash
$ curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list | sudo tee /etc/apt/sources.list.d/msprod.list
```

ソース一覧を更新し、パッケージをインストールする。

```bash
$ sudo apt update
$ sudo ACCEPT_EULA=Y apt install -y mssql-tools unixodbc-dev # sqlcmd, bcpコマンドが利用できるようになる
$ sudo apt install -y freetds-dev # RubyのGemをビルドする際に必要
```

シェルにパスを通す。

```bash
$ echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
$ source ~/.bashrc
```

バージョン情報を表示してみる。

```bash
$ sqlcmd -?
Microsoft (R) SQL Server Command Line Tool
Version 17.9.0001.1 Linux
Copyright (C) 2017 Microsoft Corporation. All rights reserved.

usage: sqlcmd            [-U login id]          [-P password]
  [-S server or Dsn if -D is provided]
  [-H hostname]          [-E trusted connection]
  [-N Encrypt Connection][-C Trust Server Certificate]
  [-d use database name] [-l login timeout]     [-t query timeout]
  [-h headers]           [-s colseparator]      [-w screen width]
  [-a packetsize]        [-e echo input]        [-I Enable Quoted Identifiers]
  [-c cmdend]
  [-q "cmdline query"]   [-Q "cmdline query" and exit]
  [-m errorlevel]        [-V severitylevel]     [-W remove trailing spaces]
  [-u unicode output]    [-r[0|1] msgs to stderr]
  [-i inputfile]         [-o outputfile]
  [-k[1|2] remove[replace] control characters]
  [-y variable length type display width]
  [-Y fixed length type display width]
  [-p[1] print statistics[colon format]]
  [-R use client regional setting]
  [-K application intent]
  [-M multisubnet failover]
  [-b On error batch abort]
  [-D Dsn flag, indicate -S is Dsn]
  [-X[1] disable commands, startup script, environment variables [and exit]]
  [-x disable variable substitution]
  [-g enable column encryption]
  [-G use Azure Active Directory for authentication]
  [-? show syntax summary]
```

### SQLite

```bash
$ sudo apt install -y sqlite3
```

バージョン情報を表示してみる。

```bash
$ sqlite3 --version
3.31.1 2020-01-27 19:55:54 3bfa9cc97da10598521b342961df8f5f68c7388fa117345eeb516eaa837balt1
```

## パブリッククラウドの CLI のインストール

### AWS CLI

```bash
$ sudo apt install -y unzip # zipファイルを解凍するために必要
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
$ rm -r aws awscliv2.zip
```

バージョン情報を表示してみる。

```bash
$ aws --version
aws-cli/2.24.21 Python/3.12.9 Linux/5.15.167.4-microsoft-standard-WSL2 exe/x86_64.ubuntu.24
```

### Azure CLI

```bash
$ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
```

バージョン情報を表示してみる。

```bash
$ az --version
azure-cli                         2.70.0

core                              2.70.0
telemetry                          1.1.0

Dependencies:
msal                            1.31.2b1
azure-mgmt-resource               23.1.1

Python location '/opt/az/bin/python3'
Config directory '/home/user/.azure'
Extensions directory '/home/user/.azure/cliextensions'

Python (Linux) 3.12.8 (main, Feb 26 2025, 06:59:52) [GCC 13.3.0]

Legal docs and information: aka.ms/AzureCliLegal


Your CLI is up-to-date.
```

### gcloud CLI

```bash
$ echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
$ sudo apt-get install apt-transport-https ca-certificates gnupg
$ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
$ sudo apt-get update && sudo apt-get install google-cloud-sdk
```

バージョン情報を表示してみる

```bash
$ gcloud --version
Google Cloud SDK 513.0.0
alpha 2025.02.28
beta 2025.02.28
bq 2.1.14
bundled-python3-unix 3.12.8
core 2025.02.28
gcloud-crc32c 1.0.0
gsutil 5.33
```

## Dockerのインストール

aptパッケージインデックスを更新し、パッケージをインストールするためにaptがHTTPS経由でリポジトリを使用できるようにする。

```bash
$ sudo apt-get update
$ sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release
```

Dockerの公式のGPGキーを追加する。

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

**stable** リポジトリを使うよう設定する。

```bash
$ echo \
  "deb [arch=amd64 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
```

aptパッケージインデックスを更新し、Docker Engineとcontainerdの最新バージョンをインストールする。

```bash
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
```

Docker Engineを起動する。

```bash
$ sudo service docker start
```

このままだとdockerコマンド実行にsudo権限が必要になるため、dockerグループにユーザー権限を付与する。

```bash
$ sudo usermod -aG docker $USER
```

バージョン情報を表示してみる。

```bash
$ docker version
Client: Docker Engine - Community
 Version:           28.0.1
 API version:       1.48
 Go version:        go1.23.6
 Git commit:        068a01e
 Built:             Wed Feb 26 10:41:12 2025
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          28.0.1
  API version:      1.48 (minimum version 1.24)
  Go version:       go1.23.6
  Git commit:       bbd0a17
  Built:            Wed Feb 26 10:41:12 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.7.25
  GitCommit:        bcc810d6b9066471b0b6fa75f557a15a1cbf31bb
 runc:
  Version:          1.2.4
  GitCommit:        v1.2.4-0-g6c52b3f
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
```

WSL起動時にDocker Engineを自動起動するよう設定する手順は以下の記事を参照。

https://qiita.com/amenoyoya/items/41a2334cbc1facb87864

:warning: Windows 11の場合、デフォルトで `systemd` が有効になっているためserviceと競合してDockerデーモンが起動しなくなる。解決するには　`/etc/wsl.conf` の以下の定義を削除すればOK。

```/etc/wsl.conf
[boot]
systemd=true
```

以上、お疲れ様でした！🎉