Azure App Service is actually a distributed system that orchestrates multiple components to host your web application.
Here’s how a typical deployment from GitHub Actions to Azure App Service unfolds, showing the key components and their interactions:
Imagine you’ve just pushed a change to your GitHub repository.
-
GitHub Actions Workflow Trigger: Your
.github/workflows/deploy.ymlfile, residing in your repository, is triggered by the push event. This file contains the instructions for your deployment. -
Checkout Action: The
actions/checkout@v3action pulls your repository’s code into the ephemeral runner environment. This is the raw source code you’ll be deploying. -
Build Step: A build tool (like
npm run build,mvn package, ordotnet publish) compiles your code, bundles assets, and prepares it for deployment. This might happen on the same runner or a separate build runner. -
Azure Login: The
azure/login@v1action authenticates your GitHub Actions runner with Azure using a Service Principal. This grants the runner the necessary permissions to interact with your Azure resources. -
Deployment to App Service: The
azure/webapps-deploy@v2action is the workhorse. It takes your built artifacts and deploys them to your Azure App Service instance. This is where the magic (and potential magic-breaking) happens.
Let’s see this in action with a sample workflow:
name: Deploy to Azure App Service
on:
push:
branches:
- main
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18.x'
- name: npm install and build
run: |
npm install
npm run build
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Deploy to Azure App Service
uses: azure/webapps-deploy@v2
with:
app-name: 'my-awesome-app-service-name' # Replace with your App Service name
package: 'dist' # Replace with your build output directory
In this workflow:
on: push: branches: - mainmeans this workflow runs every time you push to themainbranch.runs-on: ubuntu-latestspecifies the operating system for the runner.- The
Set up Node.jsstep ensures you have the correct Node.js version. npm installandnpm run buildprepare your Node.js application.azure/login@v1uses theAZURE_CREDENTIALSsecret (a JSON object containing your Service Principal details) to authenticate.azure/webapps-deploy@v2is configured with yourapp-nameand thepackagecontaining your built application files.
Internal Mechanics of App Service Deployment:
When azure/webapps-deploy runs, it doesn’t just copy files. It interacts with the Azure App Service platform’s deployment engine. For many deployment types (like Zip Deploy, which this action often uses), it uploads a .zip archive of your package directory to a staging slot on the App Service. The App Service then unpacks this archive into the wwwroot directory of your application. If you’re using deployment slots, it might deploy to a staging slot first, and then swap it into production.
The "package" parameter is crucial. It tells the action what to deploy. If your build process outputs files into a build folder, you’d set package: 'build'. If it’s a single .jar file, you might point to that directly. The action then zips up the contents of this specified directory.
The core of the deployment is the interaction with the Kudu service, the engine behind App Service deployments. Kudu handles the unpacking, and for certain languages (like Node.js, Python, PHP), it can also run post-deployment scripts or install dependencies based on configuration files (like package.json or requirements.txt) found in the deployed package.
What most people don’t realize is that the azure/webapps-deploy action, by default, performs a "Zip Deploy." This means it takes the directory specified by package, creates a zip archive of its contents, and uploads that archive. App Service then extracts this archive into the wwwroot folder. This is generally efficient, but it means that any files not included in that package directory (e.g., source maps if they aren’t in your build output, or other project files) will not be present on the App Service.
The next concept you’ll likely grapple with is managing environment-specific configurations for your deployed application, especially when dealing with multiple deployment slots.