Azure App Service+Django：クイックスタートやってみた

# はじめに
こんにちは、とあるIT企業の人間です。
「Azureを触ってみたい」&「同じ初心者にとって少しでも救いになれば」と思い、この記事を書きました。

Microsoftのサイトにある[クイックスタート](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django
)がわかりやすかったので、そちらを見ながらこの記事も読んでいただければと思います。
基本的に[クイックスタート](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django)で既に記載済みのものは載せません。また手順名はサイトと合わせて目次化しています。


Djangoの動作確認は、日頃使用しているAnaconda環境を使用しています。ちなみにDjangoもあまり触ったことないですが..


# 目的
- Djangoアプリのデプロイ手順を理解する
- 実行結果をシェアする

# 環境
- macO : Catalina 10.15.6
- conda : 4.9.2
- python : 3.8.5
- django : 3.1.4
- azure-cli : 2.16.0

# （引用）クイックスタート：Azure App Service on Linux で Python アプリを作成する

## 各手順の概要
<dl>
  <dt>1. 初期環境を設定する</dt>
  <dd>Azureへの登録、Azure CLI・Python実行環境の準備します。<strong>（本記事ではAnaconda仮想環境でdjango環境を作成します。）</strong></dd>
<dt>2. サンプルを複製する</dt>
  <dd>Azure App Serviceへデプロイするサンプルの取得します。
　</dd>
<dt>3. サンプルを実行する</dt>
  <dd>サンプルの動作確認を行います。<strong>（本記事ではAnaconda仮想環境で実施しています。）</strong></dd>
<dt>4. サンプルのデプロイ</dt>
  <dd>Azure CLIからAzure App Serviceへデプロイします。 
　</dd>
<dt>5. アプリの参照</dt>
  <dd>デプロイしたアプリのページへアクセスします。
　</dd>
<dt>6. 更新の再デプロイ</dt>
  <dd>アプリ内容を変更した時の反映方法です。<strong>（本記事ではサイトの手順に比べて、アプリの更新内容を少し増やしています。）</strong></dd>
<dt>7. ログのストリーミング</dt>
  <dd>デプロイされたアプリのコンソールログを見ることができます。
　</dd>
<dt>8. Azure アプリの管理</dt>
  <dd>AzureのページでGUIからアプリの存在を確認します。
　</dd>
<dt>9. リソースをクリーンアップする</dt>
  <dd>不要なリソースを削除します。
　</dd>
</dl>



## 1. [初期環境を設定する](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django#set-up-your-initial-environment)

Azureアカウント作成・Azure CLIのインストールは各自作成してください。
Pythonに関して、私の環境ではAnaconda環境をしているので、仮想環境を作成します。以下を実行します。

```
conda create -n django-env
```

<details><summary>実行結果（仮想環境作成）</summary><div>

```
(base) $ conda create -n django-env python=3.8
Collecting package metadata (current_repodata.json): done
Solving environment: done

## Package Plan ##

  environment location: <Anaconda3インストールディレクトリ>/envs/django-env

  added / updated specs:
    - python=3.8


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    ca-certificates-2020.12.8  |       hecd8cb5_0         121 KB
    certifi-2020.12.5          |   py38hecd8cb5_0         141 KB
    libcxx-10.0.0              |                1         760 KB
    libedit-3.1.20191231       |       h1de35cc_1          96 KB
    libffi-3.3                 |       hb1e8313_2          44 KB
    ncurses-6.2                |       h0a44026_1         749 KB
    openssl-1.1.1i             |       h9ed2024_0         2.2 MB
    pip-20.3.1                 |   py38hecd8cb5_0         1.8 MB
    python-3.8.5               |       h26836e1_1        20.6 MB
    readline-8.0               |       h1de35cc_0         326 KB
    setuptools-51.0.0          |   py38hecd8cb5_2         727 KB
    sqlite-3.33.0              |       hffcf06c_0         1.3 MB
    tk-8.6.10                  |       hb0a8c7a_0         3.0 MB
    wheel-0.36.1               |     pyhd3eb1b0_0          32 KB
    xz-5.2.5                   |       h1de35cc_0         240 KB
    ------------------------------------------------------------
                                           Total:        32.0 MB

The following NEW packages will be INSTALLED:

  ca-certificates    pkgs/main/osx-64::ca-certificates-2020.12.8-hecd8cb5_0
  certifi            pkgs/main/osx-64::certifi-2020.12.5-py38hecd8cb5_0
  libcxx             pkgs/main/osx-64::libcxx-10.0.0-1
  libedit            pkgs/main/osx-64::libedit-3.1.20191231-h1de35cc_1
  libffi             pkgs/main/osx-64::libffi-3.3-hb1e8313_2
  ncurses            pkgs/main/osx-64::ncurses-6.2-h0a44026_1
  openssl            pkgs/main/osx-64::openssl-1.1.1i-h9ed2024_0
  pip                pkgs/main/osx-64::pip-20.3.1-py38hecd8cb5_0
  python             pkgs/main/osx-64::python-3.8.5-h26836e1_1
  readline           pkgs/main/osx-64::readline-8.0-h1de35cc_0
  setuptools         pkgs/main/osx-64::setuptools-51.0.0-py38hecd8cb5_2
  sqlite             pkgs/main/osx-64::sqlite-3.33.0-hffcf06c_0
  tk                 pkgs/main/osx-64::tk-8.6.10-hb0a8c7a_0
  wheel              pkgs/main/noarch::wheel-0.36.1-pyhd3eb1b0_0
  xz                 pkgs/main/osx-64::xz-5.2.5-h1de35cc_0
  zlib               pkgs/main/osx-64::zlib-1.2.11-h1de35cc_3


Proceed ([y]/n)? y


Downloading and Extracting Packages
readline-8.0         | 326 KB    | ########################################################### | 100% 
openssl-1.1.1i       | 2.2 MB    | ########################################################### | 100% 
python-3.8.5         | 20.6 MB   | ########################################################### | 100% 
libcxx-10.0.0        | 760 KB    | ########################################################### | 100% 
pip-20.3.1           | 1.8 MB    | ########################################################### | 100% 
libffi-3.3           | 44 KB     | ########################################################### | 100% 
certifi-2020.12.5    | 141 KB    | ########################################################### | 100% 
xz-5.2.5             | 240 KB    | ########################################################### | 100% 
ncurses-6.2          | 749 KB    | ########################################################### | 100% 
setuptools-51.0.0    | 727 KB    | ########################################################### | 100% 
ca-certificates-2020 | 121 KB    | ########################################################### | 100% 
tk-8.6.10            | 3.0 MB    | ########################################################### | 100% 
libedit-3.1.20191231 | 96 KB     | ########################################################### | 100% 
sqlite-3.33.0        | 1.3 MB    | ########################################################### | 100% 
wheel-0.36.1         | 32 KB     | ########################################################### | 100% 
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use
#
#     $ conda activate django-env
#
# To deactivate an active environment, use
#
#     $ conda deactivate

```
</div></details>

作成した仮想環境（以後、django-env環境）に入ります。

```
conda activate django-env
```

Pythonのバージョンを確認しておきます。

```
(django-env) $ python -V
Python 3.8.5
```

django-env環境でdjangoをインストールします。

```
conda install django
```

<details><summary>実行結果（djangoインストール）</summary><div>

```
(django-env) $ conda install django
Collecting package metadata (current_repodata.json): done
Solving environment: done

## Package Plan ##

  environment location: <Anaconda3インストールディレクトリ>/opt/anaconda3/envs/django-env

  added / updated specs:
    - django


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    asgiref-3.3.1              |     pyhd3eb1b0_0          22 KB
    django-3.1.4               |     pyhd3eb1b0_0         3.0 MB
    krb5-1.17.1                |       hddcf347_0         1.1 MB
    libpq-12.2                 |       h051b688_0         2.0 MB
    psycopg2-2.8.5             |   py38hddc9c9b_0         144 KB
    pytz-2020.4                |     pyhd3eb1b0_0         180 KB
    sqlparse-0.4.1             |             py_0          35 KB
    ------------------------------------------------------------
                                           Total:         6.5 MB

The following NEW packages will be INSTALLED:

  asgiref            pkgs/main/noarch::asgiref-3.3.1-pyhd3eb1b0_0
  django             pkgs/main/noarch::django-3.1.4-pyhd3eb1b0_0
  krb5               pkgs/main/osx-64::krb5-1.17.1-hddcf347_0
  libpq              pkgs/main/osx-64::libpq-12.2-h051b688_0
  psycopg2           pkgs/main/osx-64::psycopg2-2.8.5-py38hddc9c9b_0
  pytz               pkgs/main/noarch::pytz-2020.4-pyhd3eb1b0_0
  sqlparse           pkgs/main/noarch::sqlparse-0.4.1-py_0


Proceed ([y]/n)? y


Downloading and Extracting Packages
krb5-1.17.1          | 1.1 MB    | ################################################################################################################################################################# | 100% 
pytz-2020.4          | 180 KB    | ################################################################################################################################################################# | 100% 
libpq-12.2           | 2.0 MB    | ################################################################################################################################################################# | 100% 
asgiref-3.3.1        | 22 KB     | ################################################################################################################################################################# | 100% 
django-3.1.4         | 3.0 MB    | ################################################################################################################################################################# | 100% 
psycopg2-2.8.5       | 144 KB    | ################################################################################################################################################################# | 100% 
sqlparse-0.4.1       | 35 KB     | ################################################################################################################################################################# | 100% 
Preparing transaction: done
Verifying transaction: done
Executing transaction: done

```
</div></summary>

これでdjangoのインストールは完了しました。

## 2. [サンプルを複製する](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django#clone-the-sample)

サイト記載のコマンドを実行してください。

<details><summary>実行結果（git clone）</summary><div>

```
(django-env) $ git clone https://github.com/Azure-Samples/python-docs-hello-django
Cloning into 'python-docs-hello-django'...
remote: Enumerating objects: 57, done.
remote: Counting objects: 100% (57/57), done.
remote: Compressing objects: 100% (46/46), done.
remote: Total 57 (delta 17), reused 28 (delta 6), pack-reused 0
Unpacking objects: 100% (57/57), done.

```
</div></summary>

python-docs-hello-djangoというフォルダが存在すればokです。

## 3. [サンプルを実行する](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django#run-the-sample)

django-env環境をすでに準備しているため。サイトの手順1, 2は不要です。

manage.pyのあるディレクトリに移動（cd）してサイトの手順3以降を実施してください。

<details><summary>実行結果（サンプルアプリの実行）</summary><div>

```
(django-env) $ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
December XX, 2020 - XX:XX:XX
Django version 3.1.4, using settings 'python_docs_hello_world.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```
</div></summary>

## 4. [サンプルのデプロイ](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django#deploy-the-sample)

サイト通り実行してください。コマンドのオプションの説明も細かく記載してあり、ありがたい...

<details><summary>実行結果（サンプルアプリのデプロイ）</summary><div>

```
(django-env) $ az webapp up --sku F1 --name <app-name>
The webapp '<app-name>' doesn't exist
Creating Resource group 'XXXXXXXXX' ...
Resource group creation complete
Creating AppServicePlan 'XXXXXXXXX' ...
Creating webapp '<app-name>' ...
Configuring default logging for the app, if not already enabled
Creating zip with contents of dir XXXXXXXXX ...
Getting scm site credentials for zip deployment
Starting zip deployment. This operation can take a while to complete ...
Deployment endpoint responded with status code 202
You can launch the app at http://<app-name>.azurewebsites.net
{
  "URL": "http://<app-name>.azurewebsites.net",
  "appserviceplan": "XXXXXXXXX",
  "location": "centralus",
  "name": "<app-name>",
  "os": "Linux",
  "resourcegroup": "XXXXXXXXX",
  "runtime_version": "python|3.7",
  "runtime_version_detected": "-",
  "sku": "FREE",
  "src_path": "XXXXXXXXX"
}

```
</div></summary>

存在しないアプロケーション名を付けないと以下のようなエラーが出るので、名前を変更してください。
どうやら、git cloneしたディレクトリの名前は誰かが使用しているみたいです。

```
(django-env) $ az webapp up --sku F1 --name python-docs-hello-django
Webapp 'python-docs-hello-django' already exists. The command will deploy contents to the existing app.
Unable to retrieve details of the existing app 'python-docs-hello-django'. Please check that the app is a part of the current subscription
```


## 5. [アプリの参照](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django#browse-to-the-app)

手順4. サンプルのデプロイで表示されたURLへアクセスしてください。

## 6. [更新の再デプロイ](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django#redeploy-updates)

ここでは、サイトの手順に加えて、以下のような別ページを作成するように編集してみます。

```
http://<app-name>.azurewebsites.net/test
```

以下のファイルを編集します。
- hello/views.py
- hello/urls.py

```hello/views.py
from django.http import HttpResponse
from django.shortcuts import render

def hello(request):
    print("Handling request to home page.")
    return HttpResponse("Hello, Azure!")

def test(request):
    return HttpResponse("This is test!")
```

```hello/urls.py
from django.urls import path

from . import views

urlpatterns = [    
    path('', views.hello, name='hello'),
    path('test/', views.test, name='test'),
]
```

サイト通りデプロイをして、http://\<app-name\>.azurewebsites.net/testへアクセスします。

<details><summary>実行結果（再デプロイ）</summary><div>


```
(django-env) $ az webapp up
Webapp '<app-name>' already exists. The command will deploy contents to the existing app.
Creating zip with contents of dir XXXXXXXXX ...
Getting scm site credentials for zip deployment
Starting zip deployment. This operation can take a while to complete ...
Deployment endpoint responded with status code 202
You can launch the app at http://<app-name>.azurewebsites.net
{
  "URL": "http://<app-name>.azurewebsites.net",
  "appserviceplan": "XXXXXXXXX",
  "location": "centralus",
  "name": "<app-name>",
  "os": "Linux",
  "resourcegroup": "XXXXXXXXX",
  "runtime_version": "python|3.7",
  "runtime_version_detected": "-",
  "sku": "FREE",
  "src_path": "XXXXXXXXX"
}

```
</div></summary>

お、~/testで表示できてますね。

![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224875/5f55fc6f-5b7d-a06e-ebd1-ab9178c88bde.png)

## 7. [ログのストリーミング](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django#stream-logs)

ログの出力内容は割愛させていただきますが、Command+Cでこんなのが見れました。

```
   _____                               
   /  _  \ __________ _________   ____  
  /  /_\  \___   /  |  \_  __ \_/ __ \ 
 /    |    \/    /|  |  /|  | \/\  ___/ 
 \____|__  /_____ \____/ |__|    \___  >
         \/      \/                  \/ 
 
 A P P   S E R V I C E   O N   L I N U X
```

## 8. [Azure アプリの管理](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django#manage-the-azure-app)

サイト通りに確認してみてください。

## 9. [リソースをクリーンアップする](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django#clean-up-resources)

サイト通りに実行し、[Azure portal](https://portal.azure.com/#home)のダッシュボードを確認してください。
最初は--no-waitオプション付けずにどのくらい時間かかるのか待ってみてもいいかもしれません。

リソースが削除されていることを確認できました。

![リソース削除確認画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224875/254d4b86-9ae7-bee7-11a8-18ff6b972f09.png)


クイックスタート終了です。お疲れ様でした。


# 最後に
クイックスタートは非常にわかりやすかった印象です。またコマンドだけでなく、オプションの説明も記載してあるので理解しやすかったように感じました。これから無料期間を使って色々触ってみて、またシェアできればと思います。

こちらの記事は、あくまでも個人の理解・見解になりますので、間違いや誤解をうむような表現があってもご了承ください。ご指摘や質問等あればコメントいただけると嬉しいです。

# 参考

[クイック スタート:Azure App Service on Linux で Python アプリを作成する](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=bash&pivots=python-framework-django)