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:
- A Node.js backend application in a Bitbucket repository
- An Azure subscription
- An Azure App Service plan and web app
- 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'
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
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
This section runs two processes in parallel:
- Build: Compiles the Node.js application and packages it for deployment
- 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
andpackage-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'
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
- Log in to the Azure Portal
- Click on "Create a resource" > "Web App"
- 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
- Click "Review + create" and then "Create"
2. Configure Startup Command
For Node.js applications, you need to specify how Azure should start your application:
- Navigate to your App Service in the Azure Portal
- Go to "Configuration" > "General settings"
- 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
- For apps using a build directory:
- Click "Save"
3. Configure Environment Variables
Backend applications typically require environment variables for database connections, API keys, and other sensitive information:
- In your App Service, go to "Configuration" > "Application settings"
- Click "New application setting" to add each environment variable
- Common variables to add:
-
NODE_ENV
: Set toproduction
-
PORT
: Usually set to8080
(Azure will map this to the public port) - Database connection strings
- API keys and secrets
- Authentication parameters
-
- Click "Save" after adding all variables
4. Configure CORS (if needed)
If your backend API serves a frontend hosted elsewhere:
- In your App Service, go to "CORS"
- Add the domains that should be allowed to access your API
- Click "Save"
5. Set up Deployment Credentials
For the Bitbucket pipeline to deploy to Azure:
- In Azure Portal, go to Azure Active Directory
- Register a new application
- Create a client secret
- Assign the application appropriate permissions to your resource group
- 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:
- Go to Repository settings > Repository variables
- 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}`);
});
Challenge 3: Application Logging
Troubleshooting deployment issues requires proper logging.
Solution: Enable application logging in Azure:
- Go to your App Service > "App Service logs"
- Enable "Application logging"
- Set the log level to "Information" or "Verbose"
- Enable "File System" logging
- Click "Save"
You can then view logs in the "Log stream" section or download them for analysis.
Testing the Deployment
After deploying, verify that:
- Your application is running by accessing the Azure App Service URL
- API endpoints are accessible and returning expected responses
- Environment variables are correctly loaded
- Your application can connect to external services (databases, etc.)
- 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:
- Include all necessary files in your deployment package
- Configure the correct startup command in Azure
- Set up environment variables for your application
- Configure CORS if needed
- Enable proper logging for troubleshooting
With this setup, your backend deployments will be consistent, reliable, and easy to manage.
Top comments (0)