23 September 2024
Before:
After:
The way Azure sets it up for you when you go through the steps of deploying a new Azure Web App service is objectively horrible. This is what Azure pushes to your repo:
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy # More GitHub Actions for Azure: https://github.com/Azure/actions name: Build and deploy Node.js app to Azure Web App on: push: branches: - main workflow_dispatch: jobs: build: runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 - name: Set up Node.js version uses: actions/setup-node@v3 with: node-version: "20.x" - uses: pnpm/action-setup@v4 with: version: 9 - name: npm install, build, and test run: | npm install npm run build --if-present - name: Zip artifact for deployment run: zip release.zip ./* -r - name: Upload artifact for deployment job uses: actions/upload-artifact@v4 with: name: node-app path: release.zip deploy: runs-on: ubuntu-latest needs: build environment: name: "Production" url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} permissions: id-token: write #This is required for requesting the JWT steps: - name: Download artifact from build job uses: actions/download-artifact@v4 with: name: node-app - name: Unzip artifact for deployment run: unzip release.zip - name: Login to Azure uses: azure/login@v2 with: client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID }} tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID }} subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID }} - name: "Deploy to Azure Web App" id: deploy-to-webapp uses: azure/webapps-deploy@v3 with: app-name: "app-name" slot-name: "Production" package: .
So what’s happening here is that we
The problem is that we’re zipping it together with node_modules
folder. So sending it and unzipping it takes a LOT of time. 🤯
I’m not sure why they recommend it this way, but after reading a bunch of poorly worded and outdated Azure guides and some short StackOverflow posts, I’ve figured out the way a Node.js app should be deployed.
Essentially we need to only send the code from GitHub to Azure and build right there. For that you don’t need to do any post-install scripts or anything, Azure App Service does it for you, here are the steps that it goes through as soon as the code reaches the service.
But it doesn’t do that by default, so you need to enable it. You do that by setting the environment variable SCM_DO_BUILD_DURING_DEPLOYMENT
to true
in Settings > Environment variables in Azure Portal.
Once we’ve done that, we now need to remove the build step from our GitHub Actions workflow and we’re done. Here is how the template looks now. 👇
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy # More GitHub Actions for Azure: https://github.com/Azure/actions name: Build and deploy Node.js app to Azure Web App on: push: branches: - main workflow_dispatch: jobs: prepare: runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 - name: Zip artifact for deployment run: zip release.zip ./* -r - name: Upload artifact for deployment job uses: actions/upload-artifact@v4 with: name: node-app path: release.zip deploy: runs-on: ubuntu-latest needs: prepare environment: name: "Production" url: ${{ steps.deploy-to-webapp.outputs.webapp-url }} permissions: id-token: write #This is required for requesting the JWT steps: - name: Download artifact from build job uses: actions/download-artifact@v4 with: name: node-app - name: Unzip artifact for deployment run: unzip release.zip - name: Login to Azure uses: azure/login@v2 with: client-id: ${{ secrets.AZUREAPPSERVICE_CLIENTID }} tenant-id: ${{ secrets.AZUREAPPSERVICE_TENANTID }} subscription-id: ${{ secrets.AZUREAPPSERVICE_SUBSCRIPTIONID }} - name: "Deploy to Azure Web App" id: deploy-to-webapp uses: azure/webapps-deploy@v3 with: app-name: "web-app" slot-name: "Production" package: .
There are also a few “gotchas” I’ve noticed when deploying to Azure Web App service:
HOST=0.0.0.0 PORT=8080
before your start script, which in my (Astro) case was node ./dist/server/entry.mjs
. You can’t pick the port. I tried. Didn’t work.20.14
is what it’s currently running in Azure as of the moment of writing this post. It was hard to find, they don’t print it in the dropdown when you select the environment when deploying the App Service. I got a few errors because the Node version wasn’t what my app was expecting 🤷♂️And most important tip: upgrade your service to paid. The whole build and deploy process is unbearably slow on a free plan. But, frankly, that’s not an Azure specific issue, that’s most of PaaS nowadays, isn’t it?
Hope that helps! 😎