This was surprisingly hard to find documented! Old Octopus blog posts weren't useful and some great blog posts were out-of-date and in some places, had mistakes that made them impossible to follow. Thankfully, I've managed to piece together a working end-to-end build alongside our traditional .Net apps.

This for .Net Core 2.2 running on IIS 10 on Windows Server 2016.

The app

The app is a simple web API style controller (which is the same as MVC in dotnet core) and there wasn't anything particular to worry about here. Just build it and commit it to source-control as normal.

Remember to create app settings for each environment, if necessary.


MS have really gone off the path with the simple and useful idea of per-environment app settings. The basic idea is that you set ASPNETCORE_ENVIRONMENT as an environment variable and this will cause it to select the correct appsettings file with some code in your Startup class. That part is good. However, when running from Visual Studio, a file called launchSettings.json will override that with "Development" whenever you run from Visual Studio! You can edit the file and remove that value if you already have your environment variables correct.

However, the tests, which are now made much easier with the WebApplicationFactory also have a similar problem due to a recent "fix" and will force "Development", even if you are running the tests on a CI server. You need to modify your code to inherit WebApplicationFactory into your own class and then override ConfigureWebHost() to call builder.UseEnvironment(environment);


If you have a recent version of TeamCity, you shouldn't need to install anything new (assuming you already have dotnet core SDK installed etc on the agent).

Your build process can be:
  1. dotnet restore
  2. dotnet build
  3. dotnet test
  4. dotnet publish
  5. Octopus push
  6. Octopus create release
In my version, I have 2 build steps so I can build the project without the solution, which also includes older netfx projects. Of course, I could have created a new solution but didn't!

The first 4 steps are as-expected. In step 5, I had to point it explicitly to the publish directory, which is bin/release/netcoreapp2.2/publish and which isn't automatically found like it appears to be in one example I saw! You can simply use something like this in the package paths box:

\YourApp\bin\Release\netcoreapp2.2\publish =>

I also chose in step 5 to publish it as a build artifact, to make it easier to browse what changed in each build.

Step 6 will be the same as other .net projects.


This was another area that wasn't well documented, although it turns out to not be very different than other types of IIS deployments, you just choose the "Deploy a Package" tasks instead of the "Deploy to IIS" task.

While setting this up, set the application pool to "No Managed Code". You can collect the package as normal from the internal feed by name (without the version number on the end) e.g. "YourApp"

IIS Web Server

Before you can run dotnet core, firstly, you need to install the .net Core Hosting Bundle which adds the various bits of magic that are not installed as part of IIS itself. You should also add an ASPNETCORE_ENVIRONMENT env variable set to a suitable value like Staging or Production and then best to restart the web server if possible to ensure things start a bit better than when you try to do it manually!

Once the Octopus job runs, it will create the site and point it to a random Octopus folder where the files are. Although you can try to deploy to a custom folder, IIS won't let you update an in-use Dotnet cor

e app so you either need to manually (or automatically) stop the app pool first, or otherwise write an
app_offline.htm file into the directory, which will cause it to shutdown the app and return the htm file instead. Obviously remove the html file once re-deployed!