Anyone who has been (attempting) to follow .NET tooling of late will have noticed that the behaviour is changing quite dramatically, especially for the (very cool) dotnet
CLI tool. I mean, how awesome is it to just clone a repo, cd
in and then run dotnet build
?!
Wait, what? Oh, so let's update our copy of dotnet
and try out a different project:
Now many of you will be able to spot that this is a very contrived example, but read on!
Note that the rest of this tutorial is mostly using Bash (since I'm on Linux). Either use Bash for Windows, or adjust for PowerShell accordingly
The "problem"
Now I call it a "problem" because it's not a problem per se, it's just progress. As the dotnet
tooling matured, there was a parallel change from the project.json
project system back to csproj
-based MSBuild projects. There have also a been a massive number of small changes to the syntax and logic behind dotnet
.
The issue I face is that I work with a wide variety of projects that use a mix of all three tooling systems ('old' csproj
, project.json
and 'new' csproj
), and while I could keep multiple copies of the SDK installed, or rely on global.json
and various other things, I like to over-engineer things so this is obviously a problem for Docker!
Everyone knows in 2017, if you're having a problem, you just need more Docker.
The "solution"
The solution to this comes in the form of Microsoft's own official microsoft/dotnet Docker image. Once you've got Docker installed and set up, just run docker pull microsoft/dotnet
to fetch the newest dotnet
tools ready to go.
Run first, ask questions later
Now, run docker run -it --rm microsoft/dotnet
and look on in amazement as you get a clean, up-to-date, dotnet
-capable environment!
Of course, that just gets us a blank slate, so we can add -v $PWD:/app
to mount our current directory as /app
in our container.
Tag that
Now so far all we have is a nice way to get the newest dotnet
CLI, but that doesn't help us when we find a project.json
. The trick here is that Microsoft's Docker image includes a number of tags for different versions of the SDK. Pulling a specific tag of an image doesn't replace any existing images you've pulled so you can use different tags alongside each other.
This is very useful for many other things. Try being able to pull
fedora:24
andfedora:23
and run them alongside each other on a Fedora 25 machine!
So to build our project.json
project all we need to do is run using the special 1.1.0-sdk-projectjson
tag:
dotnet run -it --rm -v $PWD:/app microsoft/dotnet:1.1.0-sdk-projectjson
Now run your normal dotnet restore
-> dotnet build
chain and witness as your previously not-working project.json
is built before your eyes.
Make the leap
Ah, but now you've gone and updated your project to the new csproj
format using dotnet migrate
! What now?
Well, just swap that 1.1.0-sdk-projectjson
tag for latest
and build as before:
docker run -it --rm -v $PWD:/app microsoft/dotnet:latest
Conserve your keystrokes
But it gets pretty tiring to type in that massive command every time, right? Well, if you're on Bash, try adding a quick and dirty script like this one:
#!/usr/bin/env bash
TARGET=${2-$PWD}
echo "Starting dotnet image with tag: $1 in $TARGET"
docker run -it --rm -v $TARGET:/app microsoft/dotnet:$1
Save that somewhere in your PATH with a good name (I use dnvm
because I'm nostalgic like that) and then from your project directory:
dnvm latest
This starts a new container, mapping your current directory to /app
using the latest dotnet
tooling.
Or, to build that project.json
-based project:
dnvm 1.1.0-sdk-projectjson /tmp/json/
If you don't provide a directory as the second argument, it will use your current directory.
Getting creative
Now, you can flesh out your dnvm
script with shorthands for specific SDK versions for example, or to use the Windows Containers-powered nanoserver
tags (if you're on Windows).
Even better, you can even give specific versions, such as using the 1.0.4-sdk
tag in case you have something that was working and is no longer!
Now get out there and start building things!