Scott Hanselman

.NET Core and Docker

June 26, '18 Comments [4] Posted in Docker | DotNetCore | Open Source
Sponsored By

If you've got Docker installed you can run a .NET Core sample quickly just like this. Try it:

docker run --rm microsoft/dotnet-samples

If your Docker for Windows is in "Windows Container mode" you can try .NET Framework (the 4.x Windows Framework) like this:

docker run --rm microsoft/dotnet-framework-samples

vs-docker-toolsI did a video last week with a write up showing how easy it is to get a containerized application into Azure AND cheaply with per-second billing.

Container images are easy to share via Docker Hub, the Docker Store, and private Docker registries, such as the Azure Container Registry. Also check out Visual Studio Tools for Docker. It all works very nicely together.

I like this quote from Richard Lander:

Imagine five or so years ago someone telling you in a job interview that they care so much about consistency that they always ship the operating system with their app. You probably wouldn’t have hired them. Yet, that’s exactly the model Docker uses!

And it's a good model! It gives you guaranteed consistency. "Containers include the application and all of its dependencies. The application executes the same code, regardless of computer, environment or cloud." It's also a good way to make sure your underlying .NET is up to date with security fixes:

Docker is a game changer for acquiring and using .NET updates. Think back to just a few years ago. You would download the latest .NET Framework as an MSI installer package on Windows and not need to download it again until we shipped the next version. Fast forward to today. We push updated container images to Docker Hub multiple times a month.

The .NET images get built using the official Docker images which is nice.

.NET images are built using official images. We build on top of Alpine, Debian, and Ubuntu official images for x64 and ARM. By using official images, we leave the cost and complexity of regularly updating operating system base images and packages like OpenSSL, for example, to the developers that are closest to those technologies. Instead, our build system is configured to automatically build, test and push .NET images whenever the official images that we use are updated. Using that approach, we’re able to offer .NET Core on multiple Linux distros at low cost and release updates to you within hours.

Here's where you can find .NET Docker Hub repos:

.NET Core repos:

.NET Framework repos:

  • microsoft/dotnet-framework – includes .NET Framework runtime and sdk images.
  • microsoft/aspnet – includes ASP.NET runtime images, for ASP.NET Web Forms and MVC, configured for IIS.
  • microsoft/wcf – includes WCF runtime images configured for IIS.
  • microsoft/iis – includes IIS on top of the Windows Server Core base image. Works for but not optimized for .NET Framework applications. The microsoft/aspnet and microsoft/wcfrepos are recommended instead for running the respective application types.

There's a few kinds of images in the microsoft/dotnet repo:

  • sdk — .NET Core SDK images, which include the .NET Core CLI, the .NET Core runtime and ASP.NET Core.
  • aspnetcore-runtime — ASP.NET Core images, which include the .NET Core runtime and ASP.NET Core.
  • runtime — .NET Core runtime images, which include the .NET Core runtime.
  • runtime-deps — .NET Core runtime dependency images, which include only the dependencies of .NET Core and not .NET Core itself. This image is intended for self-contained applications and is only offered for Linux. For Windows, you can use the operating system base image directly for self-contained applications, since all .NET Core dependencies are satisfied by it.

For example, I'll use an SDK image to build my app, but I'll use aspnetcore-runtime to ship it. No need to ship the SDK with a running app. I want to keep my image sizes as small as possible!

For me, I even made a little PowerShell script (runs on Windows or Linux) that builds and tests my Podcast site (the image tagged podcast:test) within docker. Note the volume mapping? It stores the Test Results outside the container so I can look at them later if I need to.

#!/usr/local/bin/powershell
docker build --pull --target testrunner -t podcast:test .
docker run --rm -v c:\github\hanselminutes-core\TestResults:/app/hanselminutes.core.tests/TestResults podcast:test

Pretty slick.

Results File: /app/hanselminutes.core.tests/TestResults/_898a406a7ad1_2018-06-28_22_05_04.trx

Total tests: 22. Passed: 22. Failed: 0. Skipped: 0.
Test execution time: 8.9496 Seconds

Go read up on how the .NET Core images are built, managed, and maintained. It made it easy for me to get my podcast site - once dockerized - running on .NET Core on a Raspberry Pi (ARM32).


New Sponsor! Never type an invoice again! With DocSight OCR by ActivePDF, you’ll extract data from bills, invoices, PO’s & other documents using zonal data capture technology. Achieve Digital Transformation today!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb
Friday, 29 June 2018 02:31:16 UTC
Hi Scott, As usual, A helpful post. Thanks for your years of dedication in helping us lesser souls.
Mahesh
Friday, 29 June 2018 15:29:16 UTC
I like your post. I get why you are saying it, but I think you are oversimplifying when you mention this:

Imagine five or so years ago someone telling you in a job interview that they care so much about consistency that they always ship the operating system with their app. You probably wouldn’t have hired them. Yet, that’s exactly the model Docker uses!


The goal with the container is to provide the tightest isolation of your code and the most minimal container that will still run your code. If we look at linux native containers, they tend to be much smaller than the windows containers because of how the windows vs linux containers work --> we aren't shipping the whole operating system, just the bits that are required for the application to run. The rest of the OS/Kernel is left for the base machine to deal with.

I do think you allude to that with a later comment though:
For example, I'll use an SDK image to build my app, but I'll use aspnetcore-runtime to ship it. No need to ship the SDK with a running app. I want to keep my image sizes as small as possible!
but wanted to make sure that for those who are learning about containerization, that we are being explicit so that they do follow best practices instead of starting every container with "FROM <Big OS image> "
Chris
Monday, 02 July 2018 12:51:49 UTC
Great article as always, however there are major problems with Docker and VS.net specifically that need to be addressed:

1. Running your tests in a different container build separately isn't really running your tests. It defeats the entire purpose of Docker because you could inadvertently have different environment variables or build-args etc. The tests should run with exactly the same commands that built the actual code. AND Unit Tests should always be done as part of BUILD, not a run command because with RUN you're decoupling settings which is a problem.
2. Azure App Service Container hosting isn't passing Application Settings properly as environment variables (I know you didn't cover this) despite the documentation saying otherwise.

#2 is just a bug hopefully that can be fixed. I've submitted an urgent Azure support ticket with 2 hour turn around that is now into day 3 without a phone call but here's hoping.

#1 is more severe and it's a product of issues with both Docker and VS.net

What should happen in VS.net is that all tests on a dockerized site should be run through the docker image. But this can't really happen because of the structure of the docker image in that it dumps the .sdk build version for just the runtime at the end that can't run tests (as far as I can tell).

What really needs to happen is:
On a development machine, VS.net needs to tell docker to keep both containers and run all tests on the sdk container whenever the developer requests them. (and not run them automatically on build/debug)

On VSTS an build-arg should be able to be passed so that after build, and before publish all unit tests are run. The problem with this (I've hacked this to work sort of) is that because you don't get back the container Id, you can't run docker cp to copy the test results out of the container AND there is no DOCKERFILE command to accomplish this. Docker should be updated to have a COPYOUT method that can copy out the results to the host which would be the most elegant solution. Worst case, VSTS should be updated to capture the container Id as an output variable so that you can then hack in a docker cp call. (there is now a reopened bug on this, so hopefully it will get done soon)

This should all be automatic. I shouldn't have to hack VS.net to make this work (which as far as I'm aware is impossible to do from the UI) and I shouldn't have to hack VSTS either, it should just work.


(PS your comment editor is seriously messed up in Edge. trying to use ol/ul results in blank outs of text, the text doesn't wrap etc.)
James Hancock
Wednesday, 04 July 2018 15:28:38 UTC
Thanks for the great article - especially for the quote with OS reinstall :)

There is also a great post from Andrew Lock about docker images for dotnetcore 2.1.
Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.