WSL2 + Ubuntu 22.04.1 LTS上のDjangoアプリを、JetBrains Gateway + PyCharmにて開発し、Herokuにpushできるようにしてみた

しばらく前に ThinkPad P14s AMD Gen2 を購入し、使い始めました。

一通りのPCセットアップができたため、次は開発環境を構築することにしました。

そこで、WSL2 + Ubuntu 22.04 上に、過去作成したDjangoアプリの開発環境を構築してみたため、流れをメモに残します。

 
目次

 

環境

  • ThinkPad P14s AMD Gen2 の状態
    • OS Windows11
    • CPU AMD Ryzen 7 PRO 5850U
    • メモリ 48GB
      • 16GB + 後付で32GB
    • ディスク
      • SSD SKHynix 512GB HFS512GDE9X081N
    • 構築済の開発環境
  • PyCharm Professionalライセンス

 

この記事でやること

WSL2 + Ubuntu 22.04.1 LTS上で、Djangoアプリの開発を行えるようにします。

具体的には以下のとおりです。

   

Windows Terminalのセットアップ

Windows Terminal のインストール

Windows上で Windows Terminal アプリを検索したところ、アプリ自体は出てきたものの、クリックしても起動しない状態でした。

そこで、以下のページ経由で Windows Store を開いて、 Windows Terminal をインストールしました。
Windows ターミナルのインストール | Microsoft Docs

 

Windows Terminal の設定変更

Windows Terminalのデフォルトは PowerShell になっていました。

ただ、Windowsをメインで使っていた時期の関係上、PowerShellよりもコマンドプロンプトに慣れていることから、デフォルトをコマンドプロンプトにします。

 
Windows Terminal を起動し、 Ctrl + , で設定を開き、以下の内容で設定します。

項目
既存のプロファイル コマンドプロンプト
既存のターミナルアプリケーション Windowsターミナル

 
また、Windows Terminalで exit を入力したときにWindows Terminalを閉じてほしいことから、 設定 > 既定値 > 詳細設定 より、以下の設定にします。

項目
プロファイルの終了動作 プロセスの終了、失敗、クラッシュ時に閉じる

 

WSL2のセットアップ

Windows Terminal の準備ができたので、次はWSL2をセットアップします。

 

WSL2 のインストール

以下の記事に従い、使用可能なディストリビューションを確認します。

Windows Terminal を管理者で開き、 wsl --list --online を実行します。

>wsl --list --online

インストールできる有効なディストリビューションの一覧を次に示します。
既定の分布は ' * ' で表されます。
 'wsl --install -d <Distro>'を使用してインストールします。

  NAME            FRIENDLY NAME
* Ubuntu          Ubuntu
  Debian          Debian GNU/Linux
  kali-linux      Kali Linux Rolling
  openSUSE-42     openSUSE Leap 42
  SLES-12         SUSE Linux Enterprise Server v12
  Ubuntu-16.04    Ubuntu 16.04 LTS
  Ubuntu-18.04    Ubuntu 18.04 LTS
  Ubuntu-20.04    Ubuntu 20.04 LTS

 
wsl --list --online には、Ubuntu 22.04 がまだ来ていないようです。

そのため、今回は wsl --install でのセットアップを諦め、以下の手順を参考にして、手動で作業を進めます。

 

Windowsの機能の有効化

Windows11のメニュー構成に慣れていないため、直接 Windowsの機能の有効化または無効化 を開きます。

Win + ROptionalFeatures.exe を入力します。
参考: Windows 10ミニTips(158) コマンドラインからWindows 10の機能を有効・無効にする | マイナビニュース

 
以下の2つにチェックを入れます。

画面に従い、Windowsを再起動します。

 

WSLの状態を確認する

Windows Terminal を管理者として起動し、 wsl --help を入力すると、ヘルプの内容が増えていました。

次に、 wsl --status で現在の状態を確認します。

>wsl --status
既定のバージョン: 2

Windows Subsystem for Linux カーネルは、'wsl --update' を使用して手動で更新できますが、システム設定が原因で自動更新が発生することはありません。
カーネルの自動更新を受け取るには、 Windows Update の設定を有効にしてください:' Windowsの更新に、その他のMicrosoftの製品の更新情報を受け取る'。
詳細については、 https://aka.ms/wsl2kernel. を参照してください
WSL 2 カーネル ファイルが見つかりません。カーネルを更新または復元するには、'wsl.exe --update' を実行してください。

 
既定のバージョンが 2 になっているようです。そのため、 wsl --set-default-version 2 な設定は不要そうでした。

一方、WSL2のカーネルが見つからないようなので、画面の表示に従い wsl --update を実行します。

>wsl --update
更新をチェック中...
更新をダウンロード中...
更新をインストール中...
この変更は、次回の WSL 再起動時に有効になります。強制的に再起動するには、'wsl --shutdown' を実行してください。
カーネル バージョン: 5.10.102.1

 
画面にある通り、WSL2を強制的に再起動します。

>wsl --shutdown

 
再度 status を確認してみると、カーネルがインストールされたようです。

>wsl --status
既定のバージョン: 2

Linux 用 Windows サブシステムの最終更新日: 2022/09/06
Windows Subsystem for Linux カーネルは、'wsl --update' を使用して手動で更新できますが、システム設定が原因で自動更新が発生することはありません。
カーネルの自動更新を受け取るには、 Windows Update の設定を有効にしてください:' Windowsの更新に、その他のMicrosoftの製品の更新情報を受け取る'。
詳細については、 https://aka.ms/wsl2kernel. を参照してください
カーネル バージョン: 5.10.102.1

 
カーネルがインストールされたので、念のため wsl --list --online を実行しますが、Ubuntu 22.04 は表示されませんでした。

>wsl --list --online
インストールできる有効なディストリビューションの一覧を次に示します。
'wsl --install -d <Distro>' を使用してインストールします。

NAME            FRIENDLY NAME
Ubuntu          Ubuntu
Debian          Debian GNU/Linux
kali-linux      Kali Linux Rolling
openSUSE-42     openSUSE Leap 42
SLES-12         SUSE Linux Enterprise Server v12
Ubuntu-16.04    Ubuntu 16.04 LTS
Ubuntu-18.04    Ubuntu 18.04 LTS
Ubuntu-20.04    Ubuntu 20.04 LTS

 
そこで、 Microsoft Storeよりダウンロードして Ubuntu 22.04 をインストールすることにします。

 

WSL2にUbuntuをインストール

Microsoft StoreよりUbuntu 22.04.1 LTS をダウンロード

Microsoft Storeにて ubuntu を検索すると複数の結果が表示されます。今回は Ubuntu 22.04.1 LTS を選びます。

Ubuntu 22.04.1 LTS のダウンロードが終わったところで、表示されている 開く をクリックします。

 

Ubuntu 22.04.1 LTS をインストール

Ubuntu 22.04.1 LTSのインストーラーが起動します。ただ、インストーラーが文字化けしていました。

いちおう画面はそれとなく分かるようになっていたため、以下のように画面ごとの操作をしました。

  • 言語選択っぽい画面
    • Japanese を選択
      • クリックすると、 Select your language の表示になった
    • 画面の右下にカーソルを合わせるとポインタの表示が変わる部分があるので、クリック
      • ボタンが隠れているらしい
  • ユーザー情報の入力画面 (Profile setup)
    • 以下の項目について、適切な内容を入力。入力後は、また右下のボタンのありそうな位置をクリック
      • your name
      • Pick a username
      • Choose a password
      • Confrim your password
  • Advanced setup
    • デフォルトの内容のままにして、右下のボタンのありそうな位置をクリック
    • Mount location
      • デフォルト通り、 /mnt/ のまま
    • Mount option
      • デフォルト通り、空白
    • Enable Host Generation
      • デフォルト通り、チェックを入れたままにする
    • Enable resolv.conf Generation
      • デフォルト通り、チェックを入れたままにする

以上の設定を終えると、 Setup complete 画面になります。

その画面の裏側で設定を適用しているようで、画面がローディング表示になるためしばらく待ちます。

 
設定の適用が完了すると、

Hi, <user_name> You have successfully completed the setup.

It is suggested to run the following command to update Ubuntu to the latest version:

$ sudo apt update $ sudo apt upgrade

  • All settings will take effect after restarting Ubuntu

と表示されました。

そこで、右下のボタンがありそうな位置をクリックすると、ダイアログが閉じました。

 
なお、裏側では別のWindows Terminalが起動しており

Installation successful!
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.10.102.1-microsoft-standard-WSL2 x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
/etc/update-motd.d/50-landscape-sysinfo: 17: cannot create /var/lib/landscape/landscape-sysinfo.cache: Permission denied
27 updates can be applied immediately.
7 of these updates are standard security updates.
To see these additional updates run: apt list --upgradable



This message is shown once a day. To disable it please create the
/home/<user_name>/.hushlogin file.

のような内容が表示されています。

 

WSL2にインストールされたUbuntuを確認

続いて、管理者のWindows Terminalを起動し wsl --list を入力すると、Ubuntu-22.04 が認識されていました。

>wsl --list
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu-22.04 (既定)

 
WSLのバージョンも合わせて確認します。WSL2で設定されているようです。

>wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-22.04    Running         2

 
ここまでで、WSL2にUbuntu22.04.1 LTSをインストールできました。

 

Ubuntuのアップデート

別途開かれた Installation successful! と表示されているWindows Terminalを使い、Ubuntuをアップデートします。

$ sudo apt -y update
[sudo] <user> のパスワード:
ヒット:1 http://archive.ubuntu.com/ubuntu jammy InRelease
ヒット:2 http://security.ubuntu.com/ubuntu jammy-security InRelease
ヒット:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease
ヒット:4 http://archive.ubuntu.com/ubuntu jammy-backports InRelease
取得:5 http://archive.ubuntu.com/ubuntu jammy/main Translation-ja [295 kB]
取得:6 http://archive.ubuntu.com/ubuntu jammy/universe Translation-ja [1,534 kB]
取得:7 http://archive.ubuntu.com/ubuntu jammy/multiverse Translation-ja [7,160 B]
1,837 kB を 4秒 で取得しました (471 kB/s)
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています... 完了
状態情報を読み取っています... 完了
アップグレードできるパッケージが 27 個あります。表示するには 'apt list --upgradable' を実行してください。

 
引き続き upgrade の方も実行します。

$ sudo apt -yV upgrade

 
これで Ubuntu 22.04.1 LTSが最新化されました。

 

WSL2の設定

続いて、WSL2の設定を行います。

 

設定方針

メモリサイズ固定について

WSL2の場合、Windowsホストのメモリが枯渇してしまう問題があるようです。
WSL2によるホストのメモリ枯渇を防ぐための暫定対処 - Qiita

ただ、

現在のWSL2ではデフォルトのメモリサイズがPC搭載メモリの50%または8GBのうち、少ない方の値に変更された

とのことなので、今のところは何も設定せず様子を見ようと思います。

 

プロセッサ数について

WSL2のデフォルトでは、プロセッサ数は

The same number of processors on Windows

https://docs.microsoft.com/en-us/windows/wsl/wsl-config#configuration-setting-for-wslconfig

のようです。

ただ、JetBrains Gateway 2022.2.2 RC では、Windowsと同じプロセッサ数のままだとCPU使用率が100%になってしまいました。

そこで、プロセッサ数は、実機の半分(今回の場合 8 ) にしてみます。

 

WSL2の設定を変更する

Windows上で %USERPROFILE%\.wslconfig ファイルを作成します。

公式ドキュメントに従い設定を行います。なお、日本語版のドキュメントだと key も日本語翻訳されているので注意が必要です。
Configuration setting for .wslconfig | Advanced settings configuration in WSL | Microsoft Docs

今回はCPUの数を8に固定するため、以下の設定となります。

[wsl2]
processors=8

 
設定を適用するために、以下のコマンドを入力してWSL2をシャットダウンします。

wsl --shutdown

その後 Ubuntu 22.04.1 LTS をクリックすることで、WSL2が起動します。

 

WSL2上にDockerをセットアップ

WSL2上にDockerをインストール

今回、DockerはWSL2上で起動します。そこで、以下を参考にWSL2にDockerをインストールします。

# 1. Set up the repository
## install packages to allow apt to use a repository over HTTPS
$ sudo apt install -y ca-certificates curl gnupg lsb-release
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています... 完了
状態情報を読み取っています... 完了
ca-certificates はすでに最新バージョン (20211016) です。
ca-certificates は手動でインストールしたと設定されました。
lsb-release はすでに最新バージョン (11.1.0ubuntu4) です。
lsb-release は手動でインストールしたと設定されました。
curl はすでに最新バージョン (7.81.0-1ubuntu1.4) です。
curl は手動でインストールしたと設定されました。
gnupg はすでに最新バージョン (2.2.27-3ubuntu2.1) です。
gnupg は手動でインストールしたと設定されました。
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  libfreetype6
これを削除するには 'sudo apt autoremove' を利用してください。
アップグレード: 0 個、新規インストール: 0 個、削除: 0 個、保留: 0 個。


# 2. Add Docker’s official GPG key:
## 以下の2つのコマンドは、特に結果は表示されず
$ sudo mkdir -p /etc/apt/keyrings

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

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


# Install Docker Engine
## 1. Update the apt package index
$ sudo apt update
取得:1 https://download.docker.com/linux/ubuntu jammy InRelease [48.9 kB]
取得:2 https://download.docker.com/linux/ubuntu jammy/stable amd64 Packages [6,439 B]
ヒット:3 http://security.ubuntu.com/ubuntu jammy-security InRelease
ヒット:4 http://archive.ubuntu.com/ubuntu jammy InRelease
ヒット:5 http://archive.ubuntu.com/ubuntu jammy-updates InRelease
ヒット:6 http://archive.ubuntu.com/ubuntu jammy-backports InRelease
55.3 kB を 1秒 で取得しました (60.2 kB/s)
パッケージリストを読み込んでいます... 完了

## install the latest version of Docker Engine, containerd, and Docker Compose
$ sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています... 完了
状態情報を読み取っています... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
docker-scan-plugin (0.17.0~ubuntu-jammy) を展開しています...
以前に未選択のパッケージ libltdl7:amd64 を選択しています。
.../7-libltdl7_2.4.6-15build2_amd64.deb を展開する準備をしています ...
libltdl7:amd64 (2.4.6-15build2) を展開しています...
以前に未選択のパッケージ libslirp0:amd64 を選択しています。
.../8-libslirp0_4.6.1-1build1_amd64.deb を展開する準備をしています ...
libslirp0:amd64 (4.6.1-1build1) を展開しています...
以前に未選択のパッケージ slirp4netns を選択しています。
.../9-slirp4netns_1.0.1-2_amd64.deb を展開する準備をしています ...
slirp4netns (1.0.1-2) を展開しています...
docker-scan-plugin (0.17.0~ubuntu-jammy) を設定しています ...
containerd.io (1.6.8-1) を設定しています ...
Created symlink /etc/systemd/system/multi-user.target.wants/containerd.service → /lib/systemd/system/containerd.service.
docker-compose-plugin (2.6.0~ubuntu-jammy) を設定しています ...
libltdl7:amd64 (2.4.6-15build2) を設定しています ...
docker-ce-cli (5:20.10.17~3-0~ubuntu-jammy) を設定しています ...
libslirp0:amd64 (4.6.1-1build1) を設定しています ...
pigz (2.6-1) を設定しています ...
docker-ce-rootless-extras (5:20.10.17~3-0~ubuntu-jammy) を設定しています ...
slirp4netns (1.0.1-2) を設定しています ...
docker-ce (5:20.10.17~3-0~ubuntu-jammy) を設定しています ...
Created symlink /etc/systemd/system/multi-user.target.wants/docker.service → /lib/systemd/system/docker.service.
Created symlink /etc/systemd/system/sockets.target.wants/docker.socket → /lib/systemd/system/docker.socket.
invoke-rc.d: could not determine current runlevel
man-db (2.10.2-1) のトリガを処理しています ...
libc-bin (2.35-0ubuntu3.1) のトリガを処理しています ...
Scanning processes...
Scanning processor microcode...
Scanning linux images...

Failed to retrieve available kernel versions.

The processor microcode seems to be up-to-date.

No services need to be restarted.

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.

 

Dockerの設定変更

WSL2 + Ubuntu 22.04では iptables を legacy に差し替える

通常であれば sudo service docker start して docker run hello-world すれば hello world コンテナが起動します。

しかし、WSL2 + Ubuntu 環境のデフォルトのままだと、 sudo service docker start してOKと表示されても、docker run に失敗します。

# 起動したっぽく表示される
$ sudo service docker start
 * Starting Docker: docker                                                                                       [ OK ]

# しかし docker run しようとしても失敗する
$ docker run hello-world
docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?.
See 'docker run --help'.

 
原因は以下のようです。

The docker installer uses iptables for nat. Unfortunately Debian uses a modified version of nftables. You can convert the entries over to nftables or just setup Debian to use the legacy iptables.

Failed to start service Docker on WSL2 · Issue #485 · WhitewaterFoundry/Pengwin

 
そこで、以下を参考に、iptableをlegacyに切り替えます。
WSL2 (Ubuntu 20.04) + docker が動作しなかったことと解決策 - Qiita

# 切り替え
$ sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
update-alternatives: /usr/sbin/iptables (iptables) を提供するためにマニュアルモードで /usr/sbin/iptables-legacy を使います

$ sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacya
update-alternatives: /usr/sbin/ip6tables (ip6tables) を提供するためにマニュアルモードで /usr/sbin/ip6tables-legacy を使 います


# 設定が切り替わったかの確認
$ sudo update-alternatives --config iptables
alternative iptables (/usr/sbin/iptables を提供) には 2 個の選択肢があります。

  選択肢    パス                     優先度  状態
------------------------------------------------------------
  0            /usr/sbin/iptables-nft      20        自動モード
* 1            /usr/sbin/iptables-legacy   10        手動モード
  2            /usr/sbin/iptables-nft      20        手動モード

現在の選択 [*] を保持するには <Enter>、さもなければ選択肢の番号のキーを押してください:

 
設定が切り替わったので、再度Dockerの動作確認を行います。

# Dockerのサービスを起動
$ sudo service docker start
 * Starting Docker: docker    [ OK ]

# hello-worldコンテナを起動
$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
...

うまく動作しているようです。

 

dockerグループへの追加とIPアドレス帯変更

以下の記事を参考に、引き続き作業を行います。
Docker Desktopを使わずにWindowsでDocker | IIJ Engineers Blog

  • dockerグループへの追加
    • sudo usermod -aG docker (ユーザ名)
  • Docker bridge networkのIPアドレス帯変更
    • /etc/docker/daemon.json を作成
    • sudo service docker restart

 
なお、Dockerの自動起動については、後ほど /usr/libexec/wsl-systemd による systemd での自動起動により対応します。そのため、ここでは設定しません。

 

WSL2上にGithub環境の構築

以下を参考に、WSL2にGithub環境を構築します。
WSL2(Ubuntu)でGitHubを使用する - Qiita

 

Gitの設定

WSL2では、まだGitの設定を行っていないため、グローバル設定から行います。

$ git config --global user.name <ユーザ名>
$ git config --global user.email <メアド>
$ git config --global pull.rebase false

 

Github用のSSH鍵を生成

Githubの公式ドキュメントを読みながら、SSH鍵を生成します。
Generating a new SSH key and adding it to the ssh-agent - GitHub Docs

なお、 ssh-keygen する時の t オプション、以前は rsa と書かれていましたが、現在は ed25519 になっています。

$ ssh-keygen -t ed25519 -f ~/.ssh/id_github_ed25519

Generating public/private ed25519 key pair.
Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_github_ed25519
Your public key has been saved in /home/user/.ssh/id_github_ed25519.pub

 

鍵をkeychainで管理

ssh-agent でも管理できますが、準備が大変そうでした。
WSL2のUbuntuでkeychain経由でssh-agentを使う

そこで、上記の記事を参考に、 keychain を使って管理することにしました。

 
aptでkeychainをインストールします。

$ sudo apt install keychain
[sudo] <user> のパスワード:
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています... 完了
状態情報を読み取っています... 完了
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
  libfreetype6
これを削除するには 'sudo apt autoremove' を利用してください。
提案パッケージ:
  ssh-askpass
以下のパッケージが新たにインストールされます:
  keychain
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 0 個。
39.0 kB のアーカイブを取得する必要があります。
この操作後に追加で 86.0 kB のディスク容量が消費されます。
取得:1 http://archive.ubuntu.com/ubuntu jammy/universe amd64 keychain all 2.8.5-2 [39.0 kB]
39.0 kB を 1秒 で取得しました (30.9 kB/s)
以前に未選択のパッケージ keychain を選択しています。
(データベースを読み込んでいます ... 現在 34382 個のファイルとディレクトリがインストールされています。)
.../keychain_2.8.5-2_all.deb を展開する準備をしています ...
keychain (2.8.5-2) を展開しています...
keychain (2.8.5-2) を設定しています ...
man-db (2.10.2-1) のトリガを処理しています ...
...

 
keychainに秘密鍵を登録します。

$ keychain -q --nogui $HOME/.ssh/id_github_ed25519

(何も結果が表示されない)

 
実行後、 $HOME/.keychain/ にファイルが作成されています。

$ ls $HOME/.keychain/
<実際のホスト名>-csh  <実際のホスト名>-fish  <実際のホスト名>-sh

 
使用中のシェルによりkeychainのファイルが異なるため、WSL2の現在のシェルを確認します。 bash のようでした。

$ echo $SHELL
/bin/bash

 
そこで、 ~/.bashrc の末尾に以下を追記します。

# keychain
source $HOME/.keychain/<実際のホスト名>-sh

 

GithubSSH用の公開鍵を登録

clip.exeのエイリアスとして pbcopy を追加

GithubSSH用の公開鍵を登録するには、手動で鍵ファイルを開いて中身をコピーすることもできます。

ただ、コピーミスがこわいので、クリップボード経由でコピーすることにします。

WSL2において、 pbcopy のようなクリップボードを利用できるコマンドを調べたところ、WSL2では clip.exe が使えるようでした。
Windows (WSL2) で Mac の pbcopy / pbpaste のようなクリップボード利用を再現する方法

 
そこで、 ~/.bashrc の末尾にエイリアスを追加し、 clip.exepbcopy として使えるよう設定します。

# pbcopy alias
alias pbcopy='clip.exe'

 
.bashrc を更新したので、再読込します。

$ source ~/.bashrc

 

SSH用の公開鍵をクリップボードにコピー

先ほど生成したSSH用の公開鍵 id_github_ed25519.pubクリップボードにコピーし、Githubの該当ページにコピペできるようにします。

$ pbcopy < ~/.ssh/id_github_ed25519.pub

 

GithubSSH用の公開鍵を登録

https://github.com/settings/keys にてSSH鍵として先ほどの公開鍵を登録します。

 

接続確認

Githubの公式ドキュメントに従い、接続確認を行います。
SSH 接続をテストする - GitHub Docs

$ ssh -T git@github.com
The authenticity of host 'github.com (***.***.***.***' can't be established.
ED25519 key fingerprint is ***
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
Hi thinkAmi! You've successfully authenticated, but GitHub does not provide shell access.

接続は成功したようです。

 

ssh config を作成

GithubSSH接続する時の手間を減らすため、Githubへの接続設定を ~/.ssh/config に追加します。
GitHub 接続時の ~/.ssh/config の書き方

Host github.com
    IdentityFile ~/.ssh/id_github_ed25519
    User git
    IdentitiesOnly yes

 

プライベートリポジトリでcloneやpushをテスト

ここまででGithubとの疎通確認はできているものの、git clone や git push を試してみます。

今回は、README.md のある private リポジトリを作成して、

  • git clone
  • git push

ができることを確認できればOKです。

 

Djangoアプリのリポジトリを git clone

今回は ~/dev/projects/ 以下に git cloneして開発することとします。
https://github.com/thinkAmi/dj_ringo_tabetter

 

WSL2にHeroku環境をセットアップ

現在のアプリはHerokuで動作しているため、WSL2にHeroku環境をセットアップします。

Heroku CLIのインストール

Herokuの公式ドキュメントに従い、 Standalone版をインストールします。
The Heroku CLI | Heroku Dev Center

ちなみに、Standalone版の場合、Heroku CLIの自動アップデートも付属しているようです。

$ curl https://cli-assets.heroku.com/install.sh | sh

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1894  100  1894    0     0   5979      0 --:--:-- --:--:-- --:--:--  5993
This script requires superuser access.
You will be prompted for your password by sudo.
[sudo] <user> のパスワード:
Installing CLI from https://cli-assets.heroku.com/heroku-linux-x64.tar.xz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 27.2M  100 27.2M    0     0  2693k      0  0:00:10  0:00:10 --:--:-- 2201k
v14.19.0
heroku installed to /usr/local/bin/heroku
 ›   Warning: Our terms of service have changed: https://dashboard.heroku.com/terms-of-service
heroku/7.63.0 wsl-x64 node-v14.19.0

 
インストールできているか確認をします。

$ heroku --version
heroku/7.63.0 wsl-x64 node-v14.19.0

 

Heroku CLIで、Herokuにログイン

heroku login コマンドでHerokuにログインします。

手元ではブラウザが開かなかったため、表示されていたURLをブラウザで開いてログインしました。

$ heroku login

heroku: Press any key to open up the browser to login or q to exit:
Opening browser to https://cli-auth.heroku.com/auth/cli/browser/***  # これ

 
Heroku CLIでの準備は完了です。

 

Jetbrains Gatewayまわりのセットアップ

今回はJetBrains Gatewayを使って、WSL2上のPyCharmに接続し、WSL2上でDjangoアプリの開発ができるようにします。

 

Windows上にJetBrains Gatewayをセットアップ

まずは、JetBrains GatewayWindowsにインストールすることにします。

ただ、JetBrains GatewayはJetBrains Toolboxには表示されませんでした。

そこで、以下からダウンロード・インストールします。
JetBrains Gateway - JetBrains IDE 向けリモート開発

インストールオプションは Add "bin" folder to PATH のみチェックを入れます。

PCの再起動が求められるので、再起動します。

 
PCの再起動後、WSL2のUbuntu 22.04.1 LTS を起動します。

 

WSL2で sshd が起動するよう設定

Windows上のJetBrains GatewayからWSL2に接続するときには、SSH接続が使われます。

そこで、WSL2で sshd が起動するよう設定を行います。

 

sshdを起動するために、WSL2上でホスト鍵を生成

WSL2上で sshd 向けのホスト鍵を生成するため、以下のコマンドを実行します。実行後、複数のホスト鍵が生成されます。

$ sudo ssh-keygen -A

[sudo] <user> のパスワード:
ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519

 

SSHでパスワード認証を許可する

続いて、WindowsからWSL2へSSH接続する時の認証まわりを設定します。

今回は開発環境ということもあり、Windowsからの接続はSSH鍵認証ではなく、パスワード認証にします。

設定ファイルを開きます。

$ sudo vi /etc/ssh/sshd_config

PasswordAuthentication 設定を yes に変更します。

# PasswordAuthentication no
PasswordAuthentication yes

 

WSL2にてsshdを起動

準備ができたため、WSL2にて sshd を起動します。

$ sudo service ssh start
 * Starting OpenBSD Secure Shell server sshd   [ OK ]

 

/usr/libexec/wsl-systemd を使った systemdによる自動起動設定

現時点では、WSL2の起動後に手動で

などのサービスを起動する必要があります。

ただ、WSL2上での開発で使うサービスは自動で起動してほしいです。

 
調べてみたところ、WSL2上のUbuntu22.04では /usr/libexec/wsl-systemd というシェルスクリプトが導入されたため、systemdによる自動起動ができそうです。

 
上記の記事に従い、設定を行います。

WSL2のUbuntu上で、 /etc/wsl.conf を開きます(なければ新規作成します)。

$ sudo vi /etc/wsl.conf

 
以下を記載します。

[boot]
command=/usr/libexec/wsl-systemd

 
WSL2を再起動するため、Windows Terminalで wsl --shutdown 後、スタートから Ubuntu 22.04.1 LTS をクリックして起動します。

 
状況を確認すると、systemdで各サービスが起動していました。

# systemdがPID 1 で動作していること
$ pidof systemd
1

# 色々起動していること
$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.2  0.0 166200 11116 ?        Ss   10:58   0:00 /lib/systemd/systemd --unit=multi-user.target
root          42  0.0  0.0  31472 11684 ?        S<s  10:58   0:00 /lib/systemd/systemd-journald
root          69  0.1  0.0  22480  6248 ?        Ss   10:58   0:00 /lib/systemd/systemd-udevd
systemd+     100  0.0  0.0  16112  7916 ?        Ss   10:58   0:00 /lib/systemd/systemd-networkd
message+     101  0.0  0.0   8760  4676 ?        Ss   10:58   0:00 @dbus-daemon --system --address=systemd: --nofork --n
root         104  0.1  0.0  33828 19032 ?        Ss   10:58   0:00 /usr/bin/python3 /usr/bin/networkd-dispatcher --run-s
root         105  0.0  0.0 234480  6656 ?        Ssl  10:58   0:00 /usr/libexec/polkitd --no-debug
syslog       106  0.0  0.0 222396  5220 ?        Ssl  10:58   0:00 /usr/sbin/rsyslogd -n -iNONE
root         107  0.1  0.1 1688080 32596 ?       Ssl  10:58   0:00 /usr/lib/snapd/snapd
root         108  0.0  0.0  15016  7148 ?        Ss   10:58   0:00 /lib/systemd/systemd-logind
root         162  0.0  0.0 316924 11756 ?        Ssl  10:58   0:00 /usr/sbin/ModemManager
systemd+     164  0.0  0.0  25256 12564 ?        Ss   10:58   0:00 /lib/systemd/systemd-resolved
root         297  0.0  0.0   7936  1264 ?        Ss   10:58   0:00 /usr/sbin/cron -f -P
root         306  0.0  0.0 110784 21672 ?        Ssl  10:58   0:00 /usr/bin/python3 /usr/share/unattended-upgrades/unatt
root         307  0.2  0.2 1725736 56456 ?       Ssl  10:58   0:00 /usr/bin/containerd
root         328  0.0  0.0   7216  1116 tty1     Ss+  10:58   0:00 /sbin/agetty -o -p -- \u --noclear --keep-baud consol
root         330  0.0  0.0   7216  1092 ?        Ss   10:58   0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
root         331  0.0  0.0  15416  8904 ?        Ss   10:58   0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startu
root         368  0.1  0.3 1679532 84656 ?       Ssl  10:58   0:00 /usr/bin/dockerd -H ...


# 念のためDockerの状況を確認
$ service docker status
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2022-09-11 10:59:00 JST; 1min 54s ago
...

 

JetBrains Gatewayを設定

JetBrains Gatewayを起動します。

ただ、まだJetBrains Gatewayの設定が終わっていないため、まずは設定から行います。

 
JetBrains Gatewayを起動後、左ペインの SSH を選択し、中央ペインの New Connection をクリックします。

右側にある歯車マークをクリックし、SSH Configurations を開きます。

左上の + をクリックし、中央ペインに以下を入力します。

項目
Host localhost
Username WSL2のuser名
Password WSL2のパスワード
Port 22
Save password チェックする
Parse config file ~/.ssh/config チェックする

 
この状態で Test Connection ボタンをクリックし、 Successfully connected! と表示されれば接続できています。

なお、初回接続はフィンガープリントの確認があります。

すべての入力が終わったら、 OK ボタンをクリックし、SSH Configurations 画面を閉じます。

Connect to SSH 画面に戻るため、Connection を SSH Configurations 画面で作成したものに変更し、 Check connection and Continue ボタンをクリックします。

Choose IDE and Project 画面が表示されるので、以下を選択します。

項目
IDE version PyCharm
Project directory 先ほど git clone したディレクトリ (/home//dev/projects/dj_ringo_tabetter)

 
入力が終わったら、 Download IDE and Connect ボタンをクリックします。

  • JetBrains Client
  • IDE background on remote

のダウンロードが始まります。

 
ダウンロードが終わると、JetBrains Gatewayに指定したプロジェクトが表示されます。

 

JetBrains Gatewayの動作確認

JetBrains Gatewayのリンクをクリックします。

初回なので「JetBrains Team Tools User Agreement」が表示されます。 acceptします。

その後、PyCharmが起動し、git cloneしたプロジェクトを開くことができました*1

 

WSL2上のPython環境構築

ここまでで JetBrains Gateway + PyCharmによる開発ができるようになりました。

次は、WSL2上で既存のDjangoアプリを開発するために必要な環境設定を行います。

 

anyenvのセットアップ

今後WSL2上で色々開発するかもしれないため、今回は anyenv 経由で pyenv の環境を構築します。
anyenv/anyenv: All in one for **env

READMEや以下の記事を参考に、WSL2上でセットアップします。
anyenvの環境構築 - Qiita

# git cloneする
$ git clone https://github.com/anyenv/anyenv ~/.anyenv
Cloning into '/home/<user>/.anyenv'...
remote: Enumerating objects: 505, done.
remote: Counting objects: 100% (109/109), done.
remote: Compressing objects: 100% (66/66), done.
remote: Total 505 (delta 54), reused 77 (delta 36), pack-reused 396
Receiving objects: 100% (505/505), 89.55 KiB | 274.00 KiB/s, done.
Resolving deltas: 100% (234/234), done.


# .bashrc に設定追加
$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bashrc


# initする
$ ~/.anyenv/bin/anyenv init
# Load anyenv automatically by adding
# the following to ~/.bash_profile:

eval "$(anyenv init -)"


# 画面に表示された内容を、 .bashrc に追加
$ echo 'eval "$(anyenv init -)"' >> ~/.bashrc


# シェルを再起動
$ exec $SHELL -l
ANYENV_DEFINITION_ROOT(/home/<user>/.config/anyenv/anyenv-install) doesn't exist. You can initialize it by:
> anyenv install --init


# メッセージの通りに実行し、マニフェストディレクトリを作成する
$ anyenv install --init
Manifest directory doesn't exist: /home/<user>/.config/anyenv/anyenv-install
Do you want to checkout https://github.com/anyenv/anyenv-install.git? [y/N]: y
Cloning https://github.com/anyenv/anyenv-install.git master to /home/<user>/.config/anyenv/anyenv-install...
Cloning into '/home/<user>/.config/anyenv/anyenv-install'...
remote: Enumerating objects: 71, done.
remote: Counting objects: 100% (14/14), done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 71 (delta 4), reused 3 (delta 1), pack-reused 57
Receiving objects: 100% (71/71), 13.15 KiB | 708.00 KiB/s, done.
Resolving deltas: 100% (11/11), done.

Completed!


# anyenvがインストールされているか確認
$ anyenv --version
anyenv 1.1.5-1-g5c58783

 

anyenv-updateのセットアップ

また、 ***env をバージョンアップしやすくするため、 anyenv-update をREADMEに従いセットアップします。
znz/anyenv-update: anyenv plugin that provides anyenv update command to update all **env and all plugins

# ディレクトリ追加
$ mkdir -p $(anyenv root)/plugins


# git clone
$ git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
Cloning into '/home/<user>/.anyenv/plugins/anyenv-update'...
remote: Enumerating objects: 87, done.
remote: Total 87 (delta 0), reused 0 (delta 0), pack-reused 87
Receiving objects: 100% (87/87), 13.33 KiB | 975.00 KiB/s, done.
Resolving deltas: 100% (33/33), done.

 

pyenv のインストール

WSL2上ではPythonの複数バージョンを扱うかもしれないため、anyenv経由で pyenv をインストールします。

# インストール
$ anyenv install pyenv
/tmp/pyenv.20220910214424.10064 ~
Cloning https://github.com/pyenv/pyenv.git master to pyenv...
Cloning into 'pyenv'...
remote: Enumerating objects: 21895, done.
remote: Counting objects: 100% (653/653), done.
remote: Compressing objects: 100% (235/235), done.
remote: Total 21895 (delta 460), reused 554 (delta 389), pack-reused 21242
Receiving objects: 100% (21895/21895), 4.41 MiB | 1.12 MiB/s, done.
Resolving deltas: 100% (14803/14803), done.
~

Install pyenv succeeded!
Please reload your profile (exec $SHELL -l) or open a new session.


# リロード
$ exec $SHELL -l

 

Pythonをビルドするためのツールをインストール

以下のドキュメントに従い、必要なツール類をインストールします。
Ubuntu環境のPython: Python環境構築ガイド - python.jp

なお、今回は tkinter は使わないため、 tk-dev はインストールしません。

$ sudo apt install build-essential libbz2-dev libdb-dev \
  libreadline-dev libffi-dev libgdbm-dev liblzma-dev \
  libncursesw5-dev libsqlite3-dev libssl-dev \
  zlib1g-dev uuid-dev

パッケージリストを読み込んでいます... 完了
...
No VM guests are running outdated hypervisor (qemu) binaries on this host.

 

Djangoアプリのruntime.txt と同じPythonをインストール

Djangoアプリの runtime.txt ファイルを見ると、Python 3.8.6 で動いています。

そのため、pyenvで3.8.6をインストールします。

$ pyenv install 3.8.6
Downloading Python-3.8.6.tar.xz...
...
WARNING: The Python tkinter extension was not compiled and GUI subsystem has been detected. Missing the Tk toolkit?
Installed Python-3.8.6 to /home/<user>/.anyenv/envs/pyenv/versions/3.8.6

 
リポジトリのあるディレクトリではPython3.8.6で動作するように設定します。

# 設定
$ pyenv local 3.8.6

# 確認
$ python --version
Python 3.8.6

 

必要なパッケージのインストール

pg_config のインストール

リポジトリには requirements.txt があります。ただ、 pip install -r requirements.txt すると、 pg_config でエラーになります。

Error: pg_config executable not found.

pg_config is required to build psycopg2 from source.  Please add the directory
containing pg_config to the $PATH or specify the full executable path with the
option:

    python setup.py build_ext --pg-config /path/to/pg_config build ...

or with the pg_config option in 'setup.cfg'.

If you prefer to avoid building psycopg2 from source, please install the PyPI
'psycopg2-binary' package instead.

 
そこで、以下を参考に状況を確認します。
psycopg2 インストールエラー - Qiita

$ pg_config --version
コマンド 'pg_config' が見つかりません。次の方法でインストールできます:
sudo apt install libpq-dev          # version 14.5-0ubuntu0.22.04.1, or
sudo apt install postgresql-common  # version 238

 
エラーメッセージに従い、 libpq-dev をインストールします。

$ sudo apt install libpq-dev

No VM guests are running outdated hypervisor (qemu) binaries on this host.

 
再度確認します。

$ pg_config --version
PostgreSQL 14.5 (Ubuntu 14.5-0ubuntu0.22.04.1)

インストールされたようです。

 

pip install

改めて pip install すると、エラーが出ています。

$ pip install -r requirements.txt

...
ERROR: After October 2020 you may experience errors when installing or updating packages. This is because pip will change the way that it resolves dependency conflicts.

We recommend you use --use-feature=2020-resolver to test your packages with the new resolver before it becomes the default.

faker 2.0.1 requires text-unidecode==1.2, but you'll have text-unidecode 1.3 which is incompatible.

 
インストール状況を確認してみると、インストール自体はできているようです。

$ pip list

Package            Version
------------------ -----------
atomicwrites       1.3.0
...
Faker              2.0.1  # インストールできている
...

 
ためしにオプションを付けて実行してみると、エラーメッセージが変わりました。

$ pip install -r requirements.txt --use-feature=2020-resolver

ERROR: Cannot install text-unidecode==1.3 and faker 2.0.1 because these package versions have conflicting dependencies.

The conflict is caused by:
    The user requested text-unidecode==1.3
    faker 2.0.1 depends on text-unidecode==1.2

To fix this you could try to:
1. loosen the range of package versions you've specified
2. remove package versions to allow pip attempt to solve the dependency conflict

ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/user_guide/#fixing-conflicting-dependencies

 
調べてみると、以前開発していた時と現在では、pipの依存性チェッカーが異なっているようです。

 
現時点ではFakerがエラーになっていますが、

  • Fakerはテストで使うライブラリなので、プロダクションコード自体には影響しない
  • 開発する中で、各パッケージはバージョンアップする予定

なことから、現時点ではひとまずこのままで進めます。

 

Docker Compose でPostgreSQLを構築

PythonはWSL2上に直接インストールしました。

一方、アプリのデータベース PostgreSQL はWSL2上に直接インストールせず、プロジェクトごとに別のPostgreSQLを参照したいです。

そこで、WSL2上に、Docker ComposeでPostgreSQLを立てることにします。

 
なお、WSL2上でDockerをインストールした際にDocker Composeもインストール済なため、 docker compose コマンドは使える状態になっています。

$ docker compose version
Docker Compose version v2.6.0

 

WSL2上のDockerでPostgreSQLを構築

Docker Composeを設定

WSL2上のDockerでPostgreSQLを構築するため、今回は Docker Compose を利用します。

docker-compose.yml ファイルを作成します。

version: '3'
services:
  db:
    image: postgres:10.6
    # portsの指定、quoteなしだと、Unquoted port mapping not recommended と出る
    ports:
      - "19876:5432"
    environment:
      POSTGRES_USER: ringo
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: ringo_tabetter_py
      # データベースファイルの置き場所をサブディレクトリにする
      PGDATA: /var/lib/postgresql/data/pgdata
    # データベースファイルの格納先を名前付きボリュームにする
    volumes:
      - ringo_data:/var/lib/postgresql/data

# 名前付きボリュームの設定
volumes:
  ringo_data: {}

 

Docker ComposeでPostgreSQLを起動

docker compose up -dPostgreSQLを起動します。

$ docker compose up -d
[+] Running 15/15
 ⠿ db Pulled                                                                                                      15.6s
...
[+] Running 3/3
 ⠿ Network dj_ringo_tabetter_default      Created                                                                  0.0s
 ⠿ Volume "dj_ringo_tabetter_ringo_data"  Created                                                                  0.0s
 ⠿ Container dj_ringo_tabetter-db-1       Started                                                                  0.6s

 

ローカルで dj_ringo_tabetter を起動

ここまででDjangoアプリを起動するための準備が一通りできたので、WSL2上でアプリを起動してみます。

 

エラー「A 'django.template.backends.django.DjangoTemplates' instance must be configured in TEMPLATES in order to use the admin application」への対応

PyCharmで dj_ringo_tabetter を起動したところ、以下のエラーになり起動しませんでした。

/home/<user>/dev/projects/dj_ringo_tabetter/env/bin/python /home/<user>/dev/projects/dj_ringo_tabetter/manage.py runserver 8000 
Watching for file changes with StatReloader
Performing system checks...

Exception in thread django-main-thread:
Traceback (most recent call last):
  File "/home/<user>/.anyenv/envs/pyenv/versions/3.8.6/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/home/<user>/.anyenv/envs/pyenv/versions/3.8.6/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/<user>/dev/projects/dj_ringo_tabetter/env/lib/python3.8/site-packages/django/utils/autoreload.py", line 54, in wrapper
    fn(*args, **kwargs)
  File "/home/<user>/dev/projects/dj_ringo_tabetter/env/lib/python3.8/site-packages/django/core/management/commands/runserver.py", line 117, in inner_run
    self.check(display_num_errors=True)
  File "/home/<user>/dev/projects/dj_ringo_tabetter/env/lib/python3.8/site-packages/django/core/management/base.py", line 436, in check
    raise SystemCheckError(msg)
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:

ERRORS:
?: (admin.E403) A 'django.template.backends.django.DjangoTemplates' instance must be configured in TEMPLATES in order to use the admin application.

System check identified 1 issue (0 silenced).

 
似たような事例がないかを調べたところ、JetBrainsのyoutrackに記載がありました。
"DjangoTemplates instance must be configured in TEMPLATES in order to use the admin application" trying to run the server from Django project template with Jinja2 : PY-39296

 
手元のソースコードを見たところ、youtrackの記載同様、 TEMPLATES の設定に django.template.backends.django.DjangoTemplates が足りていないようでした。
https://github.com/thinkAmi/dj_ringo_tabetter/blob/97a9f5be02/dj_ringo_tabetter/settings.py#L67

以前、Django自体のJinja2 Engineを使うようにしてdjango-jinjaを削除をしましたが、その対応不足だったのかもしれません。
https://github.com/thinkAmi/dj_ringo_tabetter/commit/97a9f5be0239745882a3e932b31a232a705f3ee0

 
そこで、youtrackの記載通り、 django.template.backends.django.DjangoTemplates の設定も追加しました。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
            'environment': 'dj_ringo_tabetter.jinja2.environment',
        }
    },

    # 以下を追加
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [os.path.join(BASE_DIR, "templates")],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

 

Djangoアプリの動作確認

改めて dj_ringo_tabetter アプリを起動してみます。

マイグレーションを実行していないためその旨のメッセージは出ていますが、エラーになることなく起動したようです。

/home/<user>/dev/projects/dj_ringo_tabetter/env/bin/python /home/<user>/dev/projects/dj_ringo_tabetter/manage.py runserver 8000 
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions, tweets.
Run 'python manage.py migrate' to apply them.
September 11, 2022 - 11:42:31
Django version 2.2.16, using settings 'dj_ringo_tabetter.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

 
WindowsChromeで確認します。

PyCharmのログにリンクとして表示されている http://127.0.0.1:8000/ 自体、もしくは、PyCharmのリンクを踏むと表示される

Remote host wants to open the following URL: http://127.0.0.1:55659/

を開くと、画面が表示されました。

データベースが空っぽなので何も表示されませんが、ガワは表示できているようです。

 

Heroku Postgresからデータベースの内容をリストア

上記で見た通り、現在のローカルのPostgreSQLは空っぽです。

開発用にデータをイチから作成しても良いのですが、今回はHeroku PostgresにあるデータをローカルのPostgreSQLにリストアして使うことにします。
Importing and Exporting Heroku Postgres Databases | Heroku Dev Center

 

Heroku Postgresのバックアップ

WSL2上のHeroku CLIを使い、バックアップの作成とダウンロードを行います。

なお、ディレクトリは dj_ringo_tabetterリポジトリルートとします。

# 現在のディレクトリを確認
$ pwd
/home/<user>/dev/projects/dj_ringo_tabetter


# バックアップを取得
$ heroku pg:backups:capture --app ringo-tabetter

Starting backup of thinking-carefully-5183... done

Use Ctrl-C at any time to stop monitoring progress; the backup will continue running.
Use heroku pg:backups:info to check progress.
Stop a running backup with heroku pg:backups:cancel.

Backing up DATABASE to b005... done

 

バックアップファイルのダウンロード

上記で作成したバックアップファイルをダウンロードします。

# バックアップをダウンロード
$ heroku pg:backups:download --app ringo-tabetter
Getting backup from ⬢ ringo-tabetter... done, #5


# バックアップファイルの存在を確認
$ ls latest.dump
latest.dump

 

ローカルのPostgreSQLにリストア

pg_restoreのインストール

ローカルのPostgreSQLにリストアしようと pg_restore のバージョンを確認したところ、WSL2上にはインストールされていないようでした。

$ pg_restore --version
コマンド 'pg_restore' が見つかりません。次の方法でインストールできます:
sudo apt install postgresql-client-common

 
そこで、画面の表示に従い、 pg_restore をインストールします。

$ sudo apt install postgresql-client-common

...
以下のパッケージが新たにインストールされます:
  postgresql-client-common
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 0 個。
...
No VM guests are running outdated hypervisor (qemu) binaries on this host.

 
再度 pg_restore コマンドを実行するとエラーメッセージが変わっていました。

$ pg_restore --version
Warning: No existing cluster is suitable as a default target. Please see man pg_wrapper(1) how to specify one.
Error: You must install at least one postgresql-client-<version> package

 
大丈夫かなと思い、pg_restore を実行したところ、以下のエラーになりました。

$ pg_restore --verbose --clean --no-acl --no-owner -h localhost -p 19876 -U ringo -d ringo_tabetter_py latest.dump
...
 Error: You must install at least one postgresql-client-<version> package.

 
似た事例がないかを調べたところ、postgresql-client のインストールも必要そうなことがわかりました。
ruby on rails 3 - Get Error: You must install at least one postgresql-client- package when deploy to heroku - Stack Overflow

そこで、追加でインストールを行います。

$ sudo apt install postgresql-client

状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
  postgresql-client-14
提案パッケージ:
  postgresql-14 postgresql-doc-14
以下のパッケージが新たにインストールされます:
  postgresql-client postgresql-client-14
アップグレード: 0 個、新規インストール: 2 個、削除: 0 個、保留: 0 個。
1,222 kB のアーカイブを取得する必要があります。
この操作後に追加で 3,963 kB のディスク容量が消費されます。
続行しますか? [Y/n]
...
No VM guests are running outdated hypervisor (qemu) binaries on this host.

 
インストール後にバージョンを確認すると、今度は表示されました。良さそうです。

$ pg_restore --version
pg_restore (PostgreSQL) 14.5 (Ubuntu 14.5-0ubuntu0.22.04.1)

 

pg_restoreの実行

pg_restore コマンドを使用し、ローカルのPostgreSQLにリストアします。

$ pg_restore --verbose --clean --no-acl --no-owner -h localhost -p 19876 -U ringo -d ringo_tabetter_py latest.dump
pg_restore: connecting to database for restore
Password: <PostgreSQLのパスワードを入力:今回は `postgres` >
...
pg_restore: warning: errors ignored on restore: 76

 
以上でPostgreSQLのデータも準備できました。

 

動作確認

再度、http://127.0.0.1:8000/ にアクセスすると、円グラフが表示されました。

 
続いて、 http://127.0.0.1:8000/hc/total-by-month にアクセスすると折れ線グラフが表示されました。

 
WSL2上のDjangoアプリが正常に動作していることを確認できました。

 

Djangoアプリにマイグレーションを適用

起動した時のログをみると

You have 7 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth.
Run 'python manage.py migrate' to apply them.

とありました。

そこで、マイグレーションを適用します。

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, tweets
Running migrations:
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK

適用に成功したようです。

 

Herokuアプリを更新する

remoteにHerokuを追加

Herokuにアプリをデプロイできるか、公式ドキュメントに従い確認します。
Deploying with Git | Heroku Dev Center

 
remote を追加します。

$ heroku git:remote -a ringo-tabetter
set git remote heroku to https://git.heroku.com/ringo-tabetter.git

 

push時のエラーに対応

Herokuにpushしたところ、エラーになりました。 pip install のときに見たエラーです。

$ git push heroku master
...
remote:        ERROR: Cannot install faker==2.0.1 and text-unidecode==1.3 because these package versions have conflicting dependencies.
remote:        
remote:        The conflict is caused by:
remote:            The user requested text-unidecode==1.3
remote:            faker 2.0.1 depends on text-unidecode==1.2
remote:        
remote:        To fix this you could try to:
remote:        1. loosen the range of package versions you've specified
remote:        2. remove package versions to allow pip attempt to solve the dependency conflict

 
そこで、Fakerのバージョンを上げ、Fakerが依存している text-unidecode のバージョン 1.3 で動くようにしてみます。

どのFakerのバージョンが良いかを見たところ、 8.1.0 ならば text-unidecode1.3 に依存してそうでした。

 
そこで、 requirements.txt を修正し、 Faker8.1.0 にした上でインストールしました。

$ pip install -r requirements.txt 

 
また、

$ pip install -r requirements.txt --use-feature=2020-resolver

としてもエラーは出なくなりました。

 

あらためて push

良さそうでしたので、改めてpushします。

$ git push heroku master
Enumerating objects: 11, done.
...
remote: Verifying deploy.... done.
To https://git.heroku.com/ringo-tabetter.git
   9169f8e..8b855c4  master -> master

 
デプロイに成功しました。

また、 https://ringo-tabetter.herokuapp.com/hc/total にアクセスし、動作していることが確認できました。

 
しばらく放置していたアプリなため、いろいろ修正しなければいけないことはあるものの、ひとまず開発環境の構築が完了しました。

 

ソースコード

Githubに上げました。
https://github.com/thinkAmi/dj_ringo_tabetter

*1:画像はこの記事の最後まで到達した時のJetBrains Gateway + PyCharmの状態です。DBの中身も見えるため、PyCharm単体での開発と変わりありません