Anthony Chu Contact Me

Upload Files to Blob Storage during App Service (and Azure Functions) Deployment

Wednesday, February 7, 2018

A couple of months ago, AzCopy was quietly added to Windows App Service and Azure Functions worker instances at D:\devtools\AzCopy\AzCopy.exe. It is used to upload files to blob storage from the command line. App Service allows the running of arbitrary scripts during deployment, meaning that there are a couple of scenarios that are now possible by calling AzCopy during App Service Git deployment, including deployments with a "Deploy to Azure" button:

  • Upload files to blob storage for serving from a CDN during a Web App deployment
  • Upload a single page application (SPA) frontend to blob storage during an Azure Function App deployment

Today, we'll use Joe Raio's popular Azure Functions Tug of War demo app to show how to upload the app's frontend assets to blob storage during deployment.

Post deployment scripts

Project Kudu powers the build and deployment system for App Service and Functions. It is extremely configurable and includes the ability to run post deployment action hooks.

To run post deployment scripts, we have to specify a folder that contains the scripts. To do this, we can create a .deployment file in the root of the application.


This file tells Kudu to find a folder named deployment at the root of the repository and execute the scripts inside.

Upload to blob storage

Now we need to create a folder named deployment with a PowerShell script inside. The script can really be called anything, for example: deploy-content-to-storage.ps1.


$containerName = "content"
$destinationUri = "https://$($Env:mycontainer_uri)/$containerName"
$destinationKey = $Env:STORAGE_KEY
D:\devtools\AzCopy\AzCopy.exe /Source:.\Client /Dest:$destinationUri /DestKey:$destinationKey /SetContentType /S /Y
if ($LastExitCode -ne 0) { throw "azcopy returned code $($LastExitCode)" }

$storageContext = New-AzureStorageContext -ConnectionString $Env:AzureWebJobsStorage -ErrorAction Stop
Set-AzureStorageContainerAcl -Container $containerName -Permission Blob -Context $storageContext -ErrorAction Stop

The script requires an app setting named STORAGE_KEY to be set. It also uses the Function App's built in storage account (AzureWebJobsStorage). It is pretty simple:

  1. Use AzCopy to upload files to storage. If the container doesn't exist, AzCopy automatically creates it.
  2. The container created by AzCopy defaults to an access level of "Private". We run the New-AzureStorageContext and Set-AzureStorageContainerAcl commands to update the access level to "Blob" so that the files can be accessed publicly.

Deploy to Azure

And that's it. The script will run during any GitHub deployment to a Function App. This includes a deployment using the "Deploy to Azure" button. Head over to the updated application and click the button to try it out!

Source code

It's now also been merged into Joe's Functions Tug of War demo.