AzureのWebAppでJupyter環境をデプロイして苦戦したので細かくまとめて共有する

2021/06/12に公開

はじめに

今回は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つがエラーの原因になりうまく作成できませんでした

  1. dockerfileのCOPYコマンドでローカルのファイルコピーするとき、dockerfileよりも上の階層は参照できない

Build時にそこでエラーになりました。解決方法は以下にあります。(今回は使うことはありませんが)

https://qiita.com/TKR/items/ac29ee783bc4684d0612

-fオプションで対応できるそうです。

  1. ディレクトリがない
    今回JupyterNotebookの設定を./setiings/jupyter_notebook_config.pyで行っていますが、そこではカレントディレクトリを./home/jovyan/dataにする設定が入っています。/dataがdocker-compose.ymlを読み込むタイミングで作成されるようになっています。
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を使いたいとなると、基本的には公式のリファレンスを参考にやっていきますが、わかりづらいような気がするのは私だけではないと思ったので記事にまとめてみました。

参考記事

GitHubで編集を提案

Discussion