💪

Azure App Service (Linux) 上の Django コンテナーのログを Azure Files に永続化する方法

に公開

📝 Azure App Service (Linux) 上の Django コンテナーのログを Azure Files に永続化する方法

Azure App Serviceって便利ですよね。
コンテナアプリのデプロイもできるので、自社の環境に応じた様々なWebアプリケーションを、Azure Container Registryを通じて公開可能です。
ただ、この方法は、アプリログもコンテナ内に残ってしまうため、再起動や継続的デプロイにより、ログファイルが消失してしまうという欠点があります。そこで今回は、アプリケーションのログを、永続化のため Azure Storage アカウントのファイル共有 (Azure Files) に保存する方法を紹介したいと思います。
Azure Files へのマウントを利用してファイルにログを書き出すことで、コンテナの再起動後もログを保持できます。
https://learn.microsoft.com/ja-jp/azure/app-service/configure-connect-to-azure-storage?tabs=basic%2Cportal&pivots=container-linux

ここでは Python:3.11-slim ベースのコンテナで動作するDjangoアプリを例に、標準出力とファイル両方にログを記録し、Azure Files をマウントしてログファイルを永続化する手順を詳しく説明したいと思います。
参考までに、Azure Filesを使うメリットを以下にまとめました。

  • コンテナ再起動・再デプロイでもログが残る
  • 複数のApp Serviceインスタンスから同じストレージに書き込み可能
  • SMBプロトコルで接続できるため、外部ツールでもログを直接確認できる

設定方法

1. Django アプリのログ設定(ファイル出力)

前提として、Django側のアプリ構成は以下の通りとします。

django_pj/
├── app
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   ├── __init__.py
│   ├── models.py
│   ├── urls.py
│   └── views.py
├── mounts
├── manage.py
├── project
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── static
│   ├── css
│   └── js
└── templates
      └── index.html

まず、Django 側でログをファイルにも出力する設定を行います。
通常、Djangoのログ設定はsettings.pyの中でLOGGINGという辞書を定義して行います。
以下のように FileHandler を追加することで、ログをファイルに書き出せます。必須ではないですが、ローカルでデバッグする際の利便性も視野に入れ、今回はコンソールへの出力も残しておき、ファイルとコンソールの両方に出力できるように設定しておきます。

# project/settings.py の一部
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',      # 標準出力に出力するハンドラ
        },
        'file': {
            'level': 'INFO',
            'class': 'logging.FileHandler',       # ファイルに出力するハンドラ
            'filename': 'mounts/logs/app.log',   # ログファイルのパス(後述のマウント先)
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'file'],      # コンソールとファイルの両方に出力
            'level': 'INFO',
            'propagate': True,
        },
    },
}

上記では、ログレベルINFO以上のDjangoログをコンソールとファイルに記録する設定をしています。
filename に指定したパス (mounts/logs/app.log) は、後で Azure Files をコンテナにマウントするディレクトリです。このパスに対してログを書き出すことで、Azure Storage上のファイル共有にログが保存されるようになります。なお、必要に応じてformattersを設定して日時などの書式を指定したり、RotatingFileHandler等を用いてログローテーションを行うこともできますが、本記事ではシンプルな設定に留めます。

2. Dockerfileの設定

コンテナイメージ側(Dockerfile)でも、ログを書き出すディレクトリを用意しておく必要があります。上の手順でマウントパスに指定したディレクトリ(例: /mounts/logs)が、コンテナ内になければAzure側でマウントする際に不都合が生じる可能性があります。Dockerfile内でそのフォルダを作成し、適切な権限を設定しておきましょう。

# Dockerfile (抜粋)
FROM python:3.11-slim

WORKDIR django_pj

# ...(省略)...

COPY ./app ./app
COPY manage.py manage.py
COPY ./project ./project
COPY ./static ./static
COPY ./templeates ./templates

# ログ出力用ディレクトリを作成
RUN mkdir -p ./mounts

# (必要に応じて、非rootユーザーで動作させる場合は所有者を変更)
RUN chown -R www-data:www-data ./mounts

# ...(省略)...

上記のように、RUN mkdir -p /mounts/ で空のディレクトリをイメージ内に作成します。
このフォルダはApp Serviceでマウントされるとコンテナ側の中身は見えなくなり(共有ストレージで覆われる)、元からあるファイルは消失します。
前提として、ローカルリポジトリ内にも存在しているディレクトリではあるのですが、デプロイ環境下では空の状態で用意しておくことが重要になります。
「作成するディレクトリはmountsだけで良いのか?」「その直下のlogsなどは必要ないのか?」と疑問に思うかも知れませんが、こちらは後述するファイル共有側で作成します。
Dockerfileの修正後は、イメージをビルドし直してACRへプッシュし、App Serviceのコンテナをデプロイし直してください。新しいイメージがデプロイされると、先ほど構成したストレージマウント設定に基づき /mounts/logs がAzure Filesの共有とつながります。Djangoアプリはそのパスに対してログを書き込み、結果としてログがクラウド上のファイル共有に保存されることになります。

3. Azure Storage アカウントとファイル共有の作成

次に、ログ保存用の Azure ファイル共有を用意します。
Azure Filesは、Azure Storage アカウントで提供される SMBベースのクラウドファイルサーバー機能であり、複数のサービスやVMから共有可能なファイルストレージです。

https://learn.microsoft.com/ja-jp/azure/storage/files/storage-files-introduction

App Service からこのファイル共有をマウントすることで、コンテナからクラウド上のファイルサーバーに直接ログを書き込むことが可能になります。

  1. ストレージアカウントの作成:
    ストレージアカウントを新規作成します。
    Portalから行う場合には、検索バーから「ストレージアカウント」を検索し、リソースグループ、アカウント名、リージョン、パフォーマンス (汎用的な用途であれば Standard)、レプリケーション(ローカル冗長など)を指定して作成してください。
    (もちろん、Azure CLIを使って作成することも可能です。)

  2. ファイル共有の作成:
    作成したストレージアカウントを開き、「ファイル共有」メニューからログ保存用のファイル共有を作成します。
    ファイル共有名を任意に指定(例:「django-logs」など)し、必要に応じてクォータ(最大サイズ)を設定して作成をクリックします。
    以下の画像はAzure Portal上でファイル共有を新規作成する画面の例です。ストレージアカウントの「データストレージ」→「ファイル共有」ブレードから、「+ ファイル共有」をクリックし、名前(例: django-logs)を入力して作成します。
    ファイル共有設定画面

  3. マウント先の子ディレクトリの作成:
    この状態では、ファイル共有の直下にファイルが書き込まれる状態です。先ほどのDjangoの設定では、logファイルの書き込みパスをmounts/logs/app.logと指定していますので、logsディレクトリが足りない状態です。なので、ポータルから作成してあげましょう。

4. App Service へのファイル共有マウント設定

ストレージ側の準備ができたら、App Service に対してファイル共有をマウントします。Azure App Service (Linux) ではAzure Files のマウント機能を使って、コンテナー内にネットワークドライブのようにストレージを接続できます。これにより、コンテナー内の指定ディレクトリ配下のファイル操作が、そのままクラウド上のAzure Files上のファイルに対して行われるようになります。

Portal でのマウント設定手順:

  1. Azure Portal で対象の Web アプリ (App Service) を開き、左側メニューの「設定」から「構成」を選択します。そして上部のタブから「パスのマッピング」をクリックし、「+ 新しい Azure Storage マウント」をクリックします。

  2. 以下のように、「新しいAzure Storage マウント」ダイアログが開くので、各項目を設定します。
    新しいAzureStorageマウント

    • 名前: マウントの構成名を入力します(例: logshareなど。スペースや特殊文字は使用できません)。
    • 構成オプション: 「基本」を選択します。特別なネットワーク構成や Key Vault を使用しない限り基本オプションで問題ありません。
    • ストレージ アカウント: ドロップダウンから先ほど作成したストレージアカウントを選択します。
    • ストレージの種類: 「Azure Files」を選択します。(※注意: 「Azure Blob」を選ぶと読み取り専用マウントとなり、ログを書き込む用途には使えません。ログを保存する場合は必ず Azure Files を選択してください)
    • プロトコル: 「SMB」を選択します。
    • ストレージコンテナー: ドロップダウンから利用したいコンテナを選択します。
    • マウント パス: コンテナー内でストレージ共有をマウントするパスを指定します。
      • Azure App Service側で設定するマウントパスは、Djangoプロジェクトのルートディレクトリを含めて記述する必要があります。今回のケースでは、Dockerfileから作成・定義していますおり、WORKDIR django_pjとしていますので、django_pj/mountsといった形で、必ずWORKDIRを含んだ形で指定する必要があります。
  3. 項目を入力したら「OK」をクリックして設定を保存します。ストレージのマウント設定を追加すると、Webアプリが自動的に再起動されます。再起動後、設定したパスにAzure Filesがマウントされ、コンテナからそのディレクトリ配下のファイルを読み書きできるようになります。

5. 動作確認:

最後に、ログファイルが実際にAzure Files上に保存されていることを確認しましょう。
ログファイルの存在確認: Azure Portalでストレージアカウントの「ファイル共有」ブレードを開き、対象のファイル共有(例: django-logs)を選択します。一覧にログファイル(上記設定では app.log)が作成されていれば成功です。そのファイルを開いて内容が記録されていることも確認してください。Portal上では直接ファイル内容を閲覧できませんので、一度ダウンロードするよいでしょう。
永続性の確認: Webアプリケーションを再起動したり、コンテナのインスタンスが入れ替わった場合でも、Azure Files 上のログファイルが消えずに保持されていることを確認します。例えばApp Serviceを手動で再起動した後でも、前述の方法でファイルが残っていることがわかれば、ログ永続化が正しく機能しています。コンテナのライフサイクルに関係なく、ログファイルがクラウドストレージ上に保管され続ける点がこの方法の利点です。

まとめ

以上、本記事では、Azure App Service (Linux) 上のカスタムコンテナー実行環境で、DjangoアプリケーションのログをAzure Storageのファイル共有にマウントして永続化する手順を解説しました。これにより、アプリケーションのログをコンテナ再起動やデプロイ更新による消失から保護し、長期保管や分析が可能になります。特に複数インスタンス環境でも、各コンテナから同じファイル共有にログを書き出せばログを一元管理できるメリットがあります。 運用上は、ログファイルが無制限に増大しないよう適切にローテーション(ファイルを日付で分割する、一定サイズでローテーションする等)を検討するのが良いと思います。

Discussion