Windows11でWSL2とDockerを使ってVScode＋Django＋MySQLの開発環境を構築する

# はじめに

Djangoで簡易メモAPIを開発しました。

一通りの実装が出来たので、振り返りと備忘録を兼ねて、数回に分けて記事にしていこうと思います。初回は開発環境の構築です。

# 開発経緯

Javascriptの勉強を始めた友人が、ログイン機能付きのMemoアプリを作る課題を今後進める予定なのでそのバックエンド側として開発しました。

自分の個人開発ではいつもsupabaseなどのサービスを使っているので、JavaでCRUD処理の実装を行って以来バックエンドは触れてこなかったので、自分で作ろうと思いました。

# 概要

最終的な完成図か下図のようになります。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/caac9f9e-86b2-c370-b633-134a24cbfbab.png)

開発したDjangoのアプリケーションを、terraformで構築したAWS環境にデプロイします。デプロイ環境作成はCirclCIとAnsibleで自動化し、サーバーテストも行います。

完成品はGitHubに公開しています。
Readmeを読んで実際に試していただけるようにもしました。

# 開発工程

一度にすべてはアップできないので、複数回に分けて投稿していきます。

投稿したら下記に追加していきます。

1. Windows11でWSL2とDockerを使ってVScode＋Djangoの開発環境を構築する（今ここ）

# 前提環境

Windows11

VScode

WSL2をインストール

[公式はこちら](https://learn.microsoft.com/ja-jp/windows/wsl/install)

# 環境構築手順

## WSL2とは

WSL2（Windows Subsystem for Linux 2）は、Windows 10およびWindows 11上でLinux環境を実行するためのマイクロソフトのプラットフォームです。

WSL2は、実際のLinuxカーネルを使用しており、WSL1に比べて大幅に改善されています。これにより、より高速で完全なLinux体験が提供されます。

いろいろなディストリビューションがあり、好きなLinuxOSの環境をWindowsで使えます。おかげで、この間買い替えたPCも、高額なMacにせずWindowsを選択できました。BTOでゴリゴリに盛っても13万。拡張性も高いのでWindows好きです。

今度勤める会社の貸与PCがMacみたいなので、Macはそちらで経験する予定です。

## WLS2のインストール

Windows11でWSL2のインストールはコマンド一発で出来るようになりました。

ターミナルという色々なCLIをまとめて使えるツールもプリインストールされているので、これを使ってUbuntuをインストールします。

そしてインストールしたUbuntuもターミナルで使えるようにします。

コマンドプロンプトかPowerShellを管理者権限で開きます。（右クリック→管理者で開く）

ターミナルの場合Ctrlキーを押しながら新しいタブを開くと管理者権限で開けます。

下記のインストールコマンドを実行します。

```powershell
wsl --install
```

このコマンドにより、WSL を実行し、Linux の Ubuntu ディストリビューションをインストールするために必要な機能が有効になります。

`wsl --install` コマンドを使用してインストールされた新しい Linux インストールは、既定で WSL 2 に設定されます。

Linux ディストリビューションが WSL 1 と WSL 2 のどちらに設定されているかを確認するには、コマンド `wsl -l -v` を使用します。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/0af09440-fdc6-4038-944e-9e119463b0a3.png)


上記のコマンドは、WSL がインストールされていない場合にのみ機能します。`wsl --install` を実行して WSL ヘルプ テキストが表示される場合は、`wsl --list --online` を実行して使用可能なディストリビューションの一覧を表示し、`wsl --install -d <DistroName>` を実行してディストリビューションをインストールしてみてください。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/f4d02228-e01a-3d69-c0a8-c9c932cc1642.png)


**`Ubuntu-22.04`**をインストールしてみます

```powershell
wsl --install -d **Ubuntu-22.04**
```

ユーザーネームとパスワードの入力を求められるので入力して完了です。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/c413a926-17c7-540b-3d21-6c55f9e7d28b.png)


入力後すぐにディストリビューションが起動するので下記コマンドでパッケージを更新しておくといいです。

```powershell
sudo apt update && sudo apt upgrade
```

抜けるときは`exit`

一応バージョンの確認

```powershell
wsl -l -v 
```

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/485cacd1-b0ca-960c-7296-29c30f39bc06.png)

## インストールしたUbuntuをターミナルで使用する

ターミナルのタブでもインストールしたディストリビューションが選択できるようになっています。（元々ターミナルを開いていた場合は再起動してください）

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/ba0ef5b4-de72-8da4-0d34-921654590c1f.png)

設定のプロファイルから開始ディレクトリをユーザーにしてきましょう。

ユーザーネームはディストリビューションに登録したユーザー名に置き換えてください。

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/088c5b9f-9af4-181c-5017-08b5fe5ab00b.png)

Djangoのプロジェクトもこの配下にディレクトリを作っていきます。

Cドライブ配下にもアクセスできますが、ファイルシステムの関係で読み込みが遅くなるので、WLS2のユーザーディレクトリ配下を使いましょう。

## アンインストール

Linux ディストリビューションは Microsoft Store を介してインストールできますが、ストアを介してアンインストールすることはできません。

WSL ディストリビューションの登録を解除してアンインストールするには下記のコマンドを使用します。

```powershell
wsl --unregister <DistributionName>

```

`<DistributionName>` を対象の Linux ディストリビューションの名前に置き換えると、WSL からそのディストリビューションの登録が解除され、再インストールまたはクリーンアップできます。

## Docker Desktopのインストール

[公式サイト](https://www.docker.com/products/docker-desktop/)にてDocker Desktop for Windowsのインストーラをダウンロードしてダウンロードしましょう。

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/a7b8dfff-0084-af8a-644f-a2f4607c4e72.png)

インストール方法については下記サイトが分かりやすいです。

[チグサウェブ【**【Docker Desktop】Windowsにインストール（WSL2）**】](https://chigusa-web.com/blog/windows%e3%81%abdocker%e3%82%92%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%97%e3%81%a6python%e7%92%b0%e5%a2%83%e3%82%92%e6%a7%8b%e7%af%89/)

その他にも参考になる記事がたくさんあります。

## VScodeの設定

ローカル環境のVScodeに**Remote Development**という拡張機能をインストールしておきます。これはリモート接続で開発環境を作るための拡張機能がセットになっているパックです。

![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/7dee4bc9-307d-5058-8bf5-b3eb132e784b.png)


インストールしたらVScodeを再起動しておきましょう。

この状態でターミナルからUbuntuを開いて、プロジェクトディレクトリを作成してディレクトリ内に移動ます。そのフォルダ内でVScodeを開きます。カレントディレクトリで開けるようにdotを忘れずに。

```bash
mkdir sample-project

cd sample-project/

code .
```

下図のようのにUbuntuで開けていればOKです。

![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/972ffdd7-f67f-6736-06f2-e0c222b83251.png)

## devcontainer機能を使ってDockerでコンテナ構築する

プロジェクトのディレクトリが開けたら、その直下に`.devcontainer`というディレクトリを作成し、その中に3つのファイルを作成します。

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/36a45f7d-686b-e768-7e8f-fb51c4dfb8b2.png)

それぞれのファイルの中身は下記のように編集します

- **devcontainer.json**

```jsonc:devcontainer.json
{
	"name": "sample",
	// イメージ・コンテナを作成するファイルを指定。
    // 同じディレクトリのdocker-compose.ymlを指定します
	"dockerComposeFile": "docker-compose.yml",
	// リモート先のVS Codeにインストールする拡張機能
	"service": "app",
	//開発コンテナ内のWorkspaseディレクトリを開始ディレクトリにします
    "workspaceFolder": "/workspace",
	"shutdownAction": "stopCompose",
	"customizations":{
		"vscode":{
				//仮想コンテナ内のVScodeの設定を予め指定できます。
				//通常のsettings.jsonと同じように設定可能です。
			"settings": { 
				"python.analysis.extraPaths": [
				"/usr/local/lib/python3.11/site-packages"
				],
				"[python]": {
					//フォーマッターを指定して保存時にトリガーするように設定
					"editor.defaultFormatter": "ms-python.black-formatter",
					"editor.formatOnSave": true
				  }
			},
			//仮想コンテナ内のVScodeにインストールしておきたい拡張機能を拡張機能IDで指定できます。
			"extensions": [
				"ms-azuretools.vscode-docker",
				"ms-python.python",
				"HashiCorp.terraform",
				"circleci.circleci",
				"redhat.vscode-yaml",
				"batisteo.vscode-django",
				"thebarkman.vscode-djaneiro",
				"ms-python.black-formatter"
			]
		}
	}		
}
```

- **docker-compose.yml**
    
    ymlファイルはインデントがズレるとエラーになるので注意
    

```yaml:docker-compose.yml
version: '3'

services:
  app:  # appという名前のサービスを定義
    build: .　 # Dockerファイルの場所を指定（カレントディレクトリ）
    tty: true　 # コンテナを起動した状態に保つためのオプション

        # コンテナ内からterraformを利用したい場合にAWSアクセスようのアクセスキーが必要
        # 環境変数に入れておくと、terraformが環境変数から自動的に読んでくれる
        # 誤ってGitHubに公開しないように注意
        # 環境変数の追加は都度exportコマンドでも可能
    environment:
      AWS_ACCESS_KEY_ID: [AWSのアクセスキーID]
      AWS_SECRET_ACCESS_KEY: [AWSのアクセスキー]

    # ホストマシンとコンテナ間でデータを共有するためのボリュームを指定
    volumes:
      - ../:/workspace

    # mydbというサービスに依存。これにより、appサービスはmydbサービスが起動した後に起動
    depends_on:
      - mydb

  # mydbという名前のサービスを定義
  mydb:
    image: mysql:8.0.20　
    container_name: my-db
		
    # mysql構築時に使用する環境変数
    # コチラも秘匿情報の場合GitHubに公開注意 
    environment:
      MYSQL_ROOT_PASSWORD: [パスワード]
      MYSQL_DATABASE: [データベース名] 
      MYSQL_USER: [ユーザー名]
      MYSQL_PASSWORD: [上記ユーザーのパスワード]
      TZ: 'Asia/Tokyo'
    command: >
      mysqld --default-authentication-plugin=mysql_native_password
    
     # MySQLのデータを永続化するためにボリュームを使用します。
    volumes:
      - db_data:/var/lib/mysql
		
    # ポートのマッピング
    ports:
      - 3306:3306

volumes:
  db_data:
```

- **Dockerfile**

```docker:Dockerfil
# 使用するイメージ
FROM python:3.11　

# 環境変数PYTHONUNBUFFEREDを1に設定します。
# これにより、Pythonの出力がバッファリングされず、コンソールに直接表示されるようになります。
# これは、Dockerコンテナのログをリアルタイムで見るのに役立ちます。
ENV PYTHONUNBUFFERED 1

# コンテナ立ち上げ時に走らせるコマンド
RUN apt-get update \
    && apt-get install -y default-mysql-client \
    && rm -rf /var/lib/apt/lists/*
RUN pip install --upgrade pip
RUN pip install django
RUN pip install mysqlclient
```

### GPTの解説

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/e0196253-2d23-e9aa-4914-6f5a7ceddc69.png)

その他、下記の記事に有用そうな環境変数がまとめられています。

**[Docker で Python を使うときに有用な環境変数まとめ](https://www.lifewithpython.com/2021/05/python-docker-env-vars.html)**

## コンテナビルド

ファイルを作成したら、VScode左下の`**>< WSL:Ubuntu**`をクリックします。

![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/1610dafc-b0ac-0557-490e-7b412eb12989.png)

上部にリモート接続のメニューが開いたらその中から、コンテナーで再度開くをクリック

![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/adf7c971-5c2e-4e9a-4abc-7b36d53a86b3.png)

コンテナのビルドが始まります。

下図のように左下に開発コンテナと表示され、エクスプローラーのディレクトリもWorkspaseとなっていれば成功です。Dockerでもコンテナが立ち上げて動いていることを確認できます。

![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/3d4556c7-9034-c050-1f2e-c8ad22008a27.png)

![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/b6571896-9a5f-3f2c-40c4-db42152bde15.png)

サービス名やコンテナ名がすでに別のコンテナで使われていたり、ポートが使われていたりするとエラーがでるので適宜調整が必要です。私もすでに別コンテナで3306ポートを使っていたので、新しいものは3307ポートで立ち上げました。

エラーでコンテナが開けなくても、コンテナ自体は作成されている場合があります。その場合、Docker Desktopで確認して削除してからリトライした方が上手くいきます。

サービス名やディレクトリ名など変更した場合、対応する`devcontainer.json`も併せて変更を忘れないようにしてください。

また`.yml`はインデントがズレていたり、不要の文字が混ざっているとエラーになるので、そのままコピペした場合にエラーでる場合があります。その場合、コメントを消してしっかりインデント整えると良いです。

## 環境の確認

### PythonとDjangoのバージョン確認

無事コンテナが立ち上がったら、VScodeのターミナルを開いて下記のコマンドでバージョン確認しておきます。PythonとDjango、MySQLのクライアントがインストールされているのが確認できます。

```bash
python --version
pip list
```

![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/07c65d17-6fce-3806-1c16-a5cabd22e117.png)

### データベースにアクセス

MySQLにちゃんとアクセスできるか確認します。

```bash
mysql -h [データベース名] -u root -p
パスワードを聞かれるので入力
Enter password:[docker-composeで環境変数に設定したrootパスワード]
```

下記のように表示されればアクセス成功

![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/710e505e-1c1e-f386-bdc7-05c98da4b9c5.png)

`SHOW DATAVASES;`コマンドで自分の作成したDBが作られていることを確認

![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/bb946451-d490-6fa0-ad96-e93355bf14dc.png)

# まとめ

以上でDjangoの開発環境が整いました。それぞれ自分の使いやすいように拡張機能とか設定を変えて使ってみてください。

ちなみに、WSL2の`Ubuntu`で操作していましたが、立ち上げた開発コンテナ内のディストリビューションは`Dabian`みたいです。ここは注意ですね。私も最初`Ubuntu`のつもりでパッケージインストールしようとしてできなかったりしたので。

![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1614172/826477db-f966-963a-f742-620c55d14aed.png)

もちろんDockerイメージを探して`Ubuntu`のイメージを探すこともできると思います。

仮想環境での開発はPC内のディレクトリが荒れないのでとってもいいですね。Windowsでも簡単にLinux使えるので、練習にも良いです。

開発用でもWindows選択する人も増えているのではないかな～。スマホもAndroidなのでWindowsでコスパよく開発していきます。

次の記事ではDjangoのプロジェクトを立ち上げていきます！