Skip to content

Instantly share code, notes, and snippets.

@alfonsogarciacaro
Last active March 3, 2023 09:50
Show Gist options
  • Save alfonsogarciacaro/578ed3cadf091121715e461c8902ac9f to your computer and use it in GitHub Desktop.
Save alfonsogarciacaro/578ed3cadf091121715e461c8902ac9f to your computer and use it in GitHub Desktop.
Deploying an F# ASP.NET Core app (Giraffe) to Azure

Deploying an F# ASP.NET Core app to Azure

Last week I spent a lot of time trying to deploy an F# ASP.NET Core app (a Giraffe app, specifically) to Azure because the information to complete all the steps was scattered in several places. So I'm writing this hopefully it will save the pain to others :)

Preparation

The following steps are mostly taken from this guide and it's only necessary to do them once:

  1. Create an account in Azure (or use an existing one)
  2. Create a resource group (or use an existing one)
  3. Create an app service plan (not sure if you can reuse an existing plan, we'll be using a free plan here)
  4. Create a webapp with a given name, linked to the plan and resource group
  5. Assign a username and a password for deployment
  6. Get the URL for git deployment
  7. Add a web.config to your app

The first 4 steps can be done using the Azure portal (in which case 3 and 4 are combined) or using the Azure CLI according to the guide:

resourcegroup=<Replace with desired resource group name>
webappname=<Replace with desired web app name>

# Create a resource group.
az group create --location westeurope --name $resourcegroup

# Create an App Service plan in FREE tier.
az appservice plan create --name $webappname --resource-group $resourcegroup --sku FREE

# Create a web app.
az webapp create --name $webappname --resource-group $resourcegroup --plan $webappname

The next 2 steps I only managed to do using the Azure CLI:

username=<Replace with desired deployment username>
password=<Replace with desired deployment password>

# Set the account-level deployment credentials
az webapp deployment user set --user-name $username --password $password

# Configure local Git and get deployment URL
az webapp deployment source config-local-git --name $webappname --resource-group $resourcegroup --query url

Write down the URL. The last step for the preparation is to add a web.config file to your app. This may be obvious for ASP.NET developers, but it took me a couple of hours until I found this issue and realized I was missing it. Create a web.config file next to the .fsproj with contents similar to the following:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet" arguments="Server.dll" stdoutLogEnabled="false" stdoutLogFile="logs/stdout" />
  </system.webServer>
</configuration>

ATTENTION: Note you may have to change Server.dll to match the name of your app assembly.

And make sure your .fsproj contains a tag like the following within ItemGroup:

    <None Include="web.config" CopyToOutputDirectory="PreserveNewest" />

Deployment

Now we are ready to deploy our app! When using GIT for deployment, the guides I have found suggest to commit your repo as is and let Azure build the app for you app. However we won't do that for two reasons: firstly I couldn't manage to make it work (maybe because F#?), and secondly your build script may include other steps besides building the ASP.NET Core project (in my case, compiling a Fable app for frontend, for example) and I don't know how to tell Azure to run those. Because of this, we are going to create an ad hoc repo for every deployment just to push the .NET assemblies and other files we may need. Find below the script I'm using for this (it's bash but the commands can be easily addapted to your build process):

GITURL=<Replace with the URL you wrote down before>

rm -rf deploy
dotnet publish -c Release src/Server -o ../../deploy

# Do here other build steps like running `yarn build`
# to put your minified frontend files in /deploy/public

pushd deploy
git init
git remote add origin $GITURL
git add -A
git commit -m "Update app"
git push origin master
popd

I hope this is useful to you and saves you time :) If you spot any mistake please comment below or send a PR (can you send PRs to gists?).

Update - Deploying from a zip file

I just learned that it's possible to deploy by simply pushing a zip file. This may be more convenient in our case because we are deploying binary files that are ready to use, which means we don't need source control nor Kudu performing builds (in fact, I learned about this way because Kudu started to mess around with my deployments using git). For this we only need to edit the script above in the following way:

USER=<username>
APPNAME=<appname>
ZIPURL=https://$USER@$APPNAME.scm.azurewebsites.net/api/zipdeploy

rm -rf deploy
dotnet publish -c Release src/Server -o ../../deploy

# Do here other build steps

pushd deploy
zip -r deploy.zip .
curl -X POST -u $USER --data-binary @deploy.zip $ZIPURL
popd

Note the format of the URL, it should be the same as the previous GIT url except for the zipdeploy part. The only inconvenience of this script is you have to type the password every time. If you have it in an environmental variable (say PASS) you can change the curl command to:

curl -X POST -u $USER:$PASS --data-binary @deploy.zip $ZIPURL
@nmfisher
Copy link

nmfisher commented Mar 29, 2019

Thanks for this - also note that this only seems to work on Windows App Service plans (not Linux, which according to this seems to look for the .csproj file to determine the correct .dll to run).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment