Scott Hanselman

Publishing an ASP.NET 5 app to Docker on Linux with Visual Studio

May 27, 2015 Comment on this post [19] Posted in ASP.NET | Docker | Open Source
Sponsored By

Docker Apps are mostly portableIt's early days, but this is a nice preview of the possibilities of things to come. I often use LEGO bricks in the way of an analogy when talking about software systems. I like the idea of choice, flexibility, and plug-ability. Choosing your language, operating system, deployment method and style, etc are all important.

There is a preview of an extension for Visual Studio 2015 (the release candidate at the time of this writing) that adds Docker support. If you have VS2015 RC you can get the Docker Extension here. You can certainly manage things from the command line, but I think as you go through this post you'll appreciate the convenience of this extension.

NOTE: It's also worth pointing out that there is a Windows client command line for Docker as well. You can "choco install docker" and read about it here.

The Brief What's Docker Explanation

If you aren't familiar with Docker, here's the super basics.

  • Virtual Machines: You likely know what a virtual machine is. It's the whole operating system, the whole computer, virtualized. If you have a 10 megabyte app you want to run, you may end up putting it in a 10 gigabyte virtual machine and carrying it around. That gives great security and isolation as your app is all alone on its own private VM, but it's a little overkill. Now you want to deploy 100 apps, and you've got space, CPU, and other things to think about. VMs also start slow and have to be actively maintained.
  • Docker/Linux Containers (and Windows containers "Docker for Windows Server"): Docker containers are sandboxes running on the same OS kernel. They are easy to deploy and start fast.  As a side effect of running on the same kernel, containers let you share most of that 10 gigabytes (as an example number) of support software between lots of apps, giving you less isolation but also using a LOT fewer resources. Containers start fast and the underlying shared resources are what's maintained and kept up to date.

Docker also is a way to package up an app and push it out in a reliable and reproducible way. So you can say that Docker is a technology, but also a philosophy and a process.

Docker will work on Windows and Linux

Docker and Visual Studio

Once you have the Docker for Visual Studio 2015 extension (preview) installed, go ahead and make an ASP.NET 5 app. Right click the project and hit Publish.

Publishing to Docker from Visual Studio

Note the Docker Containers section that's been added? You still have PAAS (Platform as a Service) and can also publish to VMs within Azure as well. Select Docker and you'll be here:

Selecting a Docker VM

We'll make a new VM to host our Docker stuff. This VM will have be the host for our containers. Today it'll be an Ubuntu LTS VM. Note that the dialog includes all the setup for Docker, ports, certs, etc. I could use existing VMs, of course.

Making a Docker VM

If you don't have a VM, then the initial create takes a while (5-10 min or more) so hang back. If you already have one, or the one you created is ready, then march on.

Visual Studio put in all our Docker details

Make special note of the Dockerfile option. You'll usually want to select your own manually created Dockerfile, assuming you're doing more than just a Hello World like I am.

The ASP.NET Dockerfile is up on GitHub: https://github.com/aspnet/aspnet-docker and in the Docker registry: https://registry.hub.docker.com/u/microsoft/aspnet/

In the build window you'll see lots of docker-related output. Here's a snipped version for flavor.

VERBOSE: Replacing tokens in Dockerfile: C:\Users\Scott\AppData\Local\Temp\PublishTemp\approot\src\WebApplication6\Properties\PublishProfiles\Dockerfile
VERBOSE: Package output path: C:\Users\Scott\AppData\Local\Temp\PublishTemp
VERBOSE: DockerHost: tcp://hanseldocker.cloudapp.net:2376
VERBOSE: DockerImageName: webapplication6
VERBOSE: DockerPublishHostPort: 80
VERBOSE: DockerPublishContainerPort: 80
VERBOSE: DockerAuthOptions: --tls
VERBOSE: DockerAppType: Web
VERBOSE: DockerBuildOnly: False
VERBOSE: DockerRemoveConflictingContainers: True
VERBOSE: LaunchSiteAfterPublish: True
VERBOSE: SiteUrlToLaunchAfterPublish:
VERBOSE: Querying for conflicting containers which has the same port mapped to the host...
Executing command [docker --tls -H tcp://hanseldocker.cloudapp.net:2376 ps -a | select-string -pattern ":80->" | foreach { Write-Output $_.ToString().split()[0] }]
VERBOSE: Building Docker image: webapplication6
Executing command [docker --tls -H tcp://hanseldocker.cloudapp.net:2376 build -t webapplication6 -f "C:\Users\Scott\AppData\Local\Temp\PublishTemp\approot\src\WebApplication6\Properties\PublishProfiles\Dockerfile" "C:\Users\Scott\AppData\Local\Temp\PublishTemp"]
VERBOSE: time="2015-05-27T10:59:06-07:00" level=warning msg="SECURITY WARNING: You are building a Docker image from Windows against a Linux Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories."
VERBOSE: Sending build context to Docker daemon 28.01 MB
VERBOSE: Step 0 : FROM microsoft/aspnet:vs-1.0.0-beta4
VERBOSE: vs-1.0.0-beta4: Pulling from microsoft/aspnet
VERBOSE: e5c30fef7918: Pulling fs layer
VERBOSE: e5c30fef7918: Pull complete
VERBOSE: e5c30fef7918: Already exists
VERBOSE: Digest: sha256:27fbe2377b5d4e66c4aaf3c984ef03d22afbfee3d4e78e10ff38cac7ff162d2e
VERBOSE: Status: Downloaded newer image for microsoft/aspnet:vs-1.0.0-beta4
VERBOSE: ---> e5c30fef7918
VERBOSE: Step 1 : ADD . /app
VERBOSE: ---> cf1f788321b3
VERBOSE: Removing intermediate container dd345cdcc5d9
VERBOSE: Step 2 : WORKDIR /app/approot/src/WebApplication6
VERBOSE: ---> Running in f22027140233
VERBOSE: ---> 7eabc0da4645
VERBOSE: Removing intermediate container f22027140233
VERBOSE: Step 3 : ENTRYPOINT dnx . Kestrel --server.urls http://localhost:80
VERBOSE: ---> Running in 4810324d32a5
VERBOSE: ---> e0a7ad38eb34
VERBOSE: Removing intermediate container 4810324d32a5
VERBOSE: Successfully built e0a7ad38eb34
The Docker image "webapplication6" was created successfully.
VERBOSE: Starting Docker container: webapplication6
Executing command [docker --tls -H tcp://hanseldocker.cloudapp.net:2376 run -t -d -p 80:80 webapplication6]
Docker container started with ID: 6d4820044df200e87f08cb5becbec879d1b58fcab73145ca3aa99a424c162054
To see standard output from your application, open a command line window and execute the following command:
docker --tls -H tcp://hanseldocker.cloudapp.net:2376 logs --follow 6d4820044df200e87f08cb5becbec879d1b58fcab73145ca3aa99a424c162054
VERBOSE: received -1-byte response of content type text/html; charset=utf-8
Executing command [Start-Process -FilePath "http://hanseldocker.cloudapp.net/"]
Publish completed successfully.

The interesting parts are the calls to dnx (the .NET Execution host), the warning that I started on Windows and I'm going to Linux, as well as the fact that we're using the "microsoft/aspnet" docker image.

ASP.NET in a Linux Docker Container

In my example, I had VS and the extension make my certificates. If I want to connect to this instance from the Windows Docker command line, I need to either pass those certs in, or set an env var. Here I'm running "ps" to see the remote docker containers in this Azure Linux VM. The Docker client looks in %USERPROFILE%\.docker for certs., so you just need to set DOCKER_HOST or pass it in like this.

C:\>docker --tls -H=tcp://hanseldocker.cloudapp.net:2376 ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d4820044df2 webapplication6:latest "dnx . Kestrel --ser 58 minutes ago Up 58 minutes 0.0.0.0:80->80/tcp silly_poincare

It worked great. Also be sure to explore the PublishProfiles folder that gets created in your Visual Studio project under "Properties." A PowerShell script and a Shell script get created in that folder that you can use to publish your app from the command line. For example:

.\hanseldocker-Docker-publish.ps1 -packOutput $env:USERPROFILE\AppData\Local\Temp\PublishTemp -pubxmlFile .\hanseldocker-Docker.pubxml

or from Linux:

cd ProjectFolder (like WebApplication/src/WebApplication)
source dnvm.sh
dnu restore --no-cache
mkdir ~/Temp
dnu publish . --out ~/Temp/ --wwwroot-out "wwwroot" --quiet
cd Properties/PublishProfiles
chmod +x ./Docker-publish.sh
./Docker-publish.sh ./Docker.pubxml ~/Temp/

I'm looking forward a cross-platform cross-tools choice-filled future. Finally, there's a great 7 part video series here called "Docker for .NET Developers" that you should check out on Channel 9.


Sponsor: Big thanks to Atalasoft for sponsoring the blog and feed this week! If your company works with documents, definitely check out Atalasoft's developer tools for web & mobile viewing, capture, and transformation. They've got free trials and a remarkable support team, too.

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 bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service
May 28, 2015 5:09
Can the Dockers produced by the Visual Studio plugin by published to platforms other than Azure? e.g AWS. If not is it able to just dump out a local image that could then be loaded to wherever desired?
May 28, 2015 5:32
I don't understand docker I like the idea but it looks like the docker image is tied to host os image. I am sure I am missing some part of the puzzel. I was hoping to run dnx as a amazon beanstalk worker.
May 28, 2015 6:59
Very helpful. Thank you.
May 28, 2015 10:28
@Rob - Yes, the Docker image is 100% portable to either on-prem or other cloud vendors. It can go anywhere that you can setup a Linux Docker Host (ex: supported operating systems that can run Docker). In addition, all the tooling that Visual Studio provides is *fully* scripted, meaning that even though Scott when through the UI wizard, there is an included PowerShell and Bash script to do everything completely automated without Visual Studio as well.
May 28, 2015 10:38
@Aaron - It can definitely be confusing once you first start working with Docker. There are really two parts, the Docker Host (Windows or Linux OS's, with Windows support coming soon), and the container image, which can be Ubuntu, Debian, etc. You can run a Debian container on top of an Ubuntu Docker Host for example, but all containers run on top of a host OS. You can find a list of available container images at hub.docker.com
May 28, 2015 11:20
This is really cool. My vote is for a MySql connector so that my mac-based team members can have a docker-based dev setup that is pretty much like the visual studio F5 experience with localdb.
May 28, 2015 15:10
@Aaron - Docker containers run on the host's kernel, but can be based on a completely different distro. For example, you can run an Ubuntu container on a Fedora host, or vice versa. Barring the occasional issue with Docker<->Host compatibility, once you've got your image running on one Linux host, it should run on any other Linux host.
May 28, 2015 18:16
@Mark But can you run a Windows container on a Fedora host? Or a Fedora container on a Windows host? Basically my question is "how portable is a Docker container?"
May 28, 2015 18:47
@Scott & @Dan. Thank you for this post. I really like this.
I had an issue creating a Linux VM based on the tutorial. After the VM is created an error is being thrown on installing the Docker Host to the VM
Here's the error I'm getting when trying to create a Linux VM with Docker from VS 2015.

There was an error applying the docker extension to the virtual machine. could not load file or assembly 'system.management.automation, version=3.0.0.0, culture=neutral, publickeytoken=31bf3856ad364e35' or one of its dependencies. the system cannot find the file specified.

Thanks, Blerim
May 28, 2015 22:10
@Mason - To your question, the container has to have the same base OS (Linux) as the host VM (Linux). You can not mix-and-match Windows container with Linux Hosts or vice versa.

While the container isn't portable across hosts, remember an ASP.NET app is, so you can do a Docker Build, include your app and just change the Dockerfile from a Windows image to a Linux image and your app is portable, so long as you are on .NET Core. As you can imagine, if the .NET Fx libraries you are using aren't portable between Linux and Windows, your app won't be portable.

Hope this helps!
-Dan
May 28, 2015 22:50
@Dan Thanks for the explanation, that clears up the confusion in my mind. So if I was an Independent Software Vendor providing an app via Docker, I'd need to provide both a Linux version and a Windows version. But with ASP.NET 5 and .NET Core, that should be easy to do since it's cross platform. Got it.
May 29, 2015 1:30
@Blerim - That looks like an issue with the Azure Docker extension. Can you email me at dan-dot-Fernandez-at-Microsoft-dot-com? The key thing I'd want to know is what host OS you did this on, whether you created the VM from Visual Studio, and if it's happening consistently.

Cheers,
-Dan
June 08, 2015 0:00
@scott & @dan
Does anyone has information on WindowsDocker (daemon)?
Is it available even in preview?
TJ
June 08, 2015 14:36
Hey,
First of all, you're great.
I need your help. I have just installed your Lost app for Windows Phone. And I'm working on an application where I need to access the background area of LockScreen, I didn't find any solution for this. And Second problem is I am not able to set the BitmapImage as LockScreen background.

Would be great if you help me. :)


-Krunal
June 13, 2015 0:21
@TJ - No, Windows Server with Docker container support hasn't released yet. When it will, we'll definitely make sure to plug it :)
June 18, 2015 16:35
Thanks a lot for the article. Loved your site!!
June 20, 2015 22:24
Thanks for the nice post.
Can we have 2 AspNet5Apps (2 different docker images) to run on SAME Docker enabled VM side by side without using different ports?

For instance the docker deamon being tcp://XYZ.cloudapp.net:2373And one app to be: http://Xapp.cloudapp.net and the other http://Yapp.cloudapp.net

Thanks again
July 03, 2015 3:56
Thanks! This helped me actually get it working. I was running beta6 preview (latest unstable) and it was publishing successfully, but not running with a dnu packages error. I tried rolling back to beta5 (current stable) and it still failed. Finally, I realized that both beta5 and beta6 didn't have "coreclr" runtime options, so it was obvious to me that ASP.NET 'probably won't run on Linux without coreclr support'. So, I rolled further back to beta4 (and confirmed with your post), republished and it worked!

Now, that I have an ASP.NET 5 app that runs on Linux and Windows, time to hook-up the VS Code so that devs can contribute on any platform and also get it to (hopefully) deploy to AWS Docker environment and run.

In the end, the ability to contribute to a .NET app on any platform including running it and to deploy on 'any' platform as well as any cloud with Docker virtual support... amazing! ... yes, yes Azure is great and all, but cloud agnostic will really help the adoption of .NET in organizations where 'platform agnostic' and now 'cloud agnostic' seem to be important. ;)
July 09, 2015 12:44
Thanks a lot for this.

whatsapp plus apk free download

Comments are closed.

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