On the previous post I used AWS Elastic Beanstalk to pull and run 2 dockerized Java APIs in a fully fledged application.
In this guide I will show how I used Azure DevOps release to continously deploy new versions of the APIs into AWS.
Pre-requisites
- Azure DevOps agents (I used
ubuntu-latest
pools) - An AWS account with EB (Elastic Beanstalk) access
- Setup AWS Toolkit for Microsoft Azure DevOps
IAM role
In order to allow my Azure releases to deploy new AWS Elastic Beanstalk versions, I created IAM role with the following permission policies:
AdministratorAccess-AWSElasticBeanstalk
AmazonEC2ContainerRegistryFullAccess
EC2InstanceProfileForImageBuilderECRContainerBuilds
AmazonSSMFullAccess
AmazonEC2FullAccess
AWSElasticBeanstalkMulticontainerDocker
AWSElasticBeanstalkRoleECS
Changing the pipelines to include the deployment information
In the previous post I created a deployment
folder in my solution repository, so now I changed the existing azure-pipelines.yml
to publish the deployment into a different artifact.
trigger:
- main
resources:
- repo: self
stages:
- stage: ReplaceVariables
displayName: Replace variables
jobs:
- job: ReplaceAzureVariables
displayName: Replace Azure variables
pool:
vmImage: ubuntu-latest
steps:
- task: replacetokens@5
displayName: Replace Tokens
inputs:
targetFiles: |
**/application.yml
**/application.properties
deployment/**
encoding: 'auto'
tokenPattern: 'doublebraces'
writeBOM: true
actionOnMissing: 'warn'
keepToken: false
actionOnNoFiles: 'continue'
enableTransforms: false
enableRecursion: false
useLegacyPattern: false
enableTelemetry: false
- task: CopyFiles@2
displayName: Copy deployment files
inputs:
Contents: 'deployment/**'
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- publish: $(Build.ArtifactStagingDirectory)/deployment
displayName: Publish deployment files
artifact: deployment
- task: CopyFiles@2
displayName: Copy all files
inputs:
Contents: '**'
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- publish: $(Build.ArtifactStagingDirectory)
displayName: Publish all files
artifact: drop
- stage: CustomerDockerBuildPublish
displayName: Customer API
dependsOn: ReplaceVariables
jobs:
- job: Build_and_Push
displayName: Customer - Build & Push Docker image
pool:
vmImage: ubuntu-latest
steps:
# Skip source code checkout and reuse sources
- checkout: none
# Download the artifact from the ReplaceVariables stage
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifact: drop
targetPath: '$(Build.SourcesDirectory)'
- task: Docker@2
displayName: Customer - Build Customer API Docker image
inputs:
command: build
dockerfile: './Customer.Dockerfile'
buildContext: '$(Build.SourcesDirectory)'
repository: $(CUSTOMER_DOCKER_REPOSITORY_NAME)
tags: |
$(Build.BuildNumber)
- task: ECRPushImage@1
displayName: Customer - Push Admin API Docker image
inputs:
awsCredentials: 'my-azure-service-connection'
regionName: '$(AWS_REGION)'
imageSource: 'imagename'
sourceImageName: '$(CUSTOMER_DOCKER_REPOSITORY_NAME)'
sourceImageTag: '$(Build.BuildNumber)'
pushTag: '$(Build.BuildNumber)'
repositoryName: '$(CUSTOMER_DOCKER_REPOSITORY_NAME)'
logRequest: true
logResponse: true
- stage: AdminDockerBuildPublish
displayName: Admin API
dependsOn: ReplaceVariables
jobs:
- job: Build_and_Push
displayName: Admin - Build & Push Docker image
pool:
vmImage: ubuntu-latest
steps:
# Skip source code checkout and reuse sources
- checkout: none
# Download the artifact from the ReplaceVariables stage
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifact: drop
targetPath: '$(Build.SourcesDirectory)'
- task: Docker@2
displayName: Admin - Build Admin API Docker image
inputs:
command: build
dockerfile: './Admin.Dockerfile'
buildContext: '$(Build.SourcesDirectory)'
repository: $(ADMIN_DOCKER_REPOSITORY_NAME)
tags: |
$(Build.BuildNumber)
- task: ECRPushImage@1
displayName: Admin - Push Admin API Docker image
inputs:
awsCredentials: 'my-azure-service-connection'
regionName: '$(AWS_REGION)'
imageSource: 'imagename'
sourceImageName: '$(ADMIN_DOCKER_REPOSITORY_NAME)'
sourceImageTag: '$(Build.BuildNumber)'
pushTag: '$(Build.BuildNumber)'
repositoryName: '$(ADMIN_DOCKER_REPOSITORY_NAME)'
logRequest: true
logResponse: true
Change the release trigger
Then I changed the release to be triggered when new builds from main
are successful.
Add Azure DevOps Release
Since we want the image size to be linked to the BuildNumber
I have changed the release name configuration to be:
steps:
- task: UsePythonVersion@0
displayName: 'Use Python 3.7'
inputs:
versionSpec: 3.7
- script: 'pip install --upgrade pip'
workingDirectory: '$(System.DefaultWorkingDirectory)/_MyJavaSolutionAPI/deployment'
displayName: 'Command Line Script - Install pip'
- script: 'pip install awsebcli --upgrade --user'
workingDirectory: '$(System.DefaultWorkingDirectory)/_MyJavaSolutionAPI/deployment'
displayName: 'Command Line Script- Install awsebcli '
- task: AmazonWebServices.aws-vsts-tools.AWSShellScript.AWSShellScript@1
displayName: 'AWS Shell Script - Elastic Beanstalk init'
inputs:
awsCredentials: 'my-aws-azure-service-connection'
regionName: '$(AWS_REGION)'
scriptType: inline
inlineScript: 'eb init $(AWS_BEANSTALK_ENVIRONMENT_NAME) --platform "$(AWS_PLATFORM)" --tags $(AWS_TAGS) --keyname $(AWS_BEANSTALK_KEYNAME_NAME) --region $(AWS_REGION)'
disableAutoCwd: true
workingDirectory: '$(System.DefaultWorkingDirectory)/_MyJavaSolutionAPI/deployment'
- task: AmazonWebServices.aws-vsts-tools.AWSShellScript.AWSShellScript@1
displayName: 'AWS Shell Script - Elastic Beanstalk deploy'
inputs:
awsCredentials: 'my-aws-azure-service-connection'
regionName: '$(AWS_REGION)'
scriptType: inline
inlineScript: 'eb deploy $(AWS_BEANSTALK_ENVIRONMENT_NAME) --label "$(Release.ReleaseName)" --message "$(Release.ReleaseDescription)" --process --region $(AWS_REGION)'
disableAutoCwd: true
workingDirectory: '$(System.DefaultWorkingDirectory)/_MyJavaSolutionAPI/deployment'
And with that we have a completed CI/CD pipeline in Azure DevOps
This concludes my post series "Migrating an Springboot Java API".
Creating a dockerized version of a Java 1.8 Springboot solution containing 2 APIs, then creating a CI/CD pipeline in Azure DevOps and using AWS Elastic Beanstalk to host and orchestrate the running server.
Top comments (0)