1. Introduction
In cloud environments, application storage behaves differently from traditional on-premise servers. Containers and platform services such as Azure App Service use ephemeral (temporary) storage by default. This means:
- Files written inside the container may disappear after restart.
- Scaling the application to multiple instances does not automatically share local disk content.
- Container redeployments may wipe locally stored files.
To solve this problem, Azure provides Azure File Shares, which offer persistent, shared storage that can be mounted into App Service containers.
In this lab, you will:
- Deploy a Flask web application
- Create an Azure Storage Account
- Create an Azure File Share
- Upload files using Azure CLI
- Mount the file share inside the App Service container
- Verify persistent shared storage behavior
Before starting, ensure:
- Azure CLI is installed
- You have an active Azure subscription
- You are logged in — verify with:
az account show
- You have a working Flask app from the previous exercise
2. Architecture Overview
At the end of this lab, your architecture will look like this:
User → Azure App Service (Flask App)
│
│ mounted path (/mountfiles)
↓
Azure Storage Account
↓
Azure File Share
The App Service container will access persistent storage through a mounted directory.
3. Create Infrastructure
We will first create the required Azure infrastructure step by step.
To avoid repeating long names and reduce typing errors, we define variables.
RESOURCE_GROUP=rg-appservice-lab
LOCATION=westeurope
APP_NAME=flaskapp$RANDOM
PLAN_NAME=flask-plan
STORAGE_NAME=storage$RANDOM
FILE_SHARE=sharedfiles
Explanation:
$RANDOMensures globally unique names (required for storage accounts and web apps).- Keeping all resources in one resource group simplifies cleanup.
⚠️ These variables are only valid for the current terminal session. If you close your terminal, re-run this block before continuing. You can also save them for reference:
echo "APP_NAME=$APP_NAME" >> lab-vars.env echo "STORAGE_NAME=$STORAGE_NAME" >> lab-vars.env
Create Resource Group
A Resource Group is a logical container for Azure resources.
az group create \
--name $RESOURCE_GROUP \
--location $LOCATION
This command prepares a dedicated environment for our lab.
Create App Service Plan
The App Service Plan defines:
- Compute resources
- Pricing tier
- Operating system
az appservice plan create \
--name $PLAN_NAME \
--resource-group $RESOURCE_GROUP \
--sku B1 \
--is-linux
Explanation:
--sku B1= Basic tier (sufficient for lab)--is-linux= Required for Python runtime
4. Deploy the Web App (Python Runtime)
Now we create and deploy the web application.
Navigate to your Flask project directory, then deploy:
az webapp up \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP \
--plan $PLAN_NAME \
--runtime "PYTHON:3.10"
This creates the web app and deploys your code in a single step.
Verify it works:
echo https://$APP_NAME.azurewebsites.net
Open the URL in your browser.
At this stage:
- Your app is running
- It uses only container-local storage
- No persistent shared disk exists yet
5. Create Azure Storage
Now we create persistent storage that will survive restarts and scaling.
Create Storage Account
az storage account create \
--name $STORAGE_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--sku Standard_LRS
Explanation:
- Storage accounts must have globally unique names.
Standard_LRSis cost-efficient and sufficient for labs.
Retrieve Storage Access Key
Azure File Share authentication requires an access key.
⚠️ Store the access key securely. Do not commit it to source control. For production workloads, prefer Entra ID (Azure AD) authentication with
--auth-mode login.
STORAGE_KEY=$(az storage account keys list \
--resource-group $RESOURCE_GROUP \
--account-name $STORAGE_NAME \
--query "[0].value" \
--output tsv)
We store it in a variable for later use.
Create File Share
az storage share create \
--name $FILE_SHARE \
--account-name $STORAGE_NAME \
--account-key $STORAGE_KEY \
--quota 5
Explanation:
--quota 5means 5 GB maximum size.- This share behaves like a network file system inside Azure.
Create a test file:
echo "Hello from Azure File Share" > testfile.txt
Upload it:
az storage file upload \
--share-name $FILE_SHARE \
--source testfile.txt \
--path testfile.txt \
--account-name $STORAGE_NAME \
--account-key $STORAGE_KEY
Verify upload:
az storage file list \
--share-name $FILE_SHARE \
--account-name $STORAGE_NAME \
--account-key $STORAGE_KEY \
--output table
Now the file exists in persistent cloud storage.
6. Mount File Share to App Service
Now we connect the Web App to the File Share.
This creates a mapping between the container and Azure storage.
Configure Mount
az webapp config storage-account add \
--resource-group $RESOURCE_GROUP \
--name $APP_NAME \
--custom-id fileshareconnection \
--storage-type AzureFiles \
--account-name $STORAGE_NAME \
--share-name $FILE_SHARE \
--access-key $STORAGE_KEY \
--mount-path /mountfiles
Explanation:
/mountfileswill appear inside the container- Anything written there is stored in Azure File Share
- The storage is persistent and shared
Verify the mount was registered:
az webapp config storage-account list \
--resource-group $RESOURCE_GROUP \
--name $APP_NAME \
--output table
Restart the app:
az webapp restart \
--resource-group $RESOURCE_GROUP \
--name $APP_NAME
Update your app:
import os
from flask import Flask, Response
app = Flask(__name__)
@app.route("/files")
def list_files():
path = "/mountfiles"
if not os.path.exists(path):
return Response("Mount path not found", status=404, mimetype="text/plain")
files = sorted(os.listdir(path))
if not files:
return Response("(empty)", mimetype="text/plain")
return Response("\n".join(files), mimetype="text/plain")
if __name__ == "__main__":
app.run()
Redeploy:
az webapp up \
--name $APP_NAME \
--resource-group $RESOURCE_GROUP
Test:
echo https://$APP_NAME.azurewebsites.net/files
Open the printed URL in your browser.
You should see:
testfile.txt
This confirms the container can access shared storage.
7. Persistence Test
Restart the web app:
az webapp restart \
--resource-group $RESOURCE_GROUP \
--name $APP_NAME
Check /files again.
If the file is still there → persistent storage works.
Cleanup
Always clean up cloud resources to avoid charges:
az group delete \
--name $RESOURCE_GROUP \
--yes \
--no-wait
Final Result
You now understand:
- How Azure App Service handles disk storage
- Why local container storage is not reliable
- How to mount Azure File Share
- How to build persistent cloud-native applications