Shipping a containerized app to the cloud doesn’t have to be complicated.
In this blog post, I’ll walk you through deploying a Dockerized application to Azure step-by-step from pushing your image to Azure Container Registry (ACR) to automating your deployments with GitHub Actions.
Whether you're building your first cloud native app or just need a quick blueprint for setting up Azure CI/CD, this walkthrough has you covered with screenshots, code snippets, and tips to avoid common pitfalls.
Prerequisites
Before starting, ensure you have the Azure CLI installed and you're logged in. Follow the installation guidehere
A GitHub repository containing your Dockerfile & FastAPI code.
Step 1. Create an Azure Container Registry (ACR)
We'll:
- Create a Container Registry.
- Push our Docker image to ACR
- Take note of the login server, username, and password
Create Container Registry
In the Azure Portal, click Create a resource > Container Registry.
Use these settings.
Subscription: Your Azure subscription
Resource group: Create or use an existing one
Registry name: Give your container a unique name
Location: Choose your region
Pricing plan: Basic
Skip Networking, Encryption, and Tags.
Click Create after "Validation passed" appears.
Push Your Image
Your ACR deployment is now created and completed we have to push our image store in local machine (VSCode) to the remote container.
Make sure you are in the folder/path that contains the image
Once deployed:
Click Go to resource.
Scroll down and select Pushing a container image
You'll see instructions like these (note: Azure provides generic hello-world example commands that we'll need to modify):
To push your FastAPI application instead of the hello-world example, use these commands modify the example commands to fit your project:
# Login to your Azure Container Registry
az acr login --name
# Build your FastAPI Docker image (if not already built)
docker build -t .
# Tag your local image with your ACR address
docker tag fastapidemo myfastapidemo.azurecr.io/fastapidemo:latest
# Push your tagged image to Azure Container Registry
docker push myfastapidemo.azurecr.io/fastapidemo:latest
Best practice: use explicit version tags (v1.0, v2025‑04‑23, etc.).
You should see an output similar to mines.
Verify your image was pushed successfully with:
az acr repository list --name --output table
You can also see it from the Azure portal.
Step 2. Create an APP Service & Web App
In this Section you will:
- Create an App Service Plan (Linux)
- Create a Web App for Containers
- Link it to ACR
An AppService is an HTTP-based service for hosting web applications, REST APIs, and mobile back ends.
A WebApp is an AppService that focuses on hosting web applications.
In Azure Portal, search App Services > Create > Web App
Basics
Every Field with an (* = required) must be filled
Use these Settings:
Resource Group: Select your resource group
Name: Create a Unique name
Publish(*): Container
Operating System(*): Linux
Region: Select your region
Pricing plan: Free F1 (to keep cost low)
Example.
Hit Next and skip for the Database page
Configure the container
Use the settings:
Image Source: Azure Container Registry
Registry: Select the ACR registry
Authentication: Managed identity
Image: fastapidemo (your image name)
Tag: latest (your image tag)
For the tag its best practice to avoid generic tags such as :latest instead use 1.O I only use latest for demonstration purposes
Hit Next
Networking
Enable public access: On
Hit Next
Monitor + secure
Enable Application Insights: No
In production its best to turn on to track and logs your apps data
Enable Defender for App Service: leave blank
Hit Next and Skip the Tags page
Review + Create -> Create
You should now see your basic web app all you have to do is verify your configurations now click Create
If you receive any failed deployments error switch to a different region and redeploy
Access & Verify Web App
On success, select Go to resource and open the Default Domain to confirm the app loads.
If you set everything up right you should see your containers page.
If you have any issues on the resource page under Deployment Center > View logs you will see where your deployment failed.
Step 3. Set Up GitHub Actions CI/CD
We will:
- Enable Deployment Center
- Generate a workflow file
- Add GitHub secrets
Enable deployment Center
In your Web App portal on the left side select Deployment > Deployment Center
If you see the red "SCM basic authentication is disabled for your app. Click here to go to your configuration settings to enable." it needs to be enabled.
Click it and under Platform settings toggle SCM Basic Auth Publishing: On
Save the changes above and continue to update the app.
Connect to GitHub
Source: Github Actions
Authorize GitHub, select repo + branch once completed fill in your repos details.
The rest of your Registry settings should auto‑populate (note the managed identity it shows).
In a new tab access your container registry.
Azure Portal > your ACR > Settings > Identity > User Assigned.
Add the user assigned managed identity you have listed in Deployment Center.
Now head on back to your deployment center
Hit the Save button up above
Our build will fail we will resolve this issue in the next.
✏️ Fix the generated workflow
Head over to your GitHub repo — you'll see a new folder named .github/workflows
.
This was automatically created by Azure Deployment Center when you enabled CI/CD.
Open the .yml
file inside (e.g., azure-webapps.yml
) — and click the ✏️ pencil icon to edit it directly in GitHub.
The code is a general-purpose template — we’ll customize it to match our actual Azure setup.
Replace the Docker login block with Azure‑based auth:
🐳 Original Build & Login Block:
You'll see something like this:
jobs:
build:
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to registry
uses: docker/login-action@v2
with:
registry: https://myfastapidemo.azurecr.io/
username: ${{ secrets.AzureAppService_ContainerUsername_dac00c4d6aa44559aceb4c95969103fb }}
password: ${{ secrets.AzureAppService_ContainerPassword_acd4866e025148088786c136581277b5 }}
- name: Build and push container image to registry
uses: docker/build-push-action@v3
with:
push: true
tags: myfastapidemo.azurecr.io/${{ secrets.AzureAppService_ContainerUsername_dac00c4d6aa44559aceb4c95969103fb }}/fastapidemo:${{ github.sha }}
file: ./Dockerfile
This login method assumes credentials for Docker Hub or a public registry — but we’re using Azure Container Registry (ACR) with Azure credentials.
✅ Replace It With:
jobs:
build:
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: 'Build and push image'
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 }}/:${{ github.sha }}
docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}//:${{ github.sha }}
This uses the Azure CLI to securely authenticate to ACR using a service principal instead of Docker username/password.
Add GitHub secrets
In this section we will be setting the AZURE_CREDENTIALS secret.
Open your terminal and run the following commands
This command shows all your active resource groups look for you resource group related to your ACR/webapp. Copy the resource group "id".
az group list
Create a service principal:
az ad sp create-for-rbac --scopes --role Contributor --sdk-auth
example
az ad sp create-for-rbac \
--scopes /subscriptions/88888839283023/resourceGroups/FastApI \
--role Contributor \
--sdk-auth
Your output will look similar to:
{
"clientId": "xxxx6ddc-xxxx-xxxx-xxx-ef78a99dxxxx",
"clientSecret": "xxxx79dc-xxxx-xxxx-xxxx-aaaaaec5xxxx",
"subscriptionId": "aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e",
"tenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee",
"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/"
}
Save the JSON output because it's used in a later step.
Take note of the clientId, which you need to update the service principal in the next section.
Now we need to update the service principal to allow ACR to push and pull
Lets get our registry name.
az acr list --query "[].{Name:name}" --output table
Get the resource ID of your container registry. Replace and .
registryId=$(az acr show --name --resource-group --query id --output tsv)
Assign AcrPush to the service principal, which gives push and pull access to the registry. Substitute the client ID of your service principal:
az role assignment create --assignee --scope $registryId --role AcrPush
Save the credentials to your GitHub repo, go to your repository Settings under Security > Secrets and variables > Actions > New repository secret.
Add the following secrets:
AZURE_CREDENTIALS paste full JSON including "{}"
For enterprise-grade setups, consider using Workload Identity Federation or certificate-based service principals to avoid storing long-term secrets.
Test the Pipeline
Lets make a change to our code to see if any changes made in our code will build and deploy and show on our Azure app service.
Any changes to the repo will automatically trigger our GitHub action to Build and deploy to Azure.
For me I will be making the changes to my fastapi code from {"Welcome": "To Azure"} to {"Novice": "To Azure"} and commit the code.
After you have made the changes wait for your actions to deploy than check back to you app service domain.
As you can see the change have been reflected Automatically.
Cleanup resources
Now that we have deployed everything we need to cleanup the resources to not accrue charges.
Delete the resource group to stop charges:
az group delete --name ExampleResourceGroup -y
Replace ExampleResourceGroup with your resource group name you can locate your resource groups using
az group list
Or remove it via Azure Portal.
Search for Resource groups in the azure portal and locate the resource group you create and select it and just hit Delete resource group
Conclusion
If you followed along, you now have:
- A Docker image safely stored in Azure Container Registry (ACR)
- A FastAPI web app running live on Azure App Service
- An end‑to‑end CI/CD pipeline powered by GitHub Actions that redeploys on every push