In the world of CI/CD pipelines, Azure DevOps is lacking some pretty important features, in my opinion, but the interface is pleasing, and it’s not particularly expensive. Throw in the fact that it’s a one stop shop with work items, source control, builds, test plans, deploys, and package management all in one place makes it very attractive for any new project.
My latest side-project includes a DotNet Core 3.1 MVC web app, so I decided Azure DevOps would probably be a good fit. I also took a quick look at the Azure WebApps for hosting, but quickly realised the price was significantly higher than I’d pay in AWS EC2 (I might not have looked hard enough, but my quick search for a small instance size quickly showed me that I’d be paying $70+ per month in Azure, whereas in AWS I honestly don’t really notice the increase in cost from what I already have hosted there). So I decided to go with AWS for hosting, and seeing as I didn’t want to get straight down to coding, rather than messing with infra, I decided to make use of AWS Elastic Beanstalk.
Blow by blow
Follow these instructions and you should get to the point where the sample MVC web app is deploying into AWS without too much effort. Without having thought about things up front and taking time to read around some different ideas, I was up and running in a couple of hours.
1. DevOps project
Head to your Azure Portal (I’m going to assume you already have an Azure subscription) and search for, or click the link for, “Azure DevOps”.
Don’t click DevOps Projects. I haven’t used this feature, but when I started trying it seemed very coupled with Azure features – I’m not sure you could easily go that route and easily deploy to AWS.
Click the ‘My Azure DevOps Organizations’ link on the DevOps home page.
I don’t remember if I ever had to create my default organisation. If you need to, go ahead and create one, otherwise just choose the default org and click ‘New Project’. Give your new project a name and hit the ‘Create’ button.
When your new project has been created, click on the ‘Repos’ menu item, in the left nav.
This is our code repo (you can have multiple repo’s in a single project) where we’ll push our sample application to. Use the Initialize with a README or gitignore panel to get the first things into place. Now let’s create the project and get the code into the repo.
2. Sample MVC application
I’m going to use Visual Studio 2019 to create my project, but you could use VSCode or even Notepad++ – whatever it is you normally use, go for it.
With VS2019, choose to create a ASP.NET Core Web Application.
Give your project a suitable name and place it in a sensible location, then choose the template to start with.
We want to start with the MVC project containing example MVC views and controllers, so we can see something running without having to write any code. Once you’ve created your project, you should see a structure similar to this:
Hitting F5 should run the application.
Now let’s get the code into our repo.
Your Azure DevOps repo should now look something like this:
If we were building an “all singing, all dancing” pipeline, then we would want the pipeline to be able to execute against AWS with minimal interference from a human being, but the point of this exercise is to start iterating on the build as quickly as possible, so we’re going to take a short cut. Instead of this particular pipeline creating everything from scratch, we’ll create the environment up front in AWS. The AWS Toolkit for Azure DevOps Extension in the Visual Studio Market Place does all sorts, but keeping this simple, let’s create an Elastic Beanstalk environment to deploy into.
Log into the AWS Management Console and head over to IAM to create an account for Azure DevOps. For the moment, assign it the AdministratorAccess policy. Remember to save the .csv file with the Secret Key and Access Key in it.
Now head to Elastic Beanstalk and click ‘Create Application’. Give the application a sensible name and choose the ‘.NET on Windows Server’ Platform and ‘Sample application’ where appropriate.
Yes, I would prefer to deploy to Linux as well, but at the time of writing this wasn’t supported by Elastic Beanstalk. You could always choose to deploy a Docker image instead.
If you click ‘Create application’ at this point, the instance size will be a medium. To save money, we only want micro, so choose ‘Configure more options’.
You want to start off by changing the instance size in the Capacity panel.
Switch the instance type to t3.micro, or whatever else you think you want. Once you’ve saved that, check the other settings and click ‘Create environment’ in the bottom left.
Now you’ll have to wait a while for the infra to be spun up, but eventually you’ll end up with a screen looking something like this:
4. Making the connection
To make the connection to AWS, you need to start off by installing the AWS Toolkit for Azure DevOps Extension from the Visual Studio Market Place. This is what AWS have to say about the topic, and this is a direct link to the toolkit. Once installed, you’ll be able to configure a connection to AWS.
The ‘Project Settings’ link is at the bottom of the left nav. Once opened, you can click on ‘Service Connections’ and then ‘Create service connection’ in the middle of the window.
You should see the option for AWS at the top of the list. Select it and hit ‘Next’. Enter the Access Key ID and Secret Access Key of the user you created in IAM, give your connection a name and click ‘Save’.
5. Creating your pipeline
Click on ‘Pipelines’ in the left nav, and then choose ‘Create Pipeline’.
Click ‘Azure Repos Git’, at the top, and then choose your project repo.
Choose to start with a basic YAML file, then paste in the following:
# Starter pipeline # Start with a minimal pipeline that you can customize to build and deploy your code. # Add steps that build, run tests, deploy, and more: # https://aka.ms/yaml trigger: - master pool: vmImage: 'windows-latest' variables: solution: '**/*.sln' buildPlatform: 'Any CPU' buildConfiguration: 'Release' steps: - task: NuGetToolInstaller@1 - task: NuGetCommand@2 inputs: restoreSolution: '$(solution)' - task: DotNetCoreCLI@2 inputs: command: 'build' projects: '$(solution)' - task: DotNetCoreCLI@2 inputs: command: 'publish' arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)' publishWebProjects: true
Hit ‘Save and run’ and accept the commit message. If you drill into the running job, you should see some successful results ending up looking like this:
Of course, this is just a build. Nothing has been deployed yet. To do that, we have to add a final step to the pipeline. Click Pipelines > Your Pipeline > Edit, to reach the edit screen.
In the search bar on the right, type in ‘beanstalk’ and click on ‘AWS Elastic Beanstalk Deploy Application’. Enter details matching your configuration and your YAML file should be updated with something like the following:
- task: BeanstalkDeployApplication@1 inputs: awsCredentials: 'AWS Example Connection' regionName: 'eu-west-2' applicationName: 'Test App' environmentName: 'TestApp-dev' applicationType: 'aspnetCoreWindows' dotnetPublishPath: '$(build.artifactstagingdirectory)\TESTMVCCore.zip' logRequest: true logResponse: true
Yours will be slightly different:
|awsCredentials||The name you gave to the AWS connection you created earlier.|
|regionName||The region in AWS where your Beanstalk deployment is.|
|applicationName||The name you gave to your application.|
|environmentName||The name you gave the environment.|
|applicationType||aspnetCoreWindows is best for a dotnet core web app.|
|dotnetPublishPath||This is where the output of the ‘dotnet publish’ command will be place.|
Make sure this task is at the bottom of your YAML file, then click ‘Save’. Now hit ‘Run’. After a while you will hopefully see a green deploy step. If you click that step, you should see some output similar to this:
Now go back to AWS and view the details of your Elastic Beanstalk environment. You should see a link below the environment name marked ‘Go to environment’.
Click that link, and you should see your sample app running in AWS.
And that really is all there is to it!
Try making a code change in Visual Studio and pushing to the DevOps repo. Your push will automatically trigger a build and deploy into your AWS environment.
Gets us going quickly
Don’t get me wrong, this solution doesn’t have all the bells and whistles, but what it does have is an incredibly fast and inexpensive way to set yourself up for quick build cycles while you first tackle a project.
You can do a lot with Elastic Beanstalk, and perhaps you might not need to move to something else for production. You can even deploy your application as a Docker image.
Try creating an additional environment for the same application – call it ‘staging’ or ‘production’. You’re very quickly getting the type of CI/CD experience which most enterprises only dream about.
Good luck with your project!