Tutorial: Use GitHub Actions to deploy to an App Service custom container and connect to a database
This tutorial walks you through setting up a GitHub Actions workflow to deploy a containerized ASP.NET Core application with an Azure SQL Database backend. When you're finished, you have an ASP.NET app running in Azure and connected to SQL Database. You'll first create Azure resources with an ARM template GitHub Actions workflow.
In this tutorial, you learn how to:
- Use a GitHub Actions workflow to add resources to Azure with a Azure Resource Manager template (ARM template)
- Use a GitHub Actions workflow to build a container with the latest web app changes
If you don't have an Azure subscription, create an Azure free account before you begin.
Prerequisites
To complete this tutorial, you'll need:
- An Azure account with an active subscription. Create an account for free.
- A GitHub account. If you don't have one, sign up for free.
- A GitHub repository to store your Resource Manager templates and your workflow files. To create one, see Creating a new repository.
Download the sample
Fork the sample project in the Azure Samples repo.
https://github.com/Azure-Samples/dotnetcore-containerized-sqldb-ghactions/
Create the resource group
Open the Azure Cloud Shell at https://shell.azure.com. You can alternately use the Azure CLI if you've installed it locally. (For more information on Cloud Shell, see the Cloud Shell Overview.)
az group create --name {resource-group-name} --location {resource-group-location}
Generate deployment credentials
OpenID Connect is an authentication method that uses short-lived tokens. Setting up OpenID Connect with GitHub Actions is more complex process that offers hardened security.
If you do not have an existing application, register a new Microsoft Entra ID application and service principal that can access resources.
az ad app create --display-name myApp
This command will output JSON with an
appId
that is yourclient-id
. Theid
isAPPLICATION-OBJECT-ID
and it will be used for creating federated credentials with Graph API calls. Save the value to use as theAZURE_CLIENT_ID
GitHub secret later.Create a service principal. Replace the
$appID
with the appId from your JSON output.This command generates JSON output with a service principal
id
. The service principalid
is used as the value of the--assignee-object-id
argument in theaz role assignment create
command in the next step.Copy the
appOwnerOrganizationId
from the JSON output to use as a GitHub secret forAZURE_TENANT_ID
later.az ad sp create --id $appId
Create a new role assignment for your service principal. By default, the role assignment will be tied to your default subscription. Replace
$subscriptionId
with your subscription ID,$resourceGroupName
with your resource group name, and$servicePrincipalId
with the newly created service principal id.az role assignment create --role contributor --subscription $subscriptionId --assignee-object-id $servicePrincipalId --assignee-principal-type ServicePrincipal --scope /subscriptions/$subscriptionId/resourceGroups/$resourceGroupName
Run the following command to create a new federated identity credential for your Microsoft Entra ID application.
- Replace
APPLICATION-OBJECT-ID
with the objectId (generated while creating app) for your Microsoft Entra ID application. - Set a value for
CREDENTIAL-NAME
to reference later. - Set the
subject
. The value of this is defined by GitHub depending on your workflow:- Jobs in your GitHub Actions environment:
repo:< Organization/Repository >:environment:< Name >
- For Jobs not tied to an environment, include the ref path for branch/tag based on the ref path used for triggering the workflow:
repo:< Organization/Repository >:ref:< ref path>
. For example,repo:n-username/ node_express:ref:refs/heads/my-branch
orrepo:n-username/ node_express:ref:refs/tags/my-tag
. - For workflows triggered by a pull request event:
repo:< Organization/Repository >:pull_request
.
- Jobs in your GitHub Actions environment:
az ad app federated-credential create --id <APPLICATION-OBJECT-ID> --parameters credential.json ("credential.json" contains the following content) { "name": "<CREDENTIAL-NAME>", "issuer": "https://token.actions.githubusercontent.com", "subject": "repo:octo-org/octo-repo:environment:Production", "description": "Testing", "audiences": [ "api://AzureADTokenExchange" ] }
- Replace
To learn how to create an active directory application, service principal, and federated credentials in Azure portal, see Connect GitHub and Azure.
Configure the GitHub secret for authentication
You need to provide your application's Client ID, Tenant ID, and Subscription ID to the login action. These values can either be provided directly in the workflow or can be stored in GitHub secrets and referenced in your workflow. Saving the values as GitHub secrets is the more secure option.
In GitHub, go to your repository.
Go to Settings in the navigation menu.
Select Security > Secrets and variables > Actions.
Select New repository secret.
Create secrets for
AZURE_CLIENT_ID
,AZURE_TENANT_ID
, andAZURE_SUBSCRIPTION_ID
. Use these values from your Microsoft Entra application for your GitHub secrets:GitHub secret Microsoft Entra application AZURE_CLIENT_ID Application (client) ID AZURE_TENANT_ID Directory (tenant) ID AZURE_SUBSCRIPTION_ID Subscription ID Save each secret by selecting Add secret.
Add a SQL Server secret
Create a new secret in your repository for SQL_SERVER_ADMIN_PASSWORD
. This secret can be any password that meets the Azure standards for password security. You won't be able to access this password again so save it separately.
Create Azure resources
The create Azure resources workflow runs an ARM template to deploy resources to Azure. The workflow:
- Checks out source code with the Checkout action.
- Logs into Azure with the Azure Login action and gathers environment and Azure resource information.
- Deploys resources with the Azure Resource Manager Deploy action.
To run the create Azure resources workflow:
Open the
azuredeploy.yaml
file in.github/workflows
within your repository.Update the value of
AZURE_RESOURCE_GROUP
to your resource group name.Update the values of
WEB_APP_NAME
andSQL_SERVER_NAME
to your web app name and sql server name.Go to Actions and select Run workflow.
Verify that your action ran successfully by checking for a green checkmark on the Actions page.
Add container registry and SQL secrets
In the Azure portal, open your newly created Azure Container Registry in your resource group.
Go to Access keys and copy the username and password values.
Create new GitHub secrets for
ACR_USERNAME
andACR_PASSWORD
password in your repository.In the Azure portal, open your Azure SQL database. Open Connection strings and copy the value.
Create a new secret for
SQL_CONNECTION_STRING
. Replace{your_password}
with yourSQL_SERVER_ADMIN_PASSWORD
.
Build, push, and deploy your image
The build, push, and deploy workflow builds a container with the latest app changes, pushes the container to Azure Container Registry and, updates the web application staging slot to point to the latest container pushed. The workflow containers a build and deploy job:
- The build job checks out source code with the Checkout action. The job then uses the Docker login action and a custom script to authenticate with Azure Container Registry, build a container image, and deploy it to Azure Container Registry.
- The deployment job logs into Azure with the Azure Login action and gathers environment and Azure resource information. The job then updates Web App Settings with the Azure App Service Settings action and deploys to an App Service staging slot with the Azure Web Deploy action. Last, the job runs a custom script to update the SQL database and swaps staging slot to production.
To run the build, push, and deploy workflow:
Open your
build-deploy.yaml
file in.github/workflows
within your repository.Verify that the environment variables for
AZURE_RESOURCE_GROUP
andWEB_APP_NAME
match the ones inazuredeploy.yaml
.Update the
ACR_LOGIN_SERVER
value for your Azure Container Registry login server.