Jupyter Labからサービスアカウント不要でBigQueryを利用！Minikubeでローカル環境構築


#はじめに
ローカルPC上のMinikube/DockerにてJupyterLab環境を構築し、そこからBigQueryをエンドユーザで認証して、データを取得する手順を紹介します。

#目的

- BigQueryをJupyterLabから使いたい
- GCPのサービスアカウントがなく、エンドユーザーとして認証しBigQueryを利用したい
- Dockerで環境構築したいが、Docker Desktop有償化のため、別の方法で構築したい

無償の環境を構築し、BigQueryのクエリ結果をローカルPC上のJupyterLabで分析することができます。(BigQueryの料金はもちろんかかります。DockerDesktopも個人利用なら無償のようです)

GCPのサービスアカウントも不要で、pandas等のpython知識も基本的に不要です。
JupyterLab上にクエリ実行履歴やメモが残せるので、GCPのBigQueryコンソール画面から普段クエリ実行している方におすすめです。

手元のローカル環境を汚したくないためDockerを利用します。すでにDockerDesktop等でDocker環境構築済みならStep2から、JupyterLabを直接インストールしている方はStep３のみご参考ください。

#筆者環境
- OS: macOS Big Sur バージョン 11.6.1
- Shell: zsh

#全体の流れ
1. Virtual Machine(仮想OS)としてVirtualBox上にMinikube/Docker環境を構築　
※DockerDesktopインストール済みなら不要
2. Docker-ComposeでJupyterLab環境を構築
3. JupyuterLabでBigQueryへ接続しSQLクエリ実行
4. 環境の停止/再起動

#Step1. Minikube/Docker環境構築

1.minikube、Virtualbox、Docker、Docker-ComposeをBrewでインストールします。

```shell
$ brew install minikube virtualbox docker docker-compose
```

※Brewがインストールされていなければ、下記スクリプトにてインストールします。

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

参照: https://brew.sh/index_ja


2.minikubeを実行。Virutal BoxをVirtualMachine(仮想OS)環境として指定します。

```shell
$ minikube start --container-runtime="docker" --driver=virtualbox
```

3.ローカルPCのシェル環境に応じた、環境変数の設定用のコマンドを生成します。

```shell
$ minikube docker-env
```

実行結果:

```shell
> minikube docker-env
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/yuji.yamamoto/.minikube/certs"
export MINIKUBE_ACTIVE_DOCKERD="minikube"

# To point your shell to minikube's docker-daemon, run:
# eval $(minikube -p minikube docker-env)
```

4.上記3.の結果生成されたコマンド(最下部のeval ...)を実行。筆者のzshの場合はこちらを実行します。

```shell
$ eval $(minikube -p minikube docker-env)
```

以降は、ローカルのシェルから直接docker/docker-composeコマンドが使えるようになります。

#Step2. Docker-ComposeでJupyterLab環境構築
JupyterLab環境を構築するdocker-composeファイルとその他関連ファイルを、ローカルPC上の任意のディレクトリに配置し、そこでdocker-compose buildでJupyter環境構築します。

配置したディレクトリ構造と下記の通りです。
notebooksディレクトリは作成しておきますが、内部のipynbファイルはサンプルのnotebookファイルですので、現時点では不要です。

```shell
> tree
.
├── Dockerfile-jupyter
├── docker-compose.yml
├── notebooks
    └── BigQuery_template.ipynb
```

docker-compose.ymlの定義で、`Dockerfile-jupyter`ファイルでJupyterLab環境を構築します。作成したnotebookファイルはDocker停止後や環境削除後も残しておきたいので、volumesでローカルのディレクトリにマウント(自動コピー)するように設定しておきます。
同様にJupyterLabの環境設定も残すようにvolumesで設定しておきます。

今回は個人利用のためｍJupyterLabはトークン(パスワード)なしでもログインできるように、`NotebookApp.token=''`と空欄にして起動するようにしていますが、必要に応じて設定ください。

```yaml:docker-compose.yml
version: '1'
services:
  jupyterlab:
    container_name: jupyterlab
    build: 
      context: .
      dockerfile: ./Dockerfile-jupyter
    environment:
        TZ: "Asia/Tokyo"
    volumes:
      - "./notebooks:/home/work/notebooks"
      - ".jupyter:/root/.jupyter"
    restart: always
    ports:
      - "8080:8080"
    tty: true
    command: jupyter lab --ip=0.0.0.0 --port=8080 --allow-root --no-browser --NotebookApp.token=''

```

python3.6をベースに、基本的なライブラリ、Python関連のライブラリ、JupyterLabのエクステンションをインストールします。BigQueryへの接続/連携のために、`google-cloud-bigquery[pandas]`、`pydata-google-auth`を利用します。Jupyter上でBigQueryのクエリをそのまま扱うための`jupyter-extra-magics`を利用します。

```Dockerfile:Dockerfile-jupyter
FROM python:3.6

RUN apt-get update -y \
    && apt-get upgrade -y

# install base library
RUN curl -sL https://deb.nodesource.com/setup_12.x |bash - \
    && apt-get install -y --no-install-recommends \
    wget \
    git \
    vim \
    curl \
    make \
    cmake \
    nodejs \
    && apt-get autoremove -y \
    && apt-get clean \
    && rm -rf \
        /var/lib/apt/lists/* \
        /var/cache/apt/* \
        /usr/local/src/* \
        /tmp/*

# install python library
RUN pip3 install --upgrade pip && \
    pip3 install --no-cache-dir \
      google-cloud-bigquery[pandas] \
      pydata-google-auth \
      jupyter-extra-magics \
      tqdm \
      pyarrow \
      sqlalchemy \
      ipython-sql \
      numpy \
      pandas \
      matplotlib \
      seaborn \ 
    && rm -rf ~/.cache/pip

# install jupyterlab & extentions
RUN pip3 install --upgrade --no-cache-dir \
    'jupyterlab~=3.0' \
    jupyterlab_code_formatter \
    yapf \
    && rm -rf ~/.cache/pip \
    && jupyter labextension install \
      @hokyjack/jupyterlab-monokai-plus \
      @ryantam626/jupyterlab_code_formatter \
      @jupyterlab/toc \
      @lckr/jupyterlab_variableinspector@3.0.7 \
    && jupyter serverextension enable --py jupyterlab_code_formatter

WORKDIR /home/work/
```

1.上記ファイルを準備し任意のディレクトリに配置後、同ディレクトリにてdocker-composeコマンドでコンテナをbuildします。

```shell
$ docker-compose build
```

2.問題なくbuildできたら、起動します。

```shell
$ docker-compose up
```


3.JupterLabが起動しましたので、アクセスします。上記Step1.3の実行結果に記載されているホストのアドレスとポート8080にアクセスします。筆者の場合下記になります。

http://192.168.99.100:8080

無事にアクセスできましたら、JupyterLab環境の構築は完了です！

#Step3. JupyuterLabでBigQueryへ接続しSQLクエリ実行
Jupyter上で、GCPのBigQueryへ接続し、SQLクエリを実行します。

1.JupyterLabにてPython3のNotebookを作成します。筆者は`BigQuery_template`というファイル名で作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549/984d4775-1c70-f765-cd2d-5b49721d7269.png)


2.一つ目のセルでBigqueryへのログインし認証コードを取得します。下記のコードをセルで実行すると、GCPへのログイン画面が表示されるので、BigQueryの権限を持つユーザを選択してログインしてください。表示されたコードをコピーして、セル実行結果の`Enter the authorization code: `に入れます。

```python
import pydata_google_auth
credentials = pydata_google_auth.get_user_credentials(
    ['https://www.googleapis.com/auth/bigquery'],
)
```


3.２つ目のセルで、2.で取得したcredentialを、Jupyter上でBigQueryクエリそのままで実行できるMagicコマンドのcredentialに設定します。

```python
from google.cloud.bigquery import magics
magics.context.credentials = credentials 
```

4.3つ目のセルで下記を実行することで、BigQueryのmagicコマンドが有効になります。

```python
%reload_ext google.cloud.bigquery
```
ここまで、BigQueryのクエリを実行するための準備が整いました。

5.4つ目のセルで、BigQueryのmagicコマンドを実行できます。GCPのプロジェクト名を引数にいれ、下部にクエリを記述し実行すると、結果がpandasのdataframe形式で表示されます。
筆者のプロジェクト名は仮に`sample_project`とし、publicのデータセットのクエリを実行するとなると下記のようになります。

```sql
%%bigquery --project sample_project --use_rest_api

SELECT name, SUM(number) as count
FROM `bigquery-public-data.usa_names.usa_1910_current`
GROUP BY name
ORDER BY count DESC
LIMIT 3
```

実際のJupyterLabの画面イメージはこちらです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549/572a25dd-c91d-6fc9-5bb1-aaad70c229e3.png)


Magicコマンドではパラメータを渡せたり、クエリ実行結果を別の変数へ出力できたりします。仕様詳細はこちらをご参照ください。
https://googleapis.dev/python/bigquery/latest/magics.html


#Step4. 環境の停止と再起動

コンテナの削除or停止どちかについては、コンテナの作り直しをしないのであれば停止で良いです。その後改めて起動するときは、Step2.2と同様に起動します。

```shell
docker-compose stop
```

minikube/VirtualBoxのVirtualMachinを停止するには、こちら。
ローカルPC自体の再起動など改めて起動するときはStep1.2と1.4を実行します。

```shell
minikube stop
```

VirtualBoxのVM環境の挙動がおかしいor壊れた場合は、根本から削除します。再度構築をするときはStep1.2から実行します。

```shell
minikube delete
```


#参考
- MinikubeでDocker環境構築する際に参考にしました。

https://zenn.dev/sasasin/articles/43a1b79a4cfdc1

- Docker Desｋtopの有償化の公式ドキュメントはこちらです。

https://www.docker.com/pricing/faq

- BigQueryのMagicコマンドの仕様はこちらです

https://googleapis.dev/python/bigquery/latest/magics.html