vscode devcontainer + dockerで作成するお手軽Jupyter環境

# 概要
毎回、新しいプロジェクトが始まると、環境構築のたびにパッケージの管理とかがめんどくさかった
→とりあえず、超シンプルにこれで良いやろ、というjupyter環境を作ってこの1年くらい利用して、結構よかった。
→テンプレレポにまとめた。

https://github.com/omusoba-code/jupyter-template


※本記事はwindowsを想定していますが、macでも行けるはずです。

# 誰もが通る環境構築の悩み...
### まずは、ローカルpython直入れしてみて...
- 〇 たくさんリファレンスがあってやりやすい
- × パッケージの依存関係コンフリクトなどで仮想環境が壊れるとゲームオーバー
### 慣れてくると、pyenvやcondaなどの仮想環境を使ってみて...
- 〇 仮想環境が壊れても作り直せる
- × 結局複数の仮想環境を変更するのが面倒。間違えてrootにパッケージ入れて萎える
### もう疲れてくると、コンテナでjupyter環境構築してみて...
- 〇 仮想環境いつでも飛ばせる。プロジェクト毎にDockerfileを通じて紐づけできる
- × CLIを触るのが面倒。あと、いちいちjupyterのリンク押して飛ぶのも面倒。そもそもjupyterじゃなくてVSCodeで開発したい
# 紹介する方法の楽なところ
### IDEとしてvscodeを使える←結構最大のメリット
  - わざわざjupyterのブラウザ画面を触る必要がない
  - vscodeの豊富な拡張機能を使える
### GUIで操作できる
  - remoteのコンテナ接続はポチポチで完了
### テンプレ化して使いまわせる
  - 一つの.devcontainerフォルダを使いまわすだけ
  - もしカスタマイズしたければ、Dockerfileを通じて自由にカスタムできる

# 前準備（もう完了している人はスキップでOK）
## 1.vscodeとdockerをインストール
  
  https://code.visualstudio.com/download
  
  https://docs.docker.com/get-started/get-docker/
  
## 2.vscodeの拡張機能をインストール
### 導入する拡張機能
  https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers
  
  https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker
  
  https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter
  
  https://marketplace.visualstudio.com/items?itemName=ms-python.python

  https://marketplace.visualstudio.com/items?itemName=ms-python.vscode-pylance

### 導入方法や他にあった方が良い拡張機能等はこちら参照
  
  https://itokoba.com/archives/9850

# 方法

## 1. vscodeでプロジェクトフォルダを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324271/b6402d81-ea0b-a8d6-9c6f-568aeba1d644.png)

## 2. ".devcontainer"というフォルダを作り、その中に以下の4つのファイルを作る。
※この[repo](https://github.com/omusoba-code/jupyter-template)をcloneする形でもOK
最終的なディレクトリ構造は下記のようになる
```text
project_root
└ー.devcontainer
    ├－devcontainer.json
    ├－docker-compose.yml
    ├－Dockerfile
    └ーrequirements.txt
```
### 1. "devcontainer.json"
```json:devcontainer.json
{
	"dockerComposeFile": "./docker-compose.yml", // docker-compose file
	"service": "jupyter", // service name in docker-compose file
	"workspaceFolder": "/home/jovyan/work", // root directory of the project
	"forwardPorts": [8888],
	"remoteUser": "jovyan", // default user, as the same in the Dockerfile
	"customizations": {
		"vscode": {
			"settings": {
				"python.defaultInterpreterPath": "/opt/conda/bin/python" // python interpreter path
			},
			"extensions": [ // vscode extensions
				"ms-python.python",
				"ms-python.vscode-pylance",
				"ms-toolsai.jupyter"
			]
		}
	}
}
```
これが、devcontainerの設定ファイルになります。

### 2. "docker-compose.yml"
```yaml:docker-compose.yml
version: '3'
services:
  jupyter:
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - '8888:8888'
    volumes:
      - ../:/home/jovyan/work/
```
複数コンテナを管理するファイルです。たまに、コンテナを複数作りたくなった時には、ここに設定を記述します。


### 3. "Dockerfile"

```Dockerfile:Dockerfile
FROM quay.io/jupyter/scipy-notebook:latest

# Move requiremnts.txt to work directory
COPY --chown=${NB_UID}:${NB_GID} ./requirements.txt ${HOME}/work/requirements.txt

# Install requirements
RUN pip install -r ${HOME}/work/requirements.txt && \
    pip cache purge

RUN fix-permissions "${CONDA_DIR}" && \
    fix-permissions "/home/${NB_USER}"


WORKDIR "${HOME}"
```
元々、jupyterが公式で公開しているイメージを基本的に利用。今回は`scipy-notebook:latest`をベースとして使用しているが、torch版とかもあるので、必要に応じて一行目を書きかえる。

https://jupyter-docker-stacks.readthedocs.io/en/latest/using/selecting.html

※稀にpip conda conflictが起こるときがあるが、その時はDockerfileに condaでインストールすべきパッケージを `RUN conda install hogehoge`で記述してください。
 ### 4. "requirements.txt"
```python:requirements.txt
numpy==2.2.1
Bottleneck==1.4.2
pandas==2.2.3
pydantic==2.10.4
fastapi==0.115.6
scikit-learn==1.6.0
```
追加したいパッケージがあれば基本ここに加筆していく

## コンテナで開く
左下のマークをクリックして、「コンテナーで再度開く」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324271/06e132bf-5258-f4db-cddb-496bc85a098e.png)

もしくは、何かファイルを変更した場合にはVSCodeでコマンドパレットを開いて（`ctrl+shift+P`）、`rebuild and reopen in container`を選択すれば、コンテナリビルドが行われます。

### 3. 後は適当に.ipynbファイルを作って動かせるはず！
※もしjupyter動かすときに「カーネルの選択」ダイアログが表示された場合
「Python環境」→「base(Python hogehoge)」をクリックしていけば使えるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324271/66e18422-54ed-24a9-8b79-9d972623e8f9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324271/73ad1a86-fd6d-d020-cd26-195b21aa9035.png)

# おわりに
後で確認したら結構もうすでに記事があった...
が、なぜか、jupyter-stacksをベースにpipでパッケージを導入できるようにした形でDockerfileを構築している記事は見かけなかったので、そういうニーズがある（入れたいパッケージが結構変わるけど、そのたびにコンテナビルドに時間がかかるのは嫌な）人にはおすすめです！