Post

CI/CD with GitHub Actions - Build and Push Docker Images to Azure Container Registry Using Service Principal Authentication

Build Docker images with GitHub Actions and push to Azure Container Registry using secure Service Principal authentication.

Deploying modern web applications efficiently requires a streamlined CI/CD pipeline. In this post, let’s walk through setting up a GitHub Actions workflow to build Docker containers for an Angular application and push them to Azure Container Registry (ACR). We’ll use Azure Service Principal authentication to securely connect GitHub with ACR, ensuring your images are built and deployed automatically with every code update. Whether you’re containerizing your Angular app for the first time or looking to automate your deployments, this guide will help you get started with a secure and scalable workflow. Let’s implement GitHub Actions workflow to build and push image to the Azure container registry.

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
name: Build and Push Image

on:
    push: 
        branches:
            - testbranch
jobs:
    build-push-image:
        name: Build image
        runs-on: ubuntu-latest

        steps:
        - name: Checkout code
          uses: actions/checkout@v4

        - name: Setup Docker BuildX
          uses: docker/setup-buildx-action@v3

        - name: Cache Docker layers
          uses: actions/cache@v4
          with:
           
            path: /tmp/.buildx-cache
            key: ${{ runner.os }}-buildx-${{ github.sha }}
            restore-keys: |
                ${{ runner.os }}-buildx-
              
        - name: Cache NPM dependencies
          uses: actions/cache@v4
          with: 
           
            path: ~/.npm
            key: ${{ runner.os }}-npm-${{ hasFiles('**/package-lock.json')}}
            restore-keys: |
                ${{ runner.os }}-npm-
             
        - name: Login to ACR
          uses: docker/login-action@v3
          with:
              
            registry: my-azure-container-registry.io
            username: ${{ secrets.CLIENT_ID }}
            password: ${{ secrets.CLIENT_PASSWORD }}
             

        - name: Build and push image
          uses: docker/build-push-action@v6
          with:
            context: .
            file: Dockerfile
            platforms: linux/amd64
            push: true
            tags: |
             
                my-azure-container-registry.io/images:${{ github.ref_name }}
                my-azure-container-registry.io/images:${{ github.sha }}
            cache-from: type=gha
            cache-to: type=gha,mode=max
             

The key point is authentication to Azure Container Registry from GitHub Actions using Service Principal. Let’s create one.

What is a Service Principal?

A Service Principal in Azure is a security identity used by applications, services, or automation tools (like GitHub Actions) to access Azure resources securely and with limited permissions.

When to use Service Principal?

  1. CI/CD Pipelines (e.g., GitHub Actions, Azure DevOps) - Automating tasks like building/pushing Docker images, deploying apps, or managing infrastructure. Example: Pushing a container image to Azure Container Registry.

  2. Infrastructure as Code (IaC) tools (e.g., Terraform, Bicep) - Automating Azure resource provisioning without interactive login.

  3. Custom Applications/Services Accessing Azure APIs - Apps needing to talk to Azure services like Key Vault, Storage, or Cosmos DB.

  4. Automation Scripts (e.g., PowerShell, Azure CLI) - Scheduled or triggered scripts for tasks like resource cleanup, scaling, or backups.

  5. Role-Based Access Control (RBAC) Scenarios - When you want to follow least privilege and assign specific roles (e.g., ACR Push, Reader, Contributor).

  6. Multi-Tenant or Enterprise Applications - When applications need controlled access across Azure tenants or subscriptions.

Create a Service Principal

  • Login to an Azure account and go to Microsoft Entra ID.
  • In the Manage section, go to App registrations.
  • Click on New Registration and enter a meaningful name for the application (for example github-actions-app).
  • Under supported account types, specify who can use the application
  • Select Register.
  • Once the application Overview page is displayed, Application (client) ID will be displayed. This ID is needed for login action to ACR.
  • Create CLIENT_ID Secret in GitHub account and copy/paste ID displayed on the Overview page.
  • In the registered application, go to the Manage section and then Certificates and Secrets.
  • Select Client secrets tab and then select New client secret.
  • Enter secret description and set expiration range.
  • Select Add.

Write down the generated client secret value as it can be viewed immediately after creation only.

  • Create another GitHub repo secret (CLIENT_PASSWORD). At this moment, we have both needed secrets to perform login to the Azure container registry.

  • Go to Azure container registry where images should be pushed from GitHub Actions workflow.
  • Navigate to Access Control (IAM) page.
  • Click on Add -> Add role assignment.
  • Associate proper role based on contrainer registry setup.
  • Run GitHub Actions workflow and validate that image is pushed to the container registry.

Make sure that an appropriate role is assigned to the registered application. In order to check container registry setup, go to Settings → Properties page of the container registry. Two possible modes should be there: RBAC Registry + ABAC Repository Permissions and RBAC Registry Permissions. A proper role should be selected based on the selected mode. Check official documentation about Azure Container Registry Entra permissions and role assignments.

This post is licensed under CC BY 4.0 by the author.