Deploy to Linux VMs in an environment
Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020
In this quickstart, you learn how to set up an Azure DevOps pipeline for deployment to multiple Linux virtual machine (VM) resources in an environment. You can use these instructions for any app that publishes a web deployment package.
Prerequisites
- An Azure account with an active subscription. Create an account for free.
- An Azure DevOps organization and project. Sign up for Azure Pipelines.
For JavaScript or Node.js apps, at least two Linux VMs set up with Nginx on Azure.
Fork the sample code
If you already have an app in GitHub that you want to deploy, you can create a pipeline for that code.
If you are a new user, fork this repo in GitHub:
https://github.com/MicrosoftDocs/pipelines-javascript
Create an environment with Linux VMs
You can add VMs as resources within environments and target them for multi-VM deployments. The deployment history for the environment provides traceability from the VM to the commit.
Add a VM resource
In your Azure DevOps project, go to Pipelines > Environments and then select Create environment or New environment.
On the first New environment screen, add a Name and an optional Description.
Under Resource, select Virtual machines, and then select Next.
On the next New environment screen, choose Linux under Operating system.
Copy the Linux registration script. The script is the same for all the Linux VMs added to the environment.
Note
The Personal Access Token (PAT) of the signed in user is pre-inserted in the script and expires after three hours.
Select Close, and note that the new environment is created.
Run the copied script on each target VM that you want to register with the environment.
Note
If the VM already has another agent running on it, provide a unique name for agent to register with the environment.
Once the VM is registered, it appears as a resource under the Resources tab of the environment.
To copy the script again for creating more resources, for example if your PAT expires, select Add resource on the environment's page.
Add and manage tags
Tags are a way to target a specific set of VMs in an environment for deployment. There's no limit to the number of tags that you can use. Tags are limited to 256 characters each.
You can add tags or remove tags for VMs in the interactive registration script or through the UI by selecting More actions for a VM resource. For this quickstart, assign a different tag to each VM in your environment.
Define a CI build pipeline
You need a continuous integration (CI) build pipeline that publishes your web app, and a deployment script to run locally on the Linux server. Set up your CI build pipeline based on the runtime you want to use.
Important
During GitHub procedures, you might be prompted to create a GitHub service connection or be redirected to GitHub to sign in, install Azure Pipelines, or authorize Azure Pipelines. Follow the onscreen instructions to complete the process. For more information, see Access to GitHub repositories.
- In your Azure DevOps project, select Pipelines > Create Pipeline, and then select GitHub as the location of your source code.
- On the Select a repository screen, select your forked sample repository.
- On the Configure your pipeline screen, select Starter pipeline. Azure Pipelines generates a YAML file called azure-pipelines.yml for your pipeline.
- Select the dropdown caret next to Save and run, select Save, and then select Save again. The file is saved to your forked GitHub repository.
Edit the code
Select Edit, and replace the contents of the azure-pipelines.yml file with the following code. You add to this YAML in future steps.
The following code builds your Node.js project with npm.
trigger:
- main
pool:
vmImage: ubuntu-latest
stages:
- stage: Build
displayName: Build stage
jobs:
- job: Build
displayName: Build
steps:
- task: UseNode@1
inputs:
version: '16.x'
displayName: 'Install Node.js'
- script: |
npm install
npm run build --if-present
npm run test --if-present
displayName: 'npm install, build and test'
- task: ArchiveFiles@2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
artifact: drop
For more information, review the steps in Build your Node.js app with gulp for creating a build.
Run your pipeline
Select Validate and save, then select Save, select Run, and select Run again.
After your pipeline runs, verify that the job ran successfully and that you see a published artifact.
Deploy to the Linux VMs
Edit your pipeline to add the following deployment job. Replace
<environment name>
with the name of the environment you created earlier. Select specific VMs from the environment to receive the deployment by specifying the<VM tag>
that you defined for each VM.jobs: - deployment: VMDeploy displayName: Web deploy environment: name: <environment name> resourceType: VirtualMachine tags: <VM tag> # Update value for VMs to deploy to strategy:
For more information, see the complete jobs.deployment definition.
For more information about the
environment
keyword and resources targeted by a deployment job, see the jobs.deployment.environment definition.Specify either
runOnce
orrolling
as a deploymentstrategy
.runOnce
is the simplest deployment strategy. ThepreDeploy
deploy
,routeTraffic
, andpostRouteTraffic
lifecycle hooks each execute once. Then eitheron:
success
oron:
failure
executes.The following code shows a deployment job for
runOnce
:jobs: - deployment: VMDeploy displayName: Web deploy environment: name: <environment name> resourceType: VirtualMachine tags: <VM tag> strategy: runOnce: deploy: steps: - script: echo my first deployment
The following code shows a YAML snippet for the
rolling
deployment strategy, using a Java pipeline. You can update up to five targets in each iteration. ThemaxParallel
parameter specifies the number of targets that can be deployed to in parallel.The
maxParallel
selection accounts for absolute number or percentage of targets that must remain available at any time, excluding the targets being deployed to, and determines success and failure conditions during deployment.jobs: - deployment: VMDeploy displayName: web environment: name: <environment name> resourceType: VirtualMachine tags: <VM tag> strategy: rolling: maxParallel: 2 #for percentages, mention as x% preDeploy: steps: - download: current artifact: drop - script: echo initialize, cleanup, backup, install certs deploy: steps: - task: Bash@3 inputs: targetType: 'inline' script: | # Modify deployment script based on the app type echo "Starting deployment script run" sudo java -jar '$(Pipeline.Workspace)/drop/**/target/*.jar' routeTraffic: steps: - script: echo routing traffic postRouteTraffic: steps: - script: echo health check post-route traffic on: failure: steps: - script: echo Restore from backup! This is on failure success: steps: - script: echo Notify! This is on success
With each run of this job, deployment history is recorded against the environment you created and registered the VMs in.
Access pipeline traceability in environment
The environment Deployments view provides complete traceability of commits and work items and a cross-pipeline deployment history for the environment.