AzureのWebAppでJupyter環境をデプロイして苦戦したので細かくまとめて共有する
はじめに
今回はAzureのWebApp (WebService, Web App Container, Webアプリともいう?)を利用してDockerで作成したJupyterNotebook (JupyterLab)環境をデプロイしましたので、細かく載せたいと思います。
公式のリファレンスはありますが、思ったよりもわかりづらいので要点を説明していきます。
また、この方法はDockerのimageから環境を作成するのであれば参考になるかと思います。
ちなみに前々回の記事ではRailsのアプリをACI(Azure Container Instance)を利用してデプロイしていますのでそちらも参考にしていただけると良いかと思います。
前回に比べて、今回はDockerの知識が試されるなと思いました。それなので色々苦戦しましたがなんとかできるようになりました。
自作のDockerfileでimageを作成して、WebAppを利用してデプロイし、URLでアクセスしてJupyterNotebookが利用できることを目的に今回はハンズオン形式でまとめていきます。
開発環境
- Windows 10
- VsCode (powershell)
- Docker desktop
今回はこちらのリポジトリを利用します。
このリポジトリは自然言語処理に特化したリポジトリに対して、Dockerfileの一部を修正を行ったものになります。
準備
リポジトリを適当な場所にクローンします。
git clone https://github.com/jinwatanabe/Azure_webapp_deploy.git
そのあとpowershellでクローンしたディレクトリに入ります。
cd Azure_webapp_deploy
また、Azureのアカウントがない場合は作成してAzure portalの画面を開ける状態にします。
そして、検索ウィンドウからサブスクリプションを選択して、適当なサブスクリプションを作成してください。
サブスクリプションは請求がくるときの単位になります。
ここの操作は難しくはありませんので、わからない場合は検索してみるとすぐにわかるかと思います。
そのあと、検索ウィンドウからリソース グループを選択して、適当なリソースグループを作成します。
今回はこのように作成しました。

リソースグループはjupyterdeployと名付けて、リージョンは東日本にしています。
リソースグループをつくることで、これから作成するWebAppやContainerRegistryなどをまとめて管理できます。大本のリソースグループを削除することで子のリソースもまとめて削除することもできます。
それでは、準備ができたので早速デプロイをしてきます。
デプロイの手順
1. Docker imageをContainer Registryに登録する
まずは、Dockerfileをimageにして、Container Registryに保存します。のちのデプロイでこのイメージを利用してコンテナを立ち上げます。
まずは、Azure portalの検索ウィンドウからContainer Registryと検索します。
以下のように入力します。

- リソースグループは先ほど作成したもの (jupyterdeploy)
- レジストリ名は任意 (ここではjupyterreg)
- 場所は東日本
その後、確認および作成を押して、作成を押すとデプロイが始まります。
終了したらリソース→アクセスキーの順でクリックして、管理者ユーザーを有効にします。

ここでimageを保存するのに必要になる情報があります。
- ログインサーバー
- ユーザー名
- password
あとで利用しますので、迷ったらこの画面に戻り確認してください。
それでは、Vscodeに戻って作業をします。
まずはDockerfileから`imageを作成します。
# docker build -t {ログインサーバー名/イメージ名} (Dockerfileの場所)
$ docker build -t jupyterreg.azurecr.io/jupyter .
すると、イメージが作成されます。
# 作成したイメージの確認
$ docker images
# 以下が表示される
REPOSITORY TAG IMAGE ID CREATED SIZE
jupreg.azurecr.io/jupyter latest 46dcd99122dc 2 hours ago 5.92GB
ちなみにDockerfileの場所がカレントディレクトリにない場合は、絶対パスを入れます。(ここで1度詰まりました)
# testにDockerfileがある場合
$ docker build -t jupyterreg.azurecr.io/jupyter "C:\Users\jin\Desktop\workspace\Azure_webapp_deploy\test
イメージが作成出来たらイメージでコンテナが起動できるか確認をします。
$ docker run -d -p 8888:8888 --name jupyter_test jupyterreg.azurecr.io/jupyter start-notebook.sh
# コンテナが正しく起動しているか確認
$ docker ps
以下のようになれば成功
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
4ea984170724 jupreg.azurecr.io/jupyter "tini -g -- start-no…" 8 seconds ago Up 6 seconds 0.0.0.0:8888->8888/tcp, :::8888->8888/tcp jupyter_test
表示がなかった場合は失敗しています。
# 失敗を確認する
$ docker ps -a
# STATUSがEXITになっているならDockerfileに不具合があるので確かめる必要がある (余談に遭遇したものはまとめています)
次に実際にコンテナを立ち上げて、JupyterNotebook (JpyterLab)にアクセスしてみます。
$ docker run -d -p 8888:8888 --name jupyter_test jupyterreg.azurecr.io/jupyter start-notebook.sh
imageからコンテナを起動する場合はdocker runコマンドを利用します。大まかに説明します。
- -d : バックグラウンドで起動
- -p 8080:8080 : コンテナの8080とポート8080を接続
- --name jupyter_test : コンテナの名前
- jupyterreg.azurecr.io/jupyter : イメージ名
- start-notebook.sh : Dockerfileで利用されているイメージの起動スクリプト
そのあとブラウザでlocalhost:8080にアクセスします。

するとJupyterNotebookの画面が表示されパスワードを求められるのでpasswordと入力します。

無事、イメージからJupyterNotebookを利用できました。
localhost:8888/labにアクセスすることで、JupyterLabも利用できます。
確認できたのでdocker runで立ち上げたコンテナを落とします。
# docker stop {コンテナ名}
$ docker stop jupyter_test
# 利用していないコンテナを削除するなら以下のコマンド
$ docker container prune
pruneは未使用のオブジェクトを削除するため注意が必要です。消してもよいのか確認してください。
pruneについて知りたい方はこちら
を参考にしてみてください。
次にイメージを先ほど作成したContainerRegistryに保存します。
まずはContainerRegistryにログインします。
# docker login {ログインサーバー}
$ docker login jupyterreg.azurecr.io
# usernameを聞かれるのでContainerRegistryのユーザー名を入力
$ username: jupyterreg
# パスワードを聞かれるのでContainerRegistryのpasswordを入力数る(ただし表示はされない)
$ password:
# Login Succeededとでれば成功
そして作成したDocker imageをpushします。
# docker push {イメージ名}
$ docker push jupyterreg.azurecr.io/jupyter
Azure portalのリソースグループから作成したContainerRegistryをえらび(ここではjupyterreg)、サービスの中のレポジトリを確認すると、pushしたイメージを確認することができます。
余談 : Docker build時のエラーについて
ここで、私が今回のデプロイで遭遇したエラーについてまとめておきます。うまくいかないときには参考になるかもしれないです。
docker imageを作成する際に以下の2つがエラーの原因になりうまく作成できませんでした
- dockerfileのCOPYコマンドでローカルのファイルコピーするとき、dockerfileよりも上の階層は参照できない
Build時にそこでエラーになりました。解決方法は以下にあります。(今回は使うことはありませんが)
-fオプションで対応できるそうです。
- ディレクトリがない
今回JupyterNotebookの設定を./setiings/jupyter_notebook_config.pyで行っていますが、そこではカレントディレクトリを./home/jovyan/dataにする設定が入っています。/dataがdocker-compose.ymlを読み込むタイミングで作成されるようになっています。
volumes:
- ./experiments:/home/jovyan/data/
しかし、今回はDockerfileのみでコンテナを立てるため(runで起動するため)、起動時には/dataのディレクトリがなくjupyter_notebook_config.pyでエラーになり、コンテナが落ちていました。このようなこともあるので注意が必要です。
※これはメモなのでハンズオンには直接関係ありません。この記事を参考に別のDockerfileで試す際に参考になるかもしれません。
2. WebAppにデプロイをする
ここからはAzure portalを操作していきます。
まず検索ウィンドウからWebServiceを選択、+作成を押します。
そして以下のように設定します。

- サブスクリプション : 今回作成したもの
- リソースグループ : 今回作成リソースグループ (ここではjupyterdeploy)
- 公開 : DOcker コンテナー
- 地域 : Japan East
- SKUとサイズ : Basic B1 (初期設定は価格の高いサーバーになっているので検証用に変更します)
次: Dockerを押してコンテナの設定をする

- イメージリソース : Azure Container Registry
- レジストリ : 今回作成したContainerRegistryのレジストリ名 (ここではjupyterreg)
- イメージ : ContainreRegistryにpushしたイメージ名 (ここではjupyter、jupyterreg.azurecr.io/jupyteの/以下に該当する)
- スタートアップコマンド :
start-notebook.sh(Dockerfileで利用されているimageの起動コマンド)
設定が終わったら、確認および作成→作成でデプロイが開始します。
終了したら、リソースへ移動します。

するとこのような画面になります。URLというリンクがあるのでこれにアクセスするとJupyterNotebookにアクセスが可能です。
しかし、注意が必要でデプロイは終了してもimageのpullやdocker runコマンドの実行はこれからになります。
URLにアクセスして、502エラーがでて失敗したと思わないようにしてください。 (私はそれで悩みました)
コンテナの起動は設定項目のコンテナーの設定(クラシック)をクリックして、ログをクリックすることで確認できます。(かなり時間がかかります)
docker run ...... start-notebook.shのコマンドを起動していたらコンテナが立ち上がっているかと思いますのでURLにアクセスしてみてください。エラーがでればイメージがおかしい、またはスタートアップコマンドを疑います。

このようになっていればコンテナが起動しています。
先ほどのURLでアクセスしてみます。
JupyterNotebookの画面が開き、パスワードを求められるのでpasswordと入力します。

無事デプロイができました。コードを実際に動かしてみます。

問題なさそうです。
ついでにJupyterLabも確認します。
JupyterLabはURL/labでアクセスできます。

できました。ついでに今回私がいれていた機械学習パイプラインツールElyraも実行してみたところ動いていました。

後片付け
最後に以下を削除(停止?)することで課金を止めることができます。
- WebService (WebApp)
- ContainerRegistry
- リソースグループ
- (使わないのならば) サブスクリプション
課題
今後の課題として以下の3点があります。
- docker-compose.ymlを利用したデプロイもWebAppではできるので挑戦したい(こっちのほうが楽そう?)
- ストレージを用意して共有したい (ローカルのファイルをWebApp上のJupyterにマウントしたい)
- Azure CLIコマンドでデプロイしたい
こちらは一つずつ取り組んでいく予定ですので投稿をお待ちください。
おわりに
今回はAzure WebAppを利用したJupyter環境のデプロイについて説明しました。
imageが重いためデプロイの検証にかなり時間がかかり、記事作成も深夜になってしましました(現在AM4:00)
Azureを使いたいとなると、基本的には公式のリファレンスを参考にやっていきますが、わかりづらいような気がするのは私だけではないと思ったので記事にまとめてみました。
Discussion