As a personal project, I'm learning about GitHub Actions and DevOps in general. I'm a former .NET developer so it's my prefered technology to work with.
My goal on this post, is to deploy a sample .NET 5 application to Azure App Service as a container with GitHub Actions. I will author the ARM template using Bicep.
I work on MacOS but the same process can be achieved on Windows or Linux.
Let's start.
Tooling
Few tools used on this project:
- An Azure Subscription to deploy resources
- A GitHub repository to store the source code and use GitHub Actions
- Azure CLI
- Bicep
- I recommend Visual Studio Code
- Dotnet 5
- A terminal to execute commands
Create new .NET 5 project
First, we have to create a new project.
In my case I created a repository called demoaspnet5container
The command to clone the repository to local folder is:
git clone https://github.com/MCKLMT/demoaspnet5container.git
We now have a copy of our repository locally.
We will create a new .NET 5 project.
Go in the cloned folder and execute the following command. In my case, my project will be called WebApp:
dotnet new project WebApp
Our new project has been created and you can run it locally using the command:
dotnet run
And now, you can browse the web site locally using your browser at http://localhost:5000
You can create a .gitignore file to avoid to push build artetifacts to GitHub with the following command:
dotnet new gitignore
Authoring the Docker image
Now we have our application, we want to containerize it.
To do so, we create a Dockerfile file in the same folder than the application.
The Dockerfile looks like this one:
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build-env
WORKDIR /app
RUN dotnet --version
COPY *.csproj ./
RUN dotnet restore
COPY . ./
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:5.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "WebApp.dll"]
This file is pretty simple.
First, we use a build image to restore dependencies and publish the content of the web site and secondly, we copy the resulting of the build to a new image.
Using Bicep to author ARM template
Bicep is a recent open source project which aims to simplify the authoring of Azure Resource Manager templates.
Once the template is created, you have to run the following command to build the ARM file:
bicep build main.bicep
This command will output the ARM file you can deploy using Azure CLI for instance.
I would like to share few things about it.
First, in my case, I want to use Azure App Service on Linux to host the container I built previously. The container image will be built and stored with Azure Container registry. To do so, Azure App Service will need to have the rights to pull the image from Azure Container Registry. To achieve this goal, I will create a user managed identity and affect this identity to App Service. Afterwards, I assign the permission to pull the registry to the identity. Voilà, our App Service can safely access the registry.
The bicep code of user managed identity and the role assignment:
resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
name: 'webAppIdentity'
location: location
}
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
name: roleAssignmentName
scope: containerRegistry
properties: {
roleDefinitionId: roleDefinitionId
principalId: managedIdentity.properties.principalId
principalType: 'ServicePrincipal'
}
}
The complete bicep file is available on GitHub
Create our GitHub workflow
We have all the code to be deployed on Azure.
- The bicep file which will be converted to ARM template
- The Docker image to deploy to App Service
We will create a .github/workflows/dotnet-core.yaml file. This file will contain all the steps needed and will be executed at each commit push on the master branch.
First, we will deploy the infrastructure. We have to build our bicep file, connect to Azure and deploy the resulting template:
- name: Run Bicep build
uses: aliencube/bicep-build-actions@v0.1
with:
files: Infrastructure/main.bicep
- name: Login to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Deploy Azure Resource Manager (ARM) Template
uses: azure/arm-deploy@v1
id: deploy
with:
scope: resourcegroup
subscriptionId: ${{ secrets.SUBSCRIPTION_ID }}
resourceGroupName: demoaspnet5container-rg
template: ./Infrastructure/main.json
deploymentMode: Incremental
Secondly, we will build the container using Azure Container Registry:
- name: Build image with ACR
uses: azure/CLI@v1
with:
azcliversion: latest
inlineScript: |
az acr build --registry ${{ steps.deploy.outputs.registryNameOutput }} --image aspnet5webapp:${{ env.COMMIT_REF }} ./WebApp/
The source code will be zipped, uploaded to Azure Container Registry and built in the cloud.
The final step is to tell to App Service where to get the image:
- name: Deploy the image to App Service
uses: azure/CLI@v1
with:
azcliversion: latest
inlineScript: |
az webapp config container set --name ${{ steps.deploy.outputs.webAppNameOutput }} --resource-group ${{ steps.deploy.outputs.resourceGroupOutput }}
Congratulations, your website should be up and running!
I hope you liked this post and feel free to contact me on Twitter if you want to discuss about it!
Resources
The complete source code is available on GitHub:
MCKLMT / demoaspnet5container
Sample ASP.NET 5 application deployed to App Service on Linux as a container with GitHub Actions
Few resources to go deep on this topic:
Top comments (0)