DEV Community

Cover image for Deploying a React Vite App to Azure App Service Using Docker & GitHub Actions (with OIDC) πŸš€
Dimuthu Abeysinghe
Dimuthu Abeysinghe

Posted on

Deploying a React Vite App to Azure App Service Using Docker & GitHub Actions (with OIDC) πŸš€

πŸ”— 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:

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
Enter fullscreen mode Exit fullscreen mode

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;"]
Enter fullscreen mode Exit fullscreen mode

βœ” 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
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode

πŸ“Œ 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
Enter fullscreen mode Exit fullscreen mode
  • 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
Enter fullscreen mode Exit fullscreen mode

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"]
Enter fullscreen mode Exit fullscreen mode

2️⃣ Permissions (IMPORTANT for OIDC)

permissions:
  id-token: write
  contents: read
Enter fullscreen mode Exit fullscreen mode

βœ” 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
Enter fullscreen mode Exit fullscreen mode

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 }}
Enter fullscreen mode Exit fullscreen mode

What happens behind the scenes:

  1. GitHub asks for OIDC token
  2. GitHub issues short-lived token
  3. Azure verifies repository + branch
  4. Azure gives an Access Token
  5. Workflow becomes authenticated

No passwords required.

6️⃣ Login to ACR

- name: Login to ACR
  run: az acr login --name acrReactApp
Enter fullscreen mode Exit fullscreen mode

7️⃣ Build Docker Image

- name: Build Docker Image
  run: docker build -t acrreactapp.azurecr.io/viteapp:${{ github.sha }} .
Enter fullscreen mode Exit fullscreen mode

github.shaensures each build uses a unique tag.

8️⃣ Push Docker Image

- name: Push Image
  run: docker push acrreactapp.azurecr.io/viteapp:${{ github.sha }}
Enter fullscreen mode Exit fullscreen mode

9️⃣ Deploy to Azure App Service

- uses: azure/webapps-deploy@v3
  with:
    app-name: react-docker-app
    images: acrreactapp.azurecr.io/viteapp:${{ github.sha }}
Enter fullscreen mode Exit fullscreen mode

4. πŸŽ‰ Final Flow (End-to-End Overview)

GitHub β†’ Build β†’ Docker β†’ ACR β†’ Azure App Service β†’ Live Website

Full Deployment Flow:

  1. Developer pushes code β†’ main
  2. GitHub Actions starts
  3. Install & build Vite
  4. Build Docker image
  5. Login to Azure via OIDC (no passwords)
  6. Push Docker image to ACR
  7. App Service pulls the image
  8. 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)