AzureにDjangoで作ったwebアプリのContainerをデプロイしてみる
記事にする前のメモ
自分用目次
- Django設定
- WebApps構築(CDも構築)
- Application Gateway設置
- Azure StorageをPrivate Link経由でWebAppsにマウント
- DBをPrivate Link経由でWebAppsに接続(予定)
- 未定
構成は
デプロイは
DBは一旦置いておく
DjangoのアプリはContainer化してデプロイする
とりあえず、空のリポジトリ
- djangoインストール
poetry add django
- プロジェクト作る
poetry run django-admin startproject sampleProject .
- sampleアプリ追加
poetry run python manage.py startapp sample
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'sample', # add
]
- sampleアプリを適当に書く
from django.http import HttpResponse
def index(request):
return HttpResponse('Hello Sample')
- ルーティング
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('sample/', include('sample.urls')) # add
]
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
]
- migrate
poetry run python manage.py migrate
- 起動
poetry run python manage.py runserver
OK
- docker
FROM python:3.8-slim-buster
ENV PYTHONUNBUFFERED=1
EXPOSE 8000
WORKDIR /app
COPY . .
RUN pip install poetry
RUN poetry config virtualenvs.create false
RUN poetry update
RUN python manage.py migrate
RUN chmod 744 ./startup.sh
ENTRYPOINT ["./startup.sh"]
#!/bin/bash
python manage.py runserver 0.0.0.0:8000
docker build -t sample-django .
docker run -p 8000:8000 sample-django
ok
- gunicornを使う
poetry add uvicorn gunicorn
#!/bin/bash
#python manage.py runserver 0.0.0.0:8000
gunicorn sampleProject.asgi:application -w 2 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
とりあえず、サンプルアプリ作るのはココまで。
ここからAzure
-
App Service Plan作る
-
料金プランが無料だとたぶん積むのでB1にしておく-
本格的に使うならP系のプラン必須ですが、試すだけだと高いので、、、
-
-
結局
P1V2
プランにしました。- P系でないとVNet統合が使えなくてこの先で詰んだので
- ちょっと試したいだけなのに月額1万です。こういうところ、Azureの学習コストって最悪ですよね!
-
ContainerRegistry作る
- とりあえず、一番やすいやつにしておく
- ContainerRegistryの管理ユーザー有効化
- これしないとWebAppsと連携できない
- これしないとWebAppsと連携できない
-
GtiHub Actionsで、github → Azure Container Registry
-
これ使えばいけるか?
いや、これだと、直接WebAppsにデプロイするのか。
それでもいいけど、、、
これか。面倒くさいな。また今度にしよう。
これContainer Instanceやん。。。違うじゃん。。。
調べてもよく分からんから、自力でgithub actions 書いた
- AzureにWebApps追加
コンソールを日本語にしてると逆に検索しづらいんだよなぁ。。。
デプロイセンターで「継続的デプロイ」をオン
WebAppsの前にApplicationGatewayを置く
- Application GW作成時に、バックエンドにwebappsを指定
フロントエンド・ルーティング・バックエンドを適当に設定
- 本当はhttpsにするべきだけど、今回はサンプルなのでhttpで。
- WAFも今回は使わない。高いので。
WebAppsにアクセス制御を入れて、ApplicationGatewayのあるSubnetからの通信のみを許可する
ApplicationGatewayめっちゃ遅い。。。
なんかエラーになった
Djangoにhostの設定を入れる必要があるっぽい
ALLOWED_HOSTS = ['*.azurewebsites.net']
これで行けるか?
→ダメでした。。。
とりあえず、
ALLOWED_HOSTS = ['*']
にしたら、WebApps上は大丈夫になったんだけど、Application Gatewayからだと502になるわ。
なんでよ、、、
よく分からんけど、Application Gatewayのレベルを'Standard'でなくて'Standard V2'で作り直したらうまくいった
あ、このキャプチャは、後から説明用に撮ったんですけど、リージョンがEast Asiaになってますね。
Japan Eastで作ってます。
↓
- 「正常性プルーブ設定したから動くようになった。」が正しそう。
- ルーティングの設定で直下は404だったから、ヘルスチェックでエラーになってたっぽい
- こんな感じで、200になるsample配下に正常性プルーブを向けたら動いた
- ルーティングの設定で直下は404だったから、ヘルスチェックでエラーになってたっぽい
Django初めて触ったんだけど、settings.py
にSECRET_KEY
とかいう不穏な項目があるじゃないですか。。。
これgitに上げちゃダメなやつじゃないですか。。。
↓
- もう遅いけど、環境変数に隠しました。
- ついでにローカル用に
python-dotenv
入れました
- ついでにローカル用に
poetry add python-dotenv
import os
from dotenv import load_dotenv
load_dotenv(verbose=True)
SECRET_KEY = os.getenv('SECRET_KEY')
(参考) :
DjangoのSECRET_KEYを再生成
DjangoのHOSTの設定はこれで良さそう。
ALLOWED_HOSTS = ['(WebApps名).azurewebsites.net']
Application GatewayのHTTP設定のホスト名の設定
とりあえず、これで一通りいいかな。。。
アーキテクチャ図(まだ作ってないところ含む)
ここから、WebAppsにAzure Storageをマウントする話
- VNetにAzureWebAppsからのVNET統合用のサブネットを作る
- VNetにAzure StorageへのPrivate Endpoint用のサブネットを作る
Storageのリソース作って、ネットワーク->プライベートエンドポイント接続で設定
Storageのネットワーク->ファイアウォールと仮想ネットワークで、VNET統合用のサブネットからのアクセスを許可
WebAppsのリソースに移動して、[構成]->[パスのマッピング]から、Azure Storageマウントを追加する
-
privateで繋ぐ場合、Basicだとダメなので詳細設定
-
BLOBはRead only、書き込みしたい時はAzure Files
-
WebAppsで設定するAzure Filesは、AzureStorageの「ファイル共有」のこと(分かるかこんなもん!!!)
-
WebAppsで設定する「共有名」は、 AzureStorageのファイル共有の「名前」にあわせる(分かるかこんなもん!!!)
これでつながった。
なお設定をミスると、Containerが起動すらしないので注意。
起動すらしないので、ログも見れません。。。「共有名」の設定間違って立ち上がらなくて意味不明でつらかった。
あと、なんでプライベート接続なのに、アクセスキー必要なんだろう?
ロールベースのアクセスをしてほしい。
WebAppsとDBつないでみる
とりあえずローカルでやる
AzureなのでMSSQL使う。
ローカル用にdocker立ち上げる
version: "3"
services:
db:
platform: linux/x86_64
image: mcr.microsoft.com/mssql/server:2019-latest
environment:
ACCEPT_EULA: Y
MSSQL_SA_PASSWORD: P@ssw0rd
TZ: "Asia/Tokyo"
volumes:
- ./volumes/db/data:/var/opt/mssql
ports:
- 1433:1433
ローカルだから適当でいいやと思ってパスワードをpassword
にしたら起動出来なかった。
ちゃんとチェックしていやがる。
aldjemyを入れる
% poetry add aldjemy
Using version ^2.6 for aldjemy
Updating dependencies
Resolving dependencies... (6.0s)
Writing lock file
Package operations: 3 installs, 0 updates, 0 removals
- Installing greenlet (1.1.2)
- Installing sqlalchemy (1.4.34)
- Installing aldjemy (2.6)
mssql-djangoを入れる
% poetry add mssql-django
Using version ^1.1.2 for mssql-django
Updating dependencies
Resolving dependencies... (0.9s)
Writing lock file
Package operations: 3 installs, 0 updates, 0 removals
- Installing pyodbc (4.0.32)
- Installing pytz (2022.1)
- Installing mssql-django (1.1.2)
settings.pyを編集
ALDJEMY_ENGINES = {
"mssql": 'mssql+pyodbc'
}
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": os.getenv('MS_DB_NAME', ''),
"USER": os.getenv('MS_DB_USER', ''),
"PASSWORD": os.getenv('MS_DB_PASSWORD', ''),
"HOST": os.getenv('MS_DB_HOST', 'localhost'),
"PORT": os.getenv('MS_DB_PORT', '1433'),
"OPTIONS": {
"driver": os.getenv('MS_DB_DRIVER', 'ODBC Driver 18 for SQL Server'),
},
},
}
ODBCドライバーのインストール
Djangoモデルに対して、、、
class User(models.Model):
id = models.IntegerField(primary_key=True)
username = models.CharField(max_length=16)
email = models.EmailField(max_length=254)
password = models.CharField(max_length=128)
SAが生えていて、SQLAlchemyモデルとして使える!!
from sample.models import User
User.sa.query().all()
中身を取り出し。もうちょっとキレイに書けないか?
users = [{k: v for k, v in u.__dict__.items() if k != "_sa_instance_state"}
for u in User.sa.query().all()]
それはそうとローカルで立ち上げたdockerのSQL Serverだとエラーになるんだよなぁ、、、
django.db.utils.OperationalError: ('08001', '[08001] [Microsoft][ODBC Driver 18 for SQL Server]SSL Provider: [error:0A000086:SSL routines::certificate verify failed:self-signed certificate] (-1) (SQLDriverConnect)')
Azure上のSQL Databaseだと動くのに!!
なんで?
localのsql serverでsslのエラーになる件の対応。
DATABASES
のOPTIONS
に"extra_params": "TrustServerCertificate=yes",
を追加。
全然情報なくて、くっそ強敵でした。。。TrustServerCertificate=yes
のオプションを入れればいいことは割とすぐに分かったのですが、オプションを入れる場所がさっぱり分からんかったわ。。。
ALDJEMY_ENGINES = {
"mssql": 'mssql+pyodbc'
}
DATABASES = {
"default": {
"ENGINE": "mssql",
"NAME": os.getenv('MS_DB_NAME', ''),
"USER": os.getenv('MS_DB_USER', ''),
"PASSWORD": os.getenv('MS_DB_PASSWORD', ''),
"HOST": os.getenv('MS_DB_HOST', 'localhost'),
"PORT": os.getenv('MS_DB_PORT', '1433'),
"OPTIONS": {
"driver": os.getenv('MS_DB_DRIVER', 'ODBC Driver 18 for SQL Server'),
"extra_params": "TrustServerCertificate=yes",
},
},
}
一通り記事にしたので、closeします