Azure FunctionsがDockerではなくZip Deployで起動する問題の原因と解決策|fuse.zip・packagename.txt・WEBSITE_RUN_FROM_PACKAGE徹底ガイド

「Docker で動かしているはずの Azure Functions が、なぜか fuse.zip をマウントして Zip Deploy(Run‑From‑Package)として起動してしまう」——この症状は、過去のデプロイ痕跡が優先されることで起きます。原因の構造を正しく押さえ、競合設定を無効化し、不要ファイルを掃除するだけで、コンテナ内のコードが確実に使われ、イメージ更新も即時に反映される状態に戻せます。

目次

現象の概要と観測ポイント

Function App を linuxFxVersion = DOCKER|<image>:<tag> に設定しているにもかかわらず、実機では /home/site/wwwroot に fuse.zip がマウントされ、コンテナに内包したコードが無視される現象です。結果として、新しいイメージを push してもアプリに反映されません。

  • 確認済みの前提:WEBSITE_RUN_FROM_PACKAGE は App Settings に存在しない/イメージとタグ指定は正しい/Linux コンテナベースの Function App。
  • 望まれる状態:Zip Deploy の挙動を無効化し、Docker イメージ内のコードが 唯一の実行ソースになること。イメージ更新の即時反映。

以下では、なぜ Zip Deploy が優先されるのかのメカニズム、確実に解消する手順、再発防止の運用指針までを一気通貫で解説します。

なぜ Zip Deploy(Run‑From‑Package)が勝ってしまうのか

Azure Functions(App Service 基盤)は、起動時に「どこからアプリの実体をマウントするか」を段階的に評価します。Docker コンテナであっても、プラットフォームは 過去の Run‑From‑Package の痕跡 が残っていればそれを優先します。キーとなるのが次のファイルです。

/home/data/SitePackages/packagename.txt

このテキストには、最後にデプロイした ZIP パッケージのパスが記録されます。App Settings から WEBSITE_RUN_FROM_PACKAGE を削除していても、packagename.txt が残っている限り、プラットフォームは ZIP を FUSE でマウントし、/home/site/wwwroot を fuse.zip で置き換えます。これが「Docker にしたのに ZIP が乗ってくる」根本原因です。

さらに、VS Code の Zip デプロイ、CLI の az functionapp deployment source config-zip、ポータルの Deployment Center などは、このファイルを自動生成することがあるため、一度でも Zip Deploy を使うと痕跡が残り続けます。

対処の全体像(結論の早見表)

ステップ対応内容目的/効果コマンド例
原因の理解/home/data/SitePackages/packagename.txt が残っていると Run‑From‑Package が優先される。誤作動のトリガーを特定。cat /home/data/SitePackages/packagename.txt
競合設定を無効化WEBSITE_RUN_FROM_PACKAGE を 0 に設定。Run‑From‑Package を明示的に止める。az functionapp config appsettings set --name <app> --resource-group <rg> --settings WEBSITE_RUN_FROM_PACKAGE=0
残存ファイルの削除packagename.txt と不要 ZIP を削除。ZIP マウントの根拠を消す。rm /home/data/SitePackages/packagename.txt
再起動アプリを再起動してマウント構成を再評価。Docker の WORKDIR に戻す。az functionapp restart --name <app> --resource-group <rg>
動作確認fuse.zip が消え、コンテナのディレクトリが見えることを確認。修復の確証を得る。mount | grep wwwroot

実施手順(詳細)

競合設定を明示的にオフにする

値を空文字ではなく 0 に設定する点がポイントです。空の削除だけでは再発します。

az functionapp config appsettings set \
  --name &lt;FunctionApp名&gt; \
  --resource-group &lt;リソースグループ名&gt; \
  --settings WEBSITE_RUN_FROM_PACKAGE=0

この操作で「パッケージから実行」をプラットフォームレベルで抑止します。

Run‑From‑Package の痕跡を削除する

Azure Portal の SSH(ランタイム側)または https://<appname>.scm.azurewebsites.net(Kudu/高度なツール)の Bash に入って、残存ファイルを削除します。

# 中身を確認(任意)
ls -l /home/data/SitePackages
cat /home/data/SitePackages/packagename.txt || true

# 痕跡を削除

rm -f /home/data/SitePackages/packagename.txt

# ZIP が残っていれば合わせて削除

find /home/data/SitePackages -maxdepth 1 -type f -name '*.zip' -delete 

なお、トラブルシューティングは SSH(ランタイム側)で行うのが確実です。Kudu の Bash は scm サイト側のファイルシステムを表示するため、内容が一致しないことがあります。

アプリを再起動する

az functionapp restart --name &lt;FunctionApp名&gt; --resource-group &lt;リソースグループ名&gt;

再起動により、コンテナ起動時のマウント構成が再評価され、/home/site/wwwroot がコンテナ内の実ディレクトリに戻ります。

修復を確認する

# fuse.zip が消えていることを確認
mount | grep wwwroot

# コンテナの実体が見えること(例)

ls -la /home/site/wwwroot 

mount の結果に fuse.zip が含まれない、かつ Dockerfile で用意したフォルダ構造(例:host.json、function.json、言語ごとのエントリなど)が見えていれば完了です。

追加クリーニングと再発防止の設定

  • SitePackages の再点検:ls /home/data/SitePackages で不要 ZIP/TXT が残っていないか確認し、すべて削除。
  • Deployment Center を「None」へ:ポータル > Deployment Center > Settings で Build provider を None に変更(Zip Deploy/ビルドの自動化を無効化)。
  • ビューの食い違いに注意:Kudu Bash は scm サイト側、SSH はランタイム側。整合性チェックやファイル操作は SSH を基準に。
  • App Settings の棚卸し:過去の Zip Deploy が残した SCM_DO_BUILD_DURING_DEPLOYMENT、RUN_FROM_PACKAGE 系のキーがないか見直し。不要なら削除。

コンテナ運用に統一するための指針

「Zip デプロイとコンテナ」の混在は不具合の温床です。以降は次の流れに 一本化 してください。

  1. Docker イメージを再ビルド(/home/site/wwwroot にアプリコードを配備)。
  2. レジストリへ push(推奨:毎回新しいタグまたはイメージダイジェストを使用)。
  3. linuxFxVersion のタグを更新(後述のコマンド例)。

これだけで構成がぶれません。Zip Deploy は使用しない方針にします。

イメージ更新を即座にアプリへ反映させる方法

方法 A:イミュータブルタグ/ダイジェストで linuxFxVersion を更新

タグを更新すればプラットフォームは新イメージを pull し直します。CLI で linuxFxVersion を確実に切り替える最短手は次のとおりです。

# 現在の Function App リソース ID を取得
APP_ID=$(az functionapp show -g <rg> -n <app> --query id -o tsv)

# イメージタグを更新(例:v2025.11.11)

az resource update 
--ids "$APP_ID" 
--set properties.siteConfig.linuxFxVersion="DOCKER|/:" 

同じタグを上書きする運用(例::latest 固定)は、プラットフォーム側キャッシュや pull 最適化の影響で 取りこぼし が発生しやすく、避けるのが無難です。新しいタグ(または @sha256:<digest>)を毎回指定してください。

方法 B:コンテナの継続的デプロイ(ACR Webhook 連携)

Deployment Center でレジストリと連携すると、レポジトリの更新をトリガーに 再起動+再 pull が自動化できます。ただし、本記事の主題である Zip Deploy 痕跡が残っていると正常に切り替わらないため、まずは前章までのクリーニングを先に実施してください。

方法 C:強制再起動/擬似変更で即時反映

手元から即時反映したい場合は、再起動やダミーの App Setting 更新でも引き金にできます。

# 即時再起動
az functionapp restart -g <rg> -n <app>

# ダミー設定でウォームリスタートを誘発

az functionapp config appsettings set 
--name  --resource-group  
--settings FORCE_ROLL="v$(date +%s)" 

Dockerfile の健全性チェック(最小テンプレート)

コンテナ内に /home/site/wwwroot を正しく用意できているかも確認しましょう。代表的なテンプレートを示します。

Python(Functions v4 の一例)

FROM mcr.microsoft.com/azure-functions/python:4-python3.11
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

WORKDIR /home/site/wwwroot
COPY . /home/site/wwwroot

# 依存関係(例)

RUN pip install -r requirements.txt 

Node.js(Functions v4 の一例)

FROM mcr.microsoft.com/azure-functions/node:4-node18
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

WORKDIR /home/site/wwwroot
COPY . /home/site/wwwroot

# 依存関係(例)

RUN npm ci --only=production 

WORKDIR や COPY の行が欠けていると、Zip Deploy 痕跡を消しても関数が見つからないケースがあるため、合わせて点検してください。

Kudu Bash と SSH の違い(つまずきやすいポイント)

機能Kudu(scm サイト)SSH(ランタイム側)使い分けの要点
表示する FSデプロイ/ビルド側の FS実行中コンテナの FS実行実体の確認・削除は SSH が正。
Zip Deploy の痕跡残って見えることがある実マウントの可否が分かるmount | grep wwwroot は SSH で。
ログ/home/LogFiles/kudu/ 等/home/LogFiles/(ホスト/関数)両方見比べて因果を特定。

トラブルシューティングのコマンド集

# Run-From-Package に関する環境変数の確認
env | sort | grep -E 'WEBSITE|RUN_FROM|SCM|FUNCTIONS'

# Run-From-Package 痕跡の確認

ls -l /home/data/SitePackages
cat /home/data/SitePackages/packagename.txt || true

# wwwroot のマウント確認(fuse.zip が出ていないか)

mount | grep wwwroot

# 直近のホストログ

ls -l /home/LogFiles
tail -n 200 /home/LogFiles/default_docker.log 2>/dev/null || true
tail -n 200 /home/LogFiles/kudu/trace/* 2>/dev/null || true 

運用のベストプラクティス(再発させないために)

  • デプロイ経路は「コンテナのみ」:VS Code/CLI の Zip デプロイは使わない。
  • タグは毎回新規::latest 固定は避け、バージョンタグまたはダイジェストで明示。
  • 設定の単一責任:Deployment Center を None に戻し、構成の源泉を一本化。
  • ヘルスチェックを設定:WEBSITE_HEALTHCHECK_PATH を用意すると不整合時の再起動が自動化しやすい。
  • 監査ジョブ:起動後に mount と packagename.txt の有無を検査する小さなスクリプトを仕込むと早期検知できる。

よくある質問(FAQ)

Q:WEBSITE_RUN_FROM_PACKAGE を削除したのに ZIP がマウントされ続けます。
A:/home/data/SitePackages/packagename.txt が残っています。値の削除だけでなく、0 を明示設定し、ファイルも削除してください。

Q:WEBSITE_ENABLE_APP_SERVICE_STORAGE を false にすれば消えますか?
A:/home の永続ストレージ挙動が変わるため副作用が大きく、Functions では推奨しません。本記事の手順(競合無効化+痕跡削除)で対処してください。

Q:コンテナ更新を確実に拾うには?
A:新しいタグ/ダイジェストで linuxFxVersion を更新するのが堅実です。上書きタグ運用は避けましょう。自動化したい場合は、Deployment Center でレジストリと連携して Webhook による再起動を有効化します。

Q:Zip Deploy に戻したくなったら?
A:WEBSITE_RUN_FROM_PACKAGE=1 またはパッケージ URL を設定し、packagename.txt を復元すれば ZIP マウントが有効化されます。ただし本記事の前提(コンテナ運用に統一)とは相反します。

最小再現と自己診断シナリオ

  1. コンテナで正常起動させる(mount | grep wwwroot で FUSE がないことを確認)。
  2. あえて Zip Deploy を 1 度だけ実行。
  3. 結果:以降の再起動で fuse.zip がマウントされるようになる。
  4. 本記事の手順(WEBSITE_RUN_FROM_PACKAGE=0 設定、packagename.txt 削除、再起動)を実施。
  5. 期待結果:FUSE が消え、コンテナの /home/site/wwwroot が有効になる。

開発・運用チーム向けチェックリスト

  • [ ] デプロイ経路は 1 つ(コンテナのみ)。
  • [ ] Zip Deploy 痕跡の消去(packagename.txt、不要 ZIP なし)。
  • [ ] App Settings 整理(WEBSITE_RUN_FROM_PACKAGE=0/不要キー無し)。
  • [ ] タグ戦略(イミュータブルタグ or ダイジェスト)。
  • [ ] 更新トリガー(linuxFxVersion 更新 or Webhook)。
  • [ ] 起動後の自己診断(mount | grep wwwroot 自動検査)。

障害復旧のためのワンライナー集(まとめて実行)

# 1) Run-From-Package を完全無効化
az functionapp config appsettings set \
  --name <app> --resource-group <rg> \
  --settings WEBSITE_RUN_FROM_PACKAGE=0

# 2) 痕跡削除(失敗しても続行)

( rm -f /home/data/SitePackages/packagename.txt || true ) && 
( find /home/data/SitePackages -maxdepth 1 -type f -name '*.zip' -delete || true )

# 3) 再起動

az functionapp restart -g  -n 

# 4) 検証

mount | grep wwwroot || echo "OK: fuse.zip はマウントされていません" 

問題が再発する典型パターンと回避策

パターン説明対策
VS Code の Zip デプロイをうっかり実行便利なワンクリックが packagename.txt を生成。拠点メンバーの権限/手順を見直し、コンテナのみに限定。
Deployment Center が Zip か Oryx ビルドに設定scm 側で ZIP が継続生成される。None に戻す。コンテナ CD を使うなら コンテナのみ選択。
:latest タグ固定キャッシュにより pull の取りこぼしが発生。毎回新タグ、またはダイジェスト固定に切替。
Dockerfile で /home/site/wwwroot にコピーしていない痕跡を消しても関数が見えない。COPY . /home/site/wwwroot と WORKDIR を定義。

まとめ

本件の本質は「Docker と Zip Deploy の優先衝突」です。主犯は /home/data/SitePackages/packagename.txt。WEBSITE_RUN_FROM_PACKAGE=0 を明示し、痕跡を削除し、再起動して fuse.zip を排除すれば、コンテナのコードが唯一の実行ソースに戻ります。以後はデプロイ経路をコンテナに統一し、イミュータブルなタグで linuxFxVersion を更新する運用にすれば、イメージ更新が即座に、そして確実に本番へ反映されるようになります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次