06 - CI/CD with GitHub Actions¶
Automate build and deployment so every commit can produce a new Container App revision. This tutorial uses GitHub Actions, ACR, and Azure Container Apps deploy actions.
Infrastructure Context
Service: Container Apps (Consumption) | Network: VNet integrated | VNet: ✅
This tutorial assumes a production-ready Container Apps deployment with a custom VNet, ACR with managed identity pull, and private endpoints for backend services.
flowchart TD
INET[Internet] -->|HTTPS| CA["Container App\nConsumption\nLinux Node 18 LTS"]
subgraph VNET["VNet 10.0.0.0/16"]
subgraph ENV_SUB["Environment Subnet 10.0.0.0/23\nDelegation: Microsoft.App/environments"]
CAE[Container Apps Environment]
CA
end
subgraph PE_SUB["Private Endpoint Subnet 10.0.2.0/24"]
PE_ACR[PE: ACR]
PE_KV[PE: Key Vault]
PE_ST[PE: Storage]
end
end
PE_ACR --> ACR[Azure Container Registry]
PE_KV --> KV[Key Vault]
PE_ST --> ST[Storage Account]
subgraph DNS[Private DNS Zones]
DNS_ACR[privatelink.azurecr.io]
DNS_KV[privatelink.vaultcore.azure.net]
DNS_ST[privatelink.blob.core.windows.net]
end
PE_ACR -.-> DNS_ACR
PE_KV -.-> DNS_KV
PE_ST -.-> DNS_ST
CA -.->|System-Assigned MI| ENTRA[Microsoft Entra ID]
CAE --> LOG[Log Analytics]
CA --> AI[Application Insights]
style CA fill:#107c10,color:#fff
style VNET fill:#E8F5E9,stroke:#4CAF50
style DNS fill:#E3F2FD CI/CD Pipeline Flow¶
graph LR
PUSH[Push to main] --> GHA[GitHub Actions]
GHA --> ACR[ACR Build]
ACR --> DEPLOY[Deploy Revision]
DEPLOY --> HEALTH[Health Check] Prerequisites¶
- Completed 05 - Infrastructure as Code with Bicep
- GitHub repository with Actions enabled
- Azure service principal stored as GitHub secret
Never expose credentials in workflow logs
Keep all credential material in GitHub Secrets and avoid printing secret-derived values in shell steps. Use masked placeholders in documentation and workflow examples.
Step-by-step¶
-
Configure repository variables and secrets
- Variables:
RESOURCE_GROUP,APP_NAME,ACR_NAME - Secrets:
AZURE_CREDENTIALS,REGISTRY_USERNAME,REGISTRY_PASSWORD
Example
AZURE_CREDENTIALSJSON (masked): - Variables:
-
Create workflow file
Create a file at
.github/workflows/deploy.ymlin your repository:name: Deploy Node.js App to ACA on: push: branches: [ main ] paths: - 'apps/nodejs/**' - '.github/workflows/deploy.yml' jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Azure Login uses: azure/login@v2 with: creds: ${{ secrets.AZURE_CREDENTIALS }} - name: ACR Login uses: azure/docker-login@v2 with: login-server: ${{ vars.ACR_NAME }}.azurecr.io username: ${{ secrets.REGISTRY_USERNAME }} password: ${{ secrets.REGISTRY_PASSWORD }} - name: Build and push image run: | docker build --tag ${{ vars.ACR_NAME }}.azurecr.io/${{ vars.APP_NAME }}:${{ github.sha }} ./apps/nodejs docker push ${{ vars.ACR_NAME }}.azurecr.io/${{ vars.APP_NAME }}:${{ github.sha }} - name: Deploy Container App uses: azure/container-apps-deploy-action@v1 with: imageToDeploy: ${{ vars.ACR_NAME }}.azurecr.io/${{ vars.APP_NAME }}:${{ github.sha }} resourceGroup: ${{ vars.RESOURCE_GROUP }} containerAppName: ${{ vars.APP_NAME }} -
Validate rollout behavior
- Trigger workflow from a commit to
main. - Confirm a new revision was created.
- Confirm traffic moved to healthy revision.
- Trigger workflow from a commit to
Node.js Specific CI Tips¶
- Run Tests: Add a step to run
npm testbefore building the Docker image. - Security Audit: Use
npm auditto check for known vulnerabilities in your dependencies. - Linting: Run
npm run lintto ensure code quality before deployment.
- name: Install dependencies
run: npm install
working-directory: ./apps/nodejs
- name: Run tests
run: npm test
working-directory: ./apps/nodejs
Advanced Topics¶
- Implement multi-environment pipelines (dev -> staging -> prod) with approval gates.
- Use GitHub environments to manage secrets and variables for different stages.
- Integrate with Azure Load Testing to validate performance after deployment.
Use immutable image tags in pipelines
Prefer commit SHA or release-based tags for image versions. Immutable tags make revision-to-commit tracing straightforward during incident response.