π GitHub Repository: https://github.com/Dimuthu7/React-Azure-Deployment-Demo
Modern web applications require fast builds, lightweight containers, and secure CI/CD automation. In this guide, we will deploy a React Vite application into Azure App Service (Linux) using:
- Docker (Nginx for production)
- Azure Container Registry (ACR)
- GitHub Actions CI/CD
- Azure OIDC (OpenID Connect) β passwordless authentication
This is the best practice method recommended by Microsoft because it uses short-lived identity tokens instead of long-lived secrets.
Letβs walk through everything from creating the Vite project β writing Dockerfiles β configuring Azure β writing the GitHub Action workflow.
1. π Create the React Vite App & Docker Files
Step 1 β Create Vite App
npm create vite@latest
cd your-project
npm install
Step 2 β Create Dockerfiles
We use two Dockerfiles:
1οΈβ£ Dockerfile.dev β For running tests (optional)
When running tests in CI, the production Dockerfile wonβt work because it uses Nginx (good for static hosting but cannot run tests).
So we keep a separate dev Dockerfile.
2οΈβ£ Dockerfile (Production) β For building and running the app on Azure
Dockerfile
# ---------- Build Stage ----------
FROM node:lts-alpine AS builder
WORKDIR /app
# Copy only dependency files (faster builds via caching)
COPY package*.json ./
RUN npm install
# Copy the rest of the source code
COPY . .
# Build Vite production bundle
RUN npm run build
# ---------- Server Stage ----------
# Use Nginx to host static files
FROM nginx:stable-alpine
# Copy built files
COPY --from=builder /app/dist /usr/share/nginx/html
# Expose port 80
EXPOSE 80
# Start Nginx
CMD ["nginx", "-g", "daemon off;"]
β This builds and serves the Vite app using Nginx
β Perfect for Azure App Service (Linux) with Docker
2. β Azure Setup (ACR + App Service + OIDC)
We assume a clean Azure subscription.
Step 1 β Create Resource Group
az login
az group create --name rg-test --location eastus
-
rg-testβ Your resource group -
eastusβ Region
Step 2 β Create Azure Container Registry (ACR)
az acr create \
--resource-group rg-test \
--name acrReactApp \
--sku Basic \
--admin-enabled true
π Keep the following for GitHub Secrets:
- Login Server β
acrreactapp.azurecr.io - Username
- Password
ACR stores your Docker images.
Step 3 β Create App Service Plan
az appservice plan create \
--name vite-plan \
--resource-group rg-test \
--sku B1 \
--is-linux
-
B1β cheapest tier - MUST be Linux for Docker
Step 4 β Create the Web App (Docker)
az webapp create \
--resource-group rg-test \
--plan vite-plan \
--name react-docker-app \
--deployment-container-image-name acrreactapp.azurecr.io/viteapp:latest
The image doesn't need to exist yet β GitHub Actions will build and push it later.
Step 5 β Create Azure App Registration (for OIDC)
Azure Portal β Azure Active Directory β App registrations β New registration
- Name:
github-actions-deploy - Supported account types: Single tenant
- Redirect URI: leave empty
Save:
- Application (client) ID
- Directory (tenant) ID
Step 6 β Add Federated Credential (OIDC)
Azure Portal β App Registration β
Certificates & Secrets β Federated Credentials β Add credential
Fill the fields as follows:
| Field | Value |
|---|---|
| Provider | GitHub Actions |
| Repository | your-username/your-repo |
| Branch | main |
| Audience | api://AzureADTokenExchange |
| Name | github-actions-main |
β This enables passwordless login from GitHub to Azure.
Step 7 β Assign Azure Role
Azure Portal β Subscription β Access Control (IAM) β Add role assignment
- Role: Contributor
- Assign to: Service principal
- Choose the App Registration created above
This allows GitHub workflow to deploy resources.
Step 8 β Add GitHub Secrets
| Secret | Value |
|---|---|
| ACR_LOGIN_SERVER | acrreactapp.azurecr.io |
| ACR_USERNAME | from ACR |
| ACR_PASSWORD | from ACR |
| AZURE_CLIENT_ID | App Registration client ID |
| AZURE_TENANT_ID | Azure tenant ID |
| AZURE_SUBSCRIPTION_ID | Subscription ID |
3. π€ GitHub Actions CI/CD Workflow
Create file:
.github/workflows/deploy.yml
1οΈβ£ Trigger Workflow
on:
push:
branches: ["main"]
2οΈβ£ Permissions (IMPORTANT for OIDC)
permissions:
id-token: write
contents: read
β Enables GitHub to request OIDC token
β Required for passwordless Azure login
3οΈβ£ Checkout Code
- uses: actions/checkout@v4
4οΈβ£ Install Dependencies & Build Vite App
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
5οΈβ£ Login to Azure Using OIDC
- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
What happens behind the scenes:
- GitHub asks for OIDC token
- GitHub issues short-lived token
- Azure verifies repository + branch
- Azure gives an Access Token
- Workflow becomes authenticated
No passwords required.
6οΈβ£ Login to ACR
- name: Login to ACR
run: az acr login --name acrReactApp
7οΈβ£ Build Docker Image
- name: Build Docker Image
run: docker build -t acrreactapp.azurecr.io/viteapp:${{ github.sha }} .
github.shaensures each build uses a unique tag.
8οΈβ£ Push Docker Image
- name: Push Image
run: docker push acrreactapp.azurecr.io/viteapp:${{ github.sha }}
9οΈβ£ Deploy to Azure App Service
- uses: azure/webapps-deploy@v3
with:
app-name: react-docker-app
images: acrreactapp.azurecr.io/viteapp:${{ github.sha }}
4. π Final Flow (End-to-End Overview)
GitHub β Build β Docker β ACR β Azure App Service β Live Website
Full Deployment Flow:
- Developer pushes code β main
- GitHub Actions starts
- Install & build Vite
- Build Docker image
- Login to Azure via OIDC (no passwords)
- Push Docker image to ACR
- App Service pulls the image
- App restarts with new version
5. π Why OIDC is Better Than Passwords?
| Password/Secret-Based | OIDC Token-Based |
|---|---|
| Stored in GitHub secrets | No secrets stored |
| Risk of leaks | Zero secret exposure |
| Must rotate manually | No rotation required |
| Long-lived | Short-lived (~1 min) |
| Can be reused | Cannot be reused |
π― OIDC is more secure, modern, and recommended by Microsoft.
β Conclusion
You now have a fully automated CI/CD pipeline using:
- React + Vite
- Docker
- Azure Container Registry
- Azure App Service
- GitHub Actions
- OIDC (passwordless authentication)
This setup gives you:
β Fast builds
β Secure deployments
β Scalable hosting
β Zero manual steps


Top comments (0)