Building and Deploying Container Images to Azure Container Apps with GitHub Actions

Using GitHub Actions, we can deploy new versions of our Container Apps as our images are updated

template: {
containers: [
{
name: todoApiContainerName
image: 'mcr.microsoft.com/azuredocs/containerapps-helloworld:latest'
resources: {
cpu: '0.5'
memory: '1Gi'
}
}
]
scale: {
minReplicas: 1
maxReplicas: 1
}
}

Ensuring that our GitHub action has sufficient permissions to run the workflow

az ad sp create-for-rbac --name <SERVICE_PRINCIPAL_NAME> --role "contributor" --scopes /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP_NAME> --sdk-auth
{
"clientId": "<GUID>",
"clientSecret": "<GUID>",
"subscriptionId": "<GUID>",
"tenantId": "<GUID>",
}
# Get the id of our Azure Container Registry
registryId=$(az acr show --name <registry-name> --query id --output tsv)
# Grant the 'AcrPush' role to our service principal
az role assignment create --assignee <ClientId> --scope $registryId --role AcrPush
# Grant the 'AcrPull' role to our service principal
az role assignment create --assignee <ClientId> --scope $registryId --role AcrPull

Building our container image and pushing it to Azure Container Registry

FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["BookStore.Common/BookStore.Common.csproj", "BookStore.Api/"]
COPY ["BookStore.Repository/BookStore.Repository.csproj", "BookStore.Api/"]
COPY ["BookStore.Services/BookStore.Services.csproj", "BookStore.Api/"]
COPY ["BookStore.Api/BookStore.Api.csproj", "BookStore.Api/"]
RUN dotnet restore "BookStore.Api/BookStore.Api.csproj"
COPY . .
WORKDIR "/src/BookStore.Api"
RUN dotnet build "BookStore.Api.csproj" -c Release -o /app
FROM build AS publish
RUN dotnet publish "BookStore.Api.csproj" -c Release -o /app
FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT [ "dotnet", "BookStore.Api.dll" ]
name: Build and Deploy Container Image to Azure Container Appson:
push:
paths:
- 'src/*'
workflow_dispatch:
defaults:
run:
working-directory: ./src/BookStore
jobs:
build-container-image:
runs-on: ubuntu-latest
steps:
- name: 'Checkout GitHub Action'
uses: actions/checkout@main

- name: 'Login via Azure CLI'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}

- name: 'Build and Push Image to ACR'
uses: azure/docker-login@v1
with:
login-server: ${{ secrets.REGISTRY_LOGIN_SERVER }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- run: |
docker build . -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/bookstoreapi:${{ github.sha }}
docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}/bookstoreapi:${{ github.sha }}

Deploying our container image to Azure Container Apps.

deploy-container-app:
runs-on: ubuntu-latest
needs: build-container-image
steps:
- name: 'Checkout GitHub Action'
uses: actions/checkout@main

- name: 'Login via Azure CLI'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: 'Deploy Container App'
uses: Azure/cli@v1
with:
inlineScript: |
echo "Installing containerapp extension"
az extension add --source https://workerappscliextension.blob.core.windows.net/azure-cli-extension/containerapp-0.2.0-py2.py3-none-any.whl --yes
echo "Starting Deploying"
az containerapp update -n velidabookstoreapi -g todocontainerapp-rg -i ${{ secrets.REGISTRY_LOGIN_SERVER }}/bookstoreapi:${{ github.sha }} --registry-login-server ${{ secrets.REGISTRY_LOGIN_SERVER }} --registry-username ${{ secrets.REGISTRY_USERNAME }} --registry-password ${{ secrets.REGISTRY_PASSWORD }} --debug

Alternative approach

az containerapp github-action add \
--repo-url "https://github.com/<OWNER>/<REPOSITORY_NAME>" \
--docker-file-path "./dockerfile" \
--branch <BRANCH_NAME> \
--name <CONTAINER_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--registry-url <URL_TO_CONTAINER_REGISTRY> \
--registry-username <REGISTRY_USER_NAME> \
--registry-password <REGISTRY_PASSWORD> \
--service-principal-client-id <CLIENT_ID> \
--service-principal-client-secret <CLIENT_SECRET> \
--service-principal-tenant-id <TENANT_ID> \
--token <YOUR_GITHUB_PERSONAL_ACCESS_TOKEN>

What else can we do with az containerapp commands?

az containerapp update --name $APP_NAME --resource-group $RESOURCE_GROUP --traffic-weight $CURRENT_REVISION=80,latest=20
az containerapp revision activate \
--name <REVISION_NAME> \
--app <CONTAINER_APP_NAME> \
--resource-group <RESOURCE_GROUP_NAME>

Conclusion

--

--

Customer Engineer at Microsoft working in the Fast Track for Azure team. GitHub: https://github.com/willvelida

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store