マネージドノートブックにOpenCV環境を構築する

## はじめに
こんにちは、京セラコミュニケーションシステム 森田 (@kccs_kai-morita）です。

私は普段GoogleCloudのVertex AI Workbench マネージドノートブックを用いてデータサイエンス業務を行っています。このサービスは、JupyterLab環境を提供しており、データの探索や分析、モデリングなどのデータサイエンス作業に適しています。さらに、マシンのスペックを自由に変更できる上、GPUを使用することも可能です。もちろん、Google CloudのAI環境にも簡単にアクセスできるので、非常に便利に使っています。

しかし、最近、画像データを扱うことがあり、OpenCVが動作しない問題に直面しました。その理由は、OpenCVはlibgl1-mesa-devのインストールが必要なのですが、マネージドノートブックではapt-getを使用することができないからです（厳密には使用可能ですが、パスワードが求められます）。

そこで、OpenCVが動作する方法について調査しましたので、その結果をまとめたいと思います。

## 環境構築手順
マネージドノートブックでは、ノートブックファイルをカーネルとして実行しています。デフォルトではPythonをベースとしてTensorflowやPytorchなどのパッケージとツールが含まれている環境が用意されています。さらに、任意のコンテナをノートブックファイルを実行するカーネルとして追加することが可能です。これを利用することより、OpenCV環境を用意します。

手順としては下記の通りです。必要に応じてAPIを有効化してください。
1. Dockerfileを作成する
2. コンテナイメージをビルドし、Airtifact RegistryにPushする
3. マネージドノートブック新規インスタンス作成時に、イメージを指定する

## Dockerfileを作成する
まずOpenCVに必要な依存関係を明記したDockerfileを作成します。ベースイメージ部分は[こちら](https://cloud.google.com/deep-learning-containers/docs/choosing-container?hl=ja#deciding)から選択してください。とくに機械学習フレームワークが不要であれば基本のPython CPU環境で問題ないです。

Google Cloudコンソール画面右上からCloud Shellにアクセスします。もちろん独自のdockerがビルドできかつGoogle Cloudにアクセスできる環境でも可能ですが、Cloud Shellを使う方が手っ取り早いです。マネージドノートブック内でもOK。
Dockerfileを作成しviコマンド等で編集します。

```shell:Cloud Shell 
$ mkdir Dockerfile
$ vi Dockerfile
```

Dockerfileは以下の通りです。

```shell:Dockerfile
# ベースイメージとしてDeep Learning Containers から Python(CPU)を使用
FROM gcr.io/deeplearning-platform-release/base-cpu:latest

# 準備
RUN apt-get update && apt-get upgrade -y

# OpenCVの依存関係をインストール
RUN pip install opencv-python
RUN apt-get install -y libgl1-mesa-dev
```

## コンテナイメージをビルドし、Airtifact RegistryにPushする
公式ドキュメントにはContainer RegistryにPushとありますが、Container Registryは非推奨です。

https://qiita.com/kccs_daisuke-ishizeki/items/774e54aac5a581ab9109

次のコマンドを使用して、コンテナイメージをビルドし、Airtifact RegistryにPushします。

```shell:Cloud Shell 
export PROJECT=$(gcloud config list project --format "value(core.project)")
docker build . -f Dockerfile -t "asia-northeast1-docker.pkg.dev/${PROJECT}/notebook-container/opencv-container:latest"
docker push asia-northeast1-docker.pkg.dev/${PROJECT}/notebook-container/opencv-container:latest
```
2行目でビルドし、3行目でPushをしていますが、レポジトリ名およびコンテナ名は任意の名前で問題ありません。
全体でおよそ20分かかりました。

## マネージドノートブック新規インスタンス作成時に、イメージを指定する
Vertex Workbenchにて新規マネージドノートブックを作成します。Google Cloudコンソール画面にて「Vertex AI」>「ワークベンチ」と選択し、画面上部から「新しいノートブック作成」を選択します。

「カスタムDockerイメージを指定する」のチェックボックスをオンにし、作成したAirtifact Registry上のコンテナイメージを選択します。

![ノートブック環境設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780555/f917d55c-fcc1-91eb-28c6-df488c71d128.png)<font color="DarkGray">_マネージドノートブック環境設定画面_</font>

残りの設定を任意で入力し、「作成」を押下すると作成したコンテナイメージをベースとしたカーネルが追加され、ノートブック一覧画面でも確認できます。

![ノートブック一覧画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780555/3fefc1a7-e8ed-e7c9-d9ad-860d39d00c0d.png)<font color="DarkGray">_ノートブック一覧画面_</font>

作成が完了し、起動できる様になるとノートブック画面を開いてみましょう。Activity logがコンテナイメージを読み込み中の表示がしばらく続きますが、読み込み完了のマークが確認できるとOKです。
カーネル一覧から選択するか、新規ノートブックファイル作成時に、読み込んだコンテナイメージを選択すれば、使用できるようになります。

![Activity log完了の表示](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780555/990db090-42d9-0d0d-5df2-3d55c4e55adf.png)<font color="DarkGray">_Activity log完了の表示_</font>

数十分待っても読み込みが完了しない場合は、権限周りに問題があるかも知れません。
ノートブック作成時に指定したアカウントに「Artifact Registry 管理者」の権限を追加するとマネージドノートブックがコンテナイメージを読み込みできるようになるでしょう（それより弱い権限でも可能かもしれません）。

## おわりに
公式サイトや他の記事を参考にあっちこっち飛び回りながらなんとか自作コンテナイメージをベースにすることができました。一番苦労したのは最後の権限周りで、読み込みが終わらないなと思って1時間ほど待っていると、自動シャットダウン機能でいつの間にかマシンが落ちていました。これを2回ほど繰り返してから気づきました。
この記事を書いている最中、Google Cloud Nextが開催されており、Colab Enterpriseというものが発表され現在プレビューで公開されているようです。Google ColabをベースにしているのでVertex Workbenchのようにインスタンス作成不要で、ノートブックファイル単位でマシンのインスタンスを割り当てられます。複数人で同じワークベンチを触るよりは使いやすそうです。またDuet AIによるコード補助機能もあり、少し触ってみましたが少し打ち込んだコードから推測して残りのコードを書いてくれて便利でした。ただ、今回の記事で紹介したような自作のコンテナイメージをベースにする機能は今のところなさそうでした。そのため、OpenCVは使用できないかもしれません。それぞれのサービス使い分けが必要になりそうです。

[^1]: [公式ドキュメント](https://cloud.google.com/vertex-ai/docs/workbench/managed/custom-container?hl=ja)