CI/CD is the most important part of DevOps, and I use Azure DevOps for this. To run DevOps pipeline, we need "DevOps Agent" which does various tasks, such as:
- checkout source
- compile source
- run test
- publish test
- create artifact, etc.
To successfully complete these tasks, we need all dependencies installed on the agent, and Microsoft hosted agent has quite a lot of known dependencies for many languages and platforms. You can find more info here about Microsoft hosted agents and what dependencies each agent has.
However, in some scenario, we need more granular controls and we used to use self-hosted agent, which is still valid. However, managing additional VM (or computer) is tedious task. Therefore, I use docker container to achieve the same.
See here about self-hosted agent.
I won't explain how to as I assume you already use it. I create .NET 6 console app as an example app. This is folder structure.
I created build pipeline as below.
trigger: - main pool: vmImage: ubuntu-latest steps: - script: | docker run --name $(Build.BuildNumber) -d -t mcr.microsoft.com/dotnet/sdk:6.0 docker cp $(Build.Repository.LocalPath)/ $(Build.BuildNumber):/app docker exec $(Build.BuildNumber) bash -c 'cd /app/MyDotNetProject; dotnet publish -c Release -o out' docker cp $(Build.BuildNumber):/app/MyDotNetProject/out $(Build.ArtifactStagingDirectory) displayName: 'Build in docker and export artifacts' - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)' ArtifactName: 'drop' publishLocation: 'Container'
In this yaml, I did followings:
- Pull and run the docker image to build the code. I use .NET 6 SDK image this time.
- Copy source code into running docker by using its name and path.
- Build the source and copy out the compiled assemblies.
- Publish it to pipeline artifact.
As a result, I see the output as below.
I gave a name to running container so that it's easier to interact with it. I use Build.BuildNumber but you can use any string.
I used .NET 6 SDK image this time, but this infers we can create our own docker image which contains all necessary dependencies for our build. We simply need to create such image and push it to somewhere the agent can pull and run.
As Microsoft-hosted agent will be assigned dynamically, and it won't have docker container cache, it may take time to download the image every time it runs. To save these time, self-hosted agents are useful.
In this article, I use CLI to run docker commands, but most commands can be replaced to docker task or, you can write re-usable scripts and call it. The point is we can use container as build environment inside DevOps build pipeline!