As our use case, let's use NStore, an open source library for event sourcing in C# that runs unit tests against MongoDB and SQL Server — prerequisites that are not present in Linux Hosted Agents. Before giving up using Hosted Agents and start deploying private agents, you need to know that Docker is up and running in Hosted Agents and it can be used to bring your missing prerequisites.
Having Docker preinstalled on the Hosted Build Agent gives you a tremendous power, combined with Docker Task. If I want to run a build on a Linux Hosted Agent of NStore, here is a possible build that runs perfectly fine.
Figure 1: Simple build definition that starts a MongoDB and SQL Server instance with Docker before actually running the build.
If you examine the very first task, it is amazing how simple it is to start an MsSql instance running on your Linux box. At the end of the task's execution, you have a fully functional container running in a Hosted Agent.
Figure 2: Running MsSql as a container in Linux
You just need to remember to redirect the port (-p 1433:1433) so that you can access the SQL Server instance and the game is done.
Task number 2 uses the very same technique to run a MongoDB instance inside another Docker container instance then Task 3 is a simple Docker ps command to verify that the two containers are running correctly. As you can see from Figure 3, it is quite useful to know if the container really started correctly.
Figure 3: ps command allows for a simple dump of all containers running in the machine
You can log every container output. In Task number 4, I’m just running a logs command for the MsSql container just to verify, in case the MsSql tests are all failing, why the container did not start (like you forgot the ACCEPT_EULA, or you choose a password that was not enough complex).
Figure 4: Logging the output of the container to troubleshoot them.
Remember that if the container does not start correctly, your build will have tons of failing tests, so you really need a way to quickly understand if tests are actually failing or your container instance simply did not start (and the reason why it failed)
All subsequent tasks are standard for a .NET Core project, just dotnet restore, build, and test your solution, and upload test results in the build result so you can have a nice result of all of your tests.
Finally, to make everything flexible, you should grab connection strings for tests from environment variables. NStore uses a couple of environment variables called NSTORE_MONGODB and NSTORE_MSSQL to specify connection strings used for tests. I really want you to remember that all variables of a build are copied to environment variables during the build.
Figure 5: Configuration of test connection strings are directly stored in build variables.
As you can see from Figure 5, I used MongoDB without a password (this is an instance in Docker that will be destroyed after the build, so it is acceptable to run without a password) but you can usually configure Docker instances with start parameters. In that example, I gave SQL Server a strong password (required for the container to start).
Remember, if you have an open source project, you can build for free with Azure DevOps pipelines with minimal effort. Before giving up on using Hosted Agents, just verify whether you can have what you need with Docker.