WSL 2 環境で miniforge を使って JupyterLab を簡単に起動できるようにした話

# はじめに

「WSL 2 で JupyterLab を使いたいと思ったのですが、Anaconda の商用利用有償化の話など色々あって結構手順が長くなったので、今回備忘録がてら記事にしてみました。」という書き出しで miniconda を使ったセットアップ記事を書いたのですが、その後 miniforge という、デフォルトで conda-forge がメインのリポジトリとして指定されていて、OSS コミュニティーが主体となってメンテしているパッケージの存在を知り、改めてそちらを試してみようと思った次第です。

といっても拍子抜けするほどに作業手順の大半が miniconda と変わらず、結果として記事内容はほぼコピペです。折角なので前回引っかかってアドホックに解決を試みた部分についても作業の中に組み込んだりして必死で新規記事感を出しています。

https://qiita.com/ShuntaIto/items/bb6793c0bbf2ed4e53de

現時点で私の方ではまだ情報を整理しきれておらず、どうすれば適切なのか判断がついていません。

例えば「miniconda + conda-forge」であってもインストール直後は Anaconda のリポジトリを参照している以上商用利用の件に抵触している気配がしなくもないですが、その運用なら問題ないと Reddit で Anaconda CEO が発言した[^1][^2]という情報があります。miniforge なら問題ない気もしますが、その辺りはっきりした公式アナウンスが欲しいところです。

# 環境構築

## 環境

- Windows: Windows 10 20H2 (19042.746)
- WSL 2: Ubuntu 20.04 LTS

## ビルド準備

やっておかないとたまに依存解決時にビルドが走るパッケージをインストールするときにこけます。

```
sudo apt install build-essential
```

## miniforge インストール

miniforge をインストールします。

https://github.com/conda-forge/miniforge

```bash
cd ~
wget https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh
chmod +x Miniforge3-Linux-x86_64.sh
sh Miniforge3-Linux-x86_64.sh
```

Anaconda や Miniconda とはインストーラーの様子もほんの少し違っています。

インストールの最後に

```
Do you wish the installer to initialize Miniforge3
by running conda init? [yes|no]
```
と聞かれますが、yes としておきます。

パスを通します。 (厳密には既に .bashrc に追加されているので再読み込みします)

```
source ~/.bashrc
```

終わったらインストーラーは削除しておきます。

```
rm Miniforge3-Linux-x86_64.sh
```

## チャンネル

```conda config --get channels --system```で設定された channel (リポジトリ) を確認してみました。

```
--add channels 'conda-forge'   # lowest priority
```

きちんと conda-forge になっていますね。

```conda list```でインストール直後の base 環境のパッケージ一覧を確認してみました。全て conda-forge 由来となっているので、ひとまず目的は果たせています。

<details><summary>miniforge の base 環境</summary><div>

```
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                 conda_forge    conda-forge
_openmp_mutex             4.5                       1_gnu    conda-forge
brotlipy                  0.7.0           py38h8df0ef7_1001    conda-forge
bzip2                     1.0.8                h7f98852_4    conda-forge
ca-certificates           2020.12.5            ha878542_0    conda-forge
certifi                   2020.12.5        py38h578d9bd_0    conda-forge
cffi                      1.14.4           py38ha65f79e_1    conda-forge
chardet                   4.0.0            py38h578d9bd_0    conda-forge
conda                     4.9.2            py38h578d9bd_0    conda-forge
conda-package-handling    1.7.2            py38h8df0ef7_0    conda-forge
cryptography              3.3.1            py38h2b97feb_0    conda-forge
idna                      2.10               pyh9f0ad1d_0    conda-forge
ld_impl_linux-64          2.35.1               hea4e1c9_1    conda-forge
libffi                    3.3                  h58526e2_2    conda-forge
libgcc-ng                 9.3.0               h5dbcf3e_17    conda-forge
libgomp                   9.3.0               h5dbcf3e_17    conda-forge
libstdcxx-ng              9.3.0               h2ae2ef3_17    conda-forge
ncurses                   6.2                  h58526e2_4    conda-forge
openssl                   1.1.1i               h7f98852_0    conda-forge
pip                       20.3.3             pyhd8ed1ab_0    conda-forge
pycosat                   0.6.3           py38h8df0ef7_1005    conda-forge
pycparser                 2.20               pyh9f0ad1d_2    conda-forge
pyopenssl                 20.0.1             pyhd8ed1ab_0    conda-forge
pysocks                   1.7.1            py38h924ce5b_2    conda-forge
python                    3.8.6           hffdb5ce_4_cpython    conda-forge
python_abi                3.8                      1_cp38    conda-forge
readline                  8.0                  he28a2e2_2    conda-forge
requests                  2.25.1             pyhd3deb0d_0    conda-forge
ruamel_yaml               0.15.80         py38h8df0ef7_1003    conda-forge
setuptools                49.6.0           py38h924ce5b_2    conda-forge
six                       1.15.0             pyh9f0ad1d_0    conda-forge
sqlite                    3.34.0               h74cdb3f_0    conda-forge
tk                        8.6.10               h21135ba_1    conda-forge
tqdm                      4.55.0             pyhd8ed1ab_0    conda-forge
urllib3                   1.26.2             pyhd8ed1ab_0    conda-forge
wheel                     0.36.2             pyhd3deb0d_0    conda-forge
xz                        5.2.5                h516909a_1    conda-forge
yaml                      0.2.5                h516909a_0    conda-forge
zlib                      1.2.11            h516909a_1010    conda-forge
```
</div></details>
## JupyterLab インストール

実は一度 JupyterLab のセットアップ後に extension を入れる過程でやらかして JupyterLab を壊してしまい、しかも修理ができずに詰みまして、base 環境は手つかずで置いておくべきと悟ったので、別環境を作ってそこに JupyterLab を入れる手順で進めていきます。

```
conda create -n jupyterlab python=3.8
conda activate jupyterlab
```


一通り標準的なパッケージをインストールします。

```
conda install jupyter jupyterlab pandas scikit-learn matplotlib git
```

試しに起動してみます。

```
~/miniforge3/envs/jupyterlab/bin/jupyter lab --no-browser
```

miniforge をデフォルトのままインストールした場合上記のようにユーザーのホームディレクトリにインストールされます。もしデフォルトとは異なるパスを指定した場合は、自分の環境に応じて置換して実行します。


表示された URL にアクセスして JupyterLab が動けばとりあえず OK です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359618/eabb7ac4-52d8-a033-1ca0-f4972560f06a.png)


## JupyterLab 設定

デフォルトのワーキングディレクトリを変更します。（必要ない人は飛ばして大丈夫です）

設定ファイルを生成します。

```
/home/<your-name>/miniforge3/bin/jupyter lab --generate-config
```

このコマンドにより

```
/home/<your-name>/.jupyter/jupyter_lab_config.py
```
に config ファイルが生成されます。

vim 等で編集していきます。本質的に Python のファイルなので、インデント等には注意しましょう。

下記文字列を検索し、コメントアウトした上でデフォルトにしたいディレクトリを指定します。

```
c.ServerApp.root_dir = '/mnt/c/workspace'
```

## コマンド化

WSL 2 では systemd が動いていないので、JupyterLab をサービス化して自動起動しておいていつでもブラウザでアクセス、とはいきません。（サーバーならともかく WSL 2 はローカル実行するものなので、その性質上あまりすべきではない気もします）

代わりに WSL 2 でコマンド一発で JupyterLab を起動できるようにしておきます。

```alias```を使って長ったらしい jupyterlab 仮想環境に切り替えて JupyterLab を起動するコマンドを jupyterlab というコマンドに丸め込みます。

.bashrc には .bash_aliases というエイリアス記述用のファイルが存在する場合にそれを読み込むコマンドが予め記述されている[^2]そうです。

ということで、まず .bash_aliases を作成します。

```
vim ~/.bash_aliases
```

コマンド定義を記述します。

```
alias jupyterlab="conda activate jupyterlab;~/miniforge3/envs/jupyterlab/bin/jupyter lab --no-browser"
```

最後に .bashrc を再読み込みします。

```
source ~/.bashrc
```

## extensions の準備

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359618/8ccc696d-e8b4-64a1-e3c0-e1b90d6bb744.png)

こんな機能が増えてたんですね。Enable にして利用してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359618/b8c6f278-2916-2ddb-f102-03a6db84c45c.png)

node を入れろと出てきました。ということで node 環境もセットアップします。nvm を使用しています。

```
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash
```

https://github.com/nvm-sh/nvm

インストールが完了した例によって PATH を通すために .bashrc を再読み込みします。

```
source ~/.bashrc
```

node の最新版を入れます。

```
nvm install latest
```

やった後に思いましたが、nvm で node のバージョンを切り替えると extension によって問題が出そうな気がします。node の開発もやっているので今回はこのようにしましたがめんどくさい気持ちがあります。どうするのが正解なんだろうか……。

# 終わりに

```
jupyterlab
```

WSL 2 のコンソールで miniforge を使って上記コマンド一発で JupyterLab が立ち上がるようになりました。作業手順として特別なことは何一つなく miniconda と比べてリポジトリ設定が不要な分むしろ楽なくらいでした。

miniforge は mamba や PyPy がデフォルトで統合されているバージョンもあるようですのでこだわると色々できそうな気がします。




[^1]: https://qiita.com/tfukumori/items/f8fc2c53077b234384fc
[^2]: https://www.reddit.com/r/Python/comments/iqsk3y/anaconda_is_not_free_for_commercial_use_anymore/gjb056j?utm_source=share&utm_medium=web2x&context=3