This is the ninth part of Building Microservice Applications with Azure Container Apps and Dapr. The topics we’ll cover are:
- Tutorial for building Microservice Applications with Azure Container Apps and Dapr – Part 1
- Deploy backend API Microservice to Azure Container Apps – Part 2
- Communication between Microservices in Azure Container Apps – Part 3
- Dapr Integration with Azure Container Apps – Part 4
- Azure Container Apps State Store With Dapr State Management API – Part 5
- Azure Container Apps Async Communication with Dapr Pub/Sub API – Part 6
- Azure Container Apps with Dapr Bindings Building Block – Part 7
- Azure Container Apps Monitoring and Observability with Application Insights – Part 8
- Continuous Deployment for Azure Container Apps using GitHub Actions – (This Post)
- Use Bicep to Deploy Dapr Microservices Apps to Azure Container Apps – Part 10
- Azure Container Apps Auto Scaling with KEDA – Part 11
- Azure Container Apps Volume Mounts using Azure Files – Part 12
- Integrate Health probes in Azure Container Apps – Part 13
Continuous Deployment for Azure Container Apps using GitHub Action
In the previous posts, you noticed that with every change in the source code on any of the 3 services, we have to build the applications locally, create a new image and push it to ACR by calling CLI command manually, and then we use another CLI command az containerapp update to create a new Revision of the subject Container App and publish it.
This will be a tedious process and might create issues if multiple developers are working on the same repository and they keep updating the remote resources manually from their machines.
To enhance this process we will rely on GitHub Actions to automate the build and deploy process for the 3 services, the process will be as the following:
- A code change is done on one of the projects, and a commit is pushed to a certain branch of our GitHub repository.
- GitHub action is triggered which updates the container image in the container registry. We will have a dedicated GitHub action for each project.
- Once the container is updated in the registry, Azure Container Apps creates a new revision based on the updated container image.
The source code for this tutorial is available on GitHub. You can check the demo application too.
Configure GitHub actions to connect to Azure
We need to allow our GitHub repository (GitHub actions) to connect to the Azure subscription and the resource group which hosts our 3 services, there are multiple ways to do this but we are going to use the Azure login action with a service principal secret approach.
To do so from the Azure CLI, run the command below, you need to replace the values of Subscription ID and Resource Group to match your deployment.
1 2 3 4 5 6 7 8 9 |
$SERVICE_PRINCIPAL_NAME="TasksTrackerSP" $SUBSCRIPTION_ID="<use your subscription id value>" $RESOURCE_GROUP="tasks-tracker-rg" az ad sp create-for-rbac ` --name "$SERVICE_PRINCIPAL_NAME" ` --role "contributor" ` --scopes "/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP" ` --sdk-auth |
After running this command, the output will be similar to the JSON below, you need to copy this JSON as we are using it in the next step.
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", "clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", "activeDirectoryEndpointUrl": "https://login.microsoftonline.com", "resourceManagerEndpointUrl": "https://management.azure.com/", "activeDirectoryGraphResourceId": "https://graph.windows.net/", "sqlManagementEndpointUrl": "https://management.core.windows.net:8443/", "galleryEndpointUrl": "https://gallery.azure.com/", "managementEndpointUrl": "https://management.core.windows.net/" } |
Add Action Secrets to GitHub Repository
Step 1: Create credentials for Azure
Now we need to create a couple of secrets that will be used by the GitHub actions, to do so, from the GitHub portal, navigate to your repository select “Settings”, select “Secrets”, then “Actions”. Click on “New Secret Repository”.
As the image below, name your secret “TASKSMANAGER_AZURE_CREDENTIALS” and paste the JSON from the previous step, you need to include the properties “clientId”, “clientSecret”, “subscriptionId”, and “tenantId”, other properties in JOSN can be eliminated.
1 2 3 4 5 6 |
{ "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", "clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx" } |
Step 2: Create credentials for Azure Container Registry
We need to create 2 more GitHub action secrets to store the ACR username and password to allow us to build, push, and pull images inside the GitHub action.
To get the username and password for ACR, run the below command in Azure CLI, you can get them from Azure Portal too.
1 |
az acr credential show -n $ACR_NAME |
As the step above, we will create new secrets named “TASKSMANAGER_REGISTRY_USERNAME” and “TASKSMANAGER_REGISTRY_PASSWORD” and you put the right values accordingly and save them. You should have 3 actions secrets as in the image below:
Create GitHub Action for Backend Web API service
We will start now defining the first GitHub action for the project named “TasksTracker.TasksManager.Backend.Api”, we will have a dedicated GitHub action for each service, so if a change happened to one of the services, there is no need to trigger action and do a re-deploy the service for the unchanged ones.
Next, create a new folder named “.github/workflows” on the root project directory and add a new file named “build-deploy-backend-api.yaml”, use the content below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
name: tasksmanager-backend-api deployment # When this action will be executed on: # Automatically trigger it when detected changes in repo push: branches: [ dev ] paths: - 'TasksTracker.TasksManager.Backend.Api/**' - '.github/workflows/build-deploy-backend-api.yaml' # Allow mannually trigger workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - name: Checkout to the branch uses: actions/checkout@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Log in to container registry uses: docker/login-action@v1 with: registry: taskstrackeracr.azurecr.io username: ${{ secrets.TASKSMANAGER_REGISTRY_USERNAME }} password: ${{ secrets.TASKSMANAGER_REGISTRY_PASSWORD }} - name: Build and push container image to registry uses: docker/build-push-action@v2 with: push: true tags: taskstrackeracr.azurecr.io/tasksmanager-backend-api:${{ github.sha }} , taskstrackeracr.azurecr.io/tasksmanager-backend-api:latest file: TasksTracker.TasksManager.Backend.Api/Dockerfile context: ./. deploy: runs-on: ubuntu-latest needs: build steps: - name: Azure Login uses: azure/login@v1 with: creds: ${{ secrets.TASKSMANAGER_AZURE_CREDENTIALS }} - name: Deploy to containerapp uses: azure/CLI@v1 with: inlineScript: | az config set extension.use_dynamic_install=yes_without_prompt az containerapp registry set -n tasksmanager-backend-api -g tasks-tracker-rg --server taskstrackeracr.azurecr.io --username ${{ secrets.TASKSMANAGER_REGISTRY_USERNAME }} --password ${{ secrets.TASKSMANAGER_REGISTRY_PASSWORD }} az containerapp update -n tasksmanager-backend-api -g tasks-tracker-rg --image taskstrackeracr.azurecr.io/tasksmanager-backend-api:${{ github.sha }} |
Let’s review what we added to this yaml file:
- Line 1: Setting the name “tasksmanager-backend-api deployment” for the GitHub action.
- Lines 4-8 Configure the action to be triggered when a change happens on the branch ‘dev’, if you are using a different branch name you can update this value.
- Lines 9 -10: Specify that any change on the files under the path “TasksTracker.TasksManager.Backend.Api” will trigger this action, this is very important to control that changes on this subject service will trigger this action, we want to avoid for example changes that happen on the UI project to trigger this action.
- Line 11: Specify that any change on the yaml file “build-deploy-backend-api.yaml” for this action will trigger the action.
- Line 14: Enabled manual trigger for the action (this might be needed to trigger the action without any change on code).
- Lines 16 -19: Specify that the latest Ubuntu agent will be used to run the action.
- Lines 20 – 40: Specify what we actually want to happen within our GitHub action (what jobs), we are going to add to our build process
- Lines 21-22: Check out our repository so our GitHub action can access it.
- Lines 24-25: Using the Builder, this action uses BuildKit under the hood through a simple Buildx action.
- Lines 27-32: Login to Azure Container Registry using the Username and Password created in GitHub actions secrets.
- Lines 34-40: Action to build Docker image and push to ACR, notice that we are creating 2 tags when pushing, one with tag “latest” and the other one will contain the “Commit SHA that triggered the workflow”.
- Lines 48-51 Login to Azure subscription using the credentials stored in GitHub action secrets.
- Lines 54- 60: Use Azure CLI to do the actual deployment/update for the Azure Container App and deploy a new revision.
Note: you need to do the same and create another 2 new GitHub actions for the project “TasksTracker.Processor.Backend.Svc” and project “TasksTracker.WebPortal.Frontend.Ui“, the GitHub action files are in the links.
With this in place, you can commit your work and notice that the GitHub action is triggered, if all is configured correctly you should see the results in the GitHub Actions workflows tab as well the Azure App Service should be updated with a new revision.
Note: Azure Container Apps has support from the Azure Portal or via Azure CLI commands “az containerapp github-action” to set up this continuous deployment, I preferred to do it manually from scratch to understand what is happening under the hood, as well with the built-in approach you need to create a GitHub PAT to allow Azure to access GitHub and setup the GitHub action workflows, another secret that you want to maintain 🙁
In the next post, we will be implementing using Bicep templates to create the entire environment, and resources from scratch, this will be useful if you want to provision a new test or staging environment for example. Stay tuned!
Will be very useful
Thanks for your comment, tomorrow I’m posting how to use Bicep to recreate the entire environment from scratch, stay tuned.
I think this is top notch blog post, as I have use both hashicorp terraform to deploy to AWS and Azure, I’m quietly confident that I can grab the learning curve here. Thanks for your valuable content and contribution
Regards Keith
Thank you Keith for your comment, glad to hear content is useful 👍 Bicep looks promising and GitHub Actions too.
Great post, help me a lot!
Thanks Joao, happy to hear this 🙌