DEV Community

Anshul Jangale
Anshul Jangale

Posted on

1 1 1

Backend Deployment on Azure App Service with Bitbucket CI/CD Pipeline

Introduction

After successfully setting up CI/CD for our frontend application, our next challenge was deploying the backend API to Azure App Service. This blog post details our approach to automating the backend deployment process using Bitbucket Pipelines and shares important Azure configuration steps that are often overlooked in tutorials.

Prerequisites

To follow along with this guide, you'll need:

  1. A Node.js backend application in a Bitbucket repository
  2. An Azure subscription
  3. An Azure App Service plan and web app
  4. Service principal credentials for Azure deployment

Backend Pipeline Configuration

Our backend deployment pipeline follows a similar structure to our frontend pipeline, with some key differences tailored to backend requirements. Here's our complete bitbucket-pipelines.yml file:

image: node:22

pipelines:
  branches:
    main:
      - step:
          name: Install
          caches:
            - node
          script:
            - echo "Installing dependencies..."
            - npm install --force

      - parallel:
          - step:
              name: Run build
              script:
                - echo "Building project..."
                - npm install --force
                - npm run build
                - apt-get update && apt-get install -y zip
                - zip -r app-$BITBUCKET_BUILD_NUMBER.zip build package.json package-lock.json
              artifacts:
                - "*.zip"

          - step:
              name: Security Scan
              script:
                - echo "Perform a security scan for sensitive data..."
                - echo "See https://bitbucket.org/product/features/pipelines/integrations#security"
                - apt-get update && apt-get install -y git-secrets
                # Example usage: git secrets --scan

      - step:
          name: Deploy to Production
          trigger: manual          
          deployment: Production
          script:
            - pipe: atlassian/azure-web-apps-deploy:1.0.1
              variables:
                AZURE_APP_ID: $AZURE_APP_ID
                AZURE_PASSWORD: $AZURE_PASSWORD
                AZURE_TENANT_ID: $AZURE_TENANT_ID
                AZURE_RESOURCE_GROUP: $AZURE_RESOURCE_GROUP
                AZURE_APP_NAME: $AZURE_APP_NAME
                ZIP_FILE: app-$BITBUCKET_BUILD_NUMBER.zip        
                DEBUG: 'true'
Enter fullscreen mode Exit fullscreen mode

Pipeline Breakdown

Let's examine each section of the pipeline:

Step 1: Installation

- step:
    name: Install
    caches:
      - node
    script:
      - echo "Installing dependencies..."
      - npm install --force
Enter fullscreen mode Exit fullscreen mode

This step installs all dependencies required for the application. The --force flag helps overcome any dependency conflicts that might arise.

Step 2: Parallel Execution

- parallel:
    - step:
        name: Run build
        script:
          - echo "Building project..."
          - npm install --force
          - npm run build
          - apt-get update && apt-get install -y zip
          - zip -r app-$BITBUCKET_BUILD_NUMBER.zip build package.json package-lock.json
        artifacts:
          - "*.zip"

    - step:
        name: Security Scan
        script:
          - echo "Perform a security scan for sensitive data..."
          - echo "See https://bitbucket.org/product/features/pipelines/integrations#security"
          - apt-get update && apt-get install -y git-secrets
          # Example usage: git secrets --scan
Enter fullscreen mode Exit fullscreen mode

This section runs two processes in parallel:

  1. Build: Compiles the Node.js application and packages it for deployment
  2. Security Scan: Checks for sensitive data in the codebase

Note that in our backend build, we're including:

  • The build directory with compiled code
  • package.json and package-lock.json files for dependency information

This is crucial for Azure App Service to correctly install and run the Node.js application.

Step 3: Deployment

- step:
    name: Deploy to Production
    trigger: manual          
    deployment: Production
    script:
      - pipe: atlassian/azure-web-apps-deploy:1.0.1
        variables:
          AZURE_APP_ID: $AZURE_APP_ID
          AZURE_PASSWORD: $AZURE_PASSWORD
          AZURE_TENANT_ID: $AZURE_TENANT_ID
          AZURE_RESOURCE_GROUP: $AZURE_RESOURCE_GROUP
          AZURE_APP_NAME: $AZURE_APP_NAME
          ZIP_FILE: app-$BITBUCKET_BUILD_NUMBER.zip        
          DEBUG: 'true'
Enter fullscreen mode Exit fullscreen mode

This step:

  • Has a manual trigger for controlled deployments
  • Uses the Atlassian Azure Web Apps Deploy pipe
  • Passes necessary Azure credentials stored as repository variables
  • Specifies the zip file created in the build step

Azure App Service Configuration

Unlike frontend deployments, backend deployments require additional configuration in Azure App Service. Here's a step-by-step guide to setting up your Azure environment for Node.js backend applications:

1. Create an App Service

  1. Log in to the Azure Portal
  2. Click on "Create a resource" > "Web App"
  3. Fill in the required details:
    • Resource Group: Choose existing or create new
    • Name: A unique name for your app
    • Publish: Code
    • Runtime stack: Node.js (version matching your application)
    • Operating System: Linux (recommended for Node.js)
    • Region: Choose appropriate region
  4. Click "Review + create" and then "Create"

2. Configure Startup Command

For Node.js applications, you need to specify how Azure should start your application:

  1. Navigate to your App Service in the Azure Portal
  2. Go to "Configuration" > "General settings"
  3. In the "Startup Command" field, enter your start command:
    • For apps using a build directory: node build/server.js
    • For apps using an express server: npm start
  4. Click "Save"

3. Configure Environment Variables

Backend applications typically require environment variables for database connections, API keys, and other sensitive information:

  1. In your App Service, go to "Configuration" > "Application settings"
  2. Click "New application setting" to add each environment variable
  3. Common variables to add:
    • NODE_ENV: Set to production
    • PORT: Usually set to 8080 (Azure will map this to the public port)
    • Database connection strings
    • API keys and secrets
    • Authentication parameters
  4. Click "Save" after adding all variables

4. Configure CORS (if needed)

If your backend API serves a frontend hosted elsewhere:

  1. In your App Service, go to "CORS"
  2. Add the domains that should be allowed to access your API
  3. Click "Save"

5. Set up Deployment Credentials

For the Bitbucket pipeline to deploy to Azure:

  1. In Azure Portal, go to Azure Active Directory
  2. Register a new application
  3. Create a client secret
  4. Assign the application appropriate permissions to your resource group
  5. Note down:
    • Application (client) ID
    • Directory (tenant) ID
    • Client secret

These values will be used as the AZURE_APP_ID, AZURE_TENANT_ID, and AZURE_PASSWORD in your Bitbucket pipeline.

6. Configure Bitbucket Repository Variables

In Bitbucket:

  1. Go to Repository settings > Repository variables
  2. Add the following variables:
    • AZURE_APP_ID: Your Azure service principal ID
    • AZURE_PASSWORD: Your Azure service principal password
    • AZURE_TENANT_ID: Your Azure tenant ID
    • AZURE_RESOURCE_GROUP: The resource group containing your App Service
    • AZURE_APP_NAME: The name of your App Service

Handling Backend-Specific Challenges

Challenge 1: Node.js Version Compatibility

Azure App Service supports specific Node.js versions. Ensure your application is compatible with the available versions in Azure.

Solution: In your Azure App Service settings, go to "Configuration" > "General settings" and select the appropriate Node.js version.

Challenge 2: Server Startup Detection

Azure App Service needs to detect when your Node.js application has successfully started.

Solution: Ensure your application listens on the port provided by the environment:

const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});
Enter fullscreen mode Exit fullscreen mode

Challenge 3: Application Logging

Troubleshooting deployment issues requires proper logging.

Solution: Enable application logging in Azure:

  1. Go to your App Service > "App Service logs"
  2. Enable "Application logging"
  3. Set the log level to "Information" or "Verbose"
  4. Enable "File System" logging
  5. Click "Save"

You can then view logs in the "Log stream" section or download them for analysis.

Testing the Deployment

After deploying, verify that:

  1. Your application is running by accessing the Azure App Service URL
  2. API endpoints are accessible and returning expected responses
  3. Environment variables are correctly loaded
  4. Your application can connect to external services (databases, etc.)
  5. Logs show no errors or warnings

Conclusion

Deploying a Node.js backend to Azure App Service using Bitbucket Pipelines provides a robust and automated deployment solution. By properly configuring both the pipeline and the Azure environment, you can ensure smooth and reliable deployments.

The key takeaways are:

  1. Include all necessary files in your deployment package
  2. Configure the correct startup command in Azure
  3. Set up environment variables for your application
  4. Configure CORS if needed
  5. Enable proper logging for troubleshooting

With this setup, your backend deployments will be consistent, reliable, and easy to manage.

AWS Q Developer image

Your AI Code Assistant

Generate and update README files, create data-flow diagrams, and keep your project fully documented. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

👋 Kindness is contagious

If this post resonated with you, feel free to hit ❤️ or leave a quick comment to share your thoughts!

Okay