Scott Hanselman

ZEIT now deployments of open source ASP.NET Core web apps with Docker

March 15, '17 Comments [18] Posted in ASP.NET | Docker | DotNetCore
Sponsored By

ZEIT is a new cloud service and "now" is the name of their deployment tool. ZEIT World is their DNS service. If you head over to https://zeit.co/ you'll see a somewhat cryptic animated gif that shows how almost impossibly simple it is to deploy a web app with ZEIT now.

ZEIT works with .NET Core and ASP.NET

You can make a folder, put an index.html (for example) in it and just run "now." You'll automatically get a website with an autogenerated name and it'll be live. It's probably the fastest and easiest deploy I've ever seen. Remember when Heroku (then Azure, then literally everyone) started using git for deployment? Clearly being able to type "now" and just get a web site on the public internet was the next step. (Next someone will make "up" which will then get replaced with just pressing ENTER on an empty line! ;) )

Jokes aside, now is clean and easy. I appreciate their organizational willpower to make an elegant and simple command line tool. I suspect it's harder than it looks to keep things simple.

All of their examples use JavaScript and node.js, but they also support Docker, which means they support open source ASP.NET Core on .NET Core! But do they know they do? ;) Let's find out.

And more importantly, how easy is it? Can I take a site from concept to production in minutes? Darn tootin' I can.

First, make a quick ASP.NET Core app. I'll use the MVC template with Bootstrap.

C:\Users\scott\zeitdotnet>dotnet new mvc
Content generation time: 419.5337 ms
The template "ASP.NET Core Web App" created successfully.

I'll do a quick dotnet restore to get the packages for my project.

C:\Users\scott\zeitdotnet>dotnet restore
Restoring packages for C:\Users\scott\zeitdotnet\zeitdotnet.csproj...
Generating MSBuild file C:\Users\scott\zeitdotnet\obj\zeitdotnet.csproj.nuget.g.props.
Generating MSBuild file C:\Users\scott\zeitdotnet\obj\zeitdotnet.csproj.nuget.g.targets.
Writing lock file to disk. Path: C:\Users\scott\zeitdotnet\obj\project.assets.json
Restore completed in 2.93 sec for C:\Users\scott\zeitdotnet\zeitdotnet.csproj.

NuGet Config files used:
C:\Users\scott\AppData\Roaming\NuGet\NuGet.Config
C:\Program Files (x86)\NuGet\Config\Microsoft.VisualStudio.Offline.config

Feeds used:
https://api.nuget.org/v3/index.json
C:\LocalNuGet
C:\Program Files (x86)\Microsoft SDKs\NuGetPackages\

Now I need to add a Dockerfile. I'll make one in the root that looks like this:

FROM microsoft/aspnetcore
LABEL name="zeitdotnet"
ENTRYPOINT ["dotnet", "zeitdotnet.dll"]
ARG source=.
WORKDIR /app
EXPOSE 80
COPY $source .

Note that I could have ZEIT build my app for me if I used the aspnetcore Dockerfile that includes the .NET Core SDK, but that would not only make my deployment longer, it would also make my docker images a LOT larger. I want to include JUST the .NET Core runtime in my image, so I'll build and publish locally.

ZEIT now is going to need to see my Dockerfile, and since I want my app to include the binaries (I don't want to ship my source in the Docker image up to ZEIT) I need to mark my Dockerfile as "Content" and make sure it's copied to the publish folder when my app is built and published.

<ItemGroup>
  <None Remove="Dockerfile" />
</ItemGroup>

<ItemGroup>
  <Content Include="Dockerfile">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </Content>
</ItemGroup>

I'll add this my project's csproj file. If I was using Visual Studio, this is the same as right clicking on the Properties of the Dockerfile, setting it to Content and then "Always Copy to Output Directory."

Now I'll just build and publish to a folder with one command:

C:\Users\scott\zeitdotnet>dotnet publish
Microsoft (R) Build Engine version 15.1.548.43366
Copyright (C) Microsoft Corporation. All rights reserved.

zeitdotnet -> C:\Users\scott\zeitdotnet\bin\Debug\netcoreapp1.1\zeitdotnet.dll

And finally, from the .\bin\Debug\netcoreapp1.1\ folder I run "now." (Note that I've installed now and signed up for their service, of course.)

C:\Users\scott\zeitdotnet\bin\Debug\netcoreapp1.1\publish>now
> Deploying ~\zeitdotnet\bin\Debug\netcoreapp1.1\publish
> Ready! https://zeitdotnet-gmhcxevqkf.now.sh (copied to clipboard) [3s]
> Upload [====================] 100% 0.0s
> Sync complete (196.18kB) [2s]
> Initializing…
> Building
> ▲ docker build
> ---> 035a0a1401c3
> Removing intermediate container 289b9e4ce5d9
> Step 6 : EXPOSE 80
> ---> Running in efb817308333
> ---> fbac2aaa3039
> Removing intermediate container efb817308333
> Step 7 : COPY $source .
> ---> ff009cfc48ea
> Removing intermediate container 8d650c1867cd
> Successfully built ff009cfc48ea
> ▲ Storing image
> ▲ Deploying image
> Deployment complete!

Now has put the generated URL in my clipboard (during deployment you'll get redirected to a lovely status page) and when it's deployed I can visit my live site. But, that URL is not what I want. I want to use a custom URL.

I can take one of my domains and set it up with ZEIT World's DNS but I like DNSimple (ref).

I can add my domain as an external one after adding a TXT record to my DNS to verify I own it. Then I setup a CNAME to point my subdomain to alias.zeit.co.

C:\Users\scott\Desktop\zeitdotnet>now alias https://zeitdotnet-gmhcxevqkf.now.sh http://zeitdotnet.hanselman.com
> zeitdotnet.hanselman.com is a custom domain.
> Verifying the DNS settings for zeitdotnet.hanselman.com (see https://zeit.world for help)
> Verification OK!
> Provisioning certificate for zeitdotnet.hanselman.com
> Success! Alias created:
https://zeitdotnet.hanselman.com now points to https://zeitdotnet-gmhcxevqkf.now.sh [copied to clipboard]

And that's it. It even has a nice SSL certificate that they applied for me. It doesn't terminate to SSL all the way into the docker container's Kestral web server, but for most things that aren't banking it'll be just fine.

All in all, a lovely experience. Here's my Hello World ASP.NE Core app running in ZEIT and deployed with now  at http://zeitdotnet.hanselman.com (if you are visiting this long after this was published, this sample MAY be gone.)

I am still learning about this (this whole exercise was about 30 total minutes and asking Glenn Condron a docker question) so I'm not clear how this would work in a large multi-container deployment, but as long as your site is immutable (don't write to the container's local disk!) ZEIT says it will scale your single containers. Perhaps docker-compose support is coming?


Sponsor: Did you know VSTS can integrate closely with Octopus Deploy? Join Damian Brady and Brian A. Randell as they show you how to automate deployments from VSTS to Octopus Deploy, and demo the new VSTS Octopus Deploy dashboard widget. Register now!

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
Wednesday, 15 March 2017 21:31:41 UTC
One of the coolest services I've seen in a while!!!

I signed up for a premium account, added a `Dockerfile` to my current NancyFX project I was in the middle of working on and simply ran the `now ...` commands.

After a few minutes of wrangling DNS over at cloudflare, we were all good and deployed!

The _ONLY_ issue I've encountered is that my base `/` route gives me a 500 error, but that is indicative of the `index.html` file missing.

Thanks for sharing this awesome utility/tool! I was looking for a better and more convenient "set it and forget it" type hosting for a few small services that will be lightly used. I don't like my options for deploying containers in Azure, though that was my "goto" choice at first. Seems like an awesome compromise :D.
Wednesday, 15 March 2017 22:03:27 UTC
Fixed my missing index.html issue by including "views" folder in copyToOutput! :)
Wednesday, 15 March 2017 23:20:30 UTC
Any particular reason for the "glenn" branding on the resulting site? Is it a security issue?
Mike C
Wednesday, 15 March 2017 23:57:49 UTC
Mike C - Because Glenn Condron and I worked on it. ;)
Scott Hanselman
Thursday, 16 March 2017 08:39:22 UTC
This reminds me of a similar service from a couple of years ago called bowery.io. Looks like they aren't live anymore. But this is awesome cool! Pretty simple.
Thursday, 16 March 2017 15:38:13 UTC
I've been working on something similar to this, although not very seriously, it was more for an NDC talk than anything else. Main difference is mine requires you to have set up a Docker Swarm somewhere. https://github.com/rendlelabs/jfri
Thursday, 16 March 2017 15:57:30 UTC
This is cool @Scott, thought i'd follow the steps and try it out. Hit a hurdle in the deployment. Here's the console output

λ now
> Deploying ~\Source\Repos\zeitdotnet\bin\release\netcoreapp1.1
> Warning! Skipping file C:\Users\Matt\Source\Repos\zeitdotnet\bin\release\netcoreapp1.1\publish\refs\Microsoft.CodeAnalysis.dll (size exceeded 1MB)
> Warning! Skipping file C:\Users\Matt\Source\Repos\zeitdotnet\bin\release\netcoreapp1.1\publish\refs\Microsoft.CodeAnalysis.CSharp.dll (size exceeded 1MB)
> Warning! 2 of the files exceeded the limit for your plan.
> Please run `now upgrade` to upgrade.
> Ready! https://zeitdotnet-rcorvfekbr.now.sh (copied to clipboard) [1s]
> Upload [====================] 100% 0.0s
> Sync complete (192.17kB) [2s]
> Initializing…
> Error! The build step of your project failed. To retry, run `now --force`.


tried both Debug and Release configs, but both include the CodeAnalysis assemblies which exceed the 1MB free plan limit. Did you use a paid account with your experiment, or found some other way around this?
Matt Patterson
Thursday, 16 March 2017 18:00:25 UTC
I loved this so much I went and made an account and even ended up with a blog post of my own!

Hope this helps provide some more insight for some people: https://blog.nandotech.com/post/2017-03-16-zeit-now-deploying-dotnet-core-in-a-docker-bow/
Thursday, 16 March 2017 23:16:25 UTC
Matt, yes I paid. I will ask them about that limit.
Scott Hanselman
Friday, 17 March 2017 11:25:41 UTC
It's really great to see new startups developing more user friendly cloud hosting and deployments. I hope to see the big cloud providers follow suit and provide a much simpler 'beginners' cloud hosting solution without overwhelming the new user with thousands of options.

I looked into deploying a simple program into Azure recently as an API and was blocked by pay walls, different trial options, enter your credit card details, 'sign up for developer program' links, then after all that faff logging in and seeing a wall of options and icons...! Why is it so hard to just host a simple API?

I really think it's worth getting the hobbyist on board with new technologies as those are the people who turn up to work on Monday and talk excitedly about their side projects they hosted on the Sunday.
Mike Parker
Friday, 17 March 2017 22:53:50 UTC
m here at the software store since trying to negotiate them out of the best price list, cuz things have changed here now, they said there has been this new government inflation goods list that has affected their market here, i have been trying to talk them out for the best price we can get the v13F full package.
they sell at a different price list now and the problem is that i already initiated the program process for the phone and it has the timer notification mode that must not pass the time cuz the program has already been activated and will automatically notify the target if it gets corrupted so we must act fast here and get the gadget to complete the program process. i have tried other stores all day and its same price
yes you are getting everything delivered today, once i get this gadget now, i will be heading home to complete the process with this required tools.
im waiting for you outside here to confirm the payment once you balance up the fee so that i can complete the purchase here on time xt
cassie dennis
Saturday, 18 March 2017 06:38:46 UTC
Hi Scott,

I have followed all the steps but end up with this:


D:\dotenetprojects\netcorernd\zeitditnet\bin\Debug\netcoreapp1.1>now --force
> Deploying D:\dotenetprojects\netcorernd\zeitditnet\bin\Debug\netcoreapp1.1
> Ready! https://zeitdotnet-vfojlanefi.now.sh (copied to clipboard) [3s]
> Upload [====================] 100% 0.0s
> Sync complete (140B) [2s]
> Initializing…
> Building
> ▲ docker build
> ---> 1e13808096de
> Removing intermediate container 6b7c20ebca7a
> Step 6 : EXPOSE 80
> ---> Running in 5b0aa02f1f0e
> ---> 9609b6963b21
> Removing intermediate container 5b0aa02f1f0e
> Step 7 : COPY $source .
> ---> 0b362ad4d724
> Removing intermediate container e7eb49288d2b
> Successfully built 0b362ad4d724
> ▲ Storing image
> ▲ Deploying image
> ▲ Container started
> Did you mean to run dotnet SDK commands? Please install dotnet SDK from:
> http://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409
> ▲ Deploying image
> ▲ Container started
> Did you mean to run dotnet SDK commands? Please install dotnet SDK from:
> http://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409
> ▲ Deploying image
> ▲ Container started
> Did you mean to run dotnet SDK commands? Please install dotnet SDK from:
> http://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409
> ▲ Deploying image
> ▲ Container started
> Did you mean to run dotnet SDK commands? Please install dotnet SDK from:
> http://go.microsoft.com/fwlink/?LinkID=798306&clcid=0x409


Is there anything i did wrong?

DockeFile Content:
FROM microsoft/aspnetcore
LABEL name="zeitdotnet"
ENTRYPOINT ["dotnet", "zeitdotnet.dll"]
ARG source=.
WORKDIR /app
EXPOSE 80
COPY $source .
Imran Siddiqui
Tuesday, 21 March 2017 08:38:34 UTC
Thanks for sharing post nice one
Thursday, 23 March 2017 20:18:00 UTC
How do I add Dockerfile to my project when there is no .csprpoj file?
Evandro
Thursday, 23 March 2017 20:18:02 UTC
How do I add Dockerfile to my project when there is no .csprpoj file?
Evandro
Saturday, 25 March 2017 22:00:17 UTC
Thanks for sharing this awesome utility

velocidade
Cibelle
Wednesday, 29 March 2017 07:59:50 UTC
What about database with this service ?
Thanks for sharing this tool !
Dolu
Wednesday, 29 March 2017 20:09:50 UTC
To anybody who is reading this comment, this utility and service is amazing, use it you will see how great it is, thank you Scott.
تانک ازت
Name
E-mail (will show your gravatar icon)
Home page
 
Comment (Some html is allowed: a@href@title, b, blockquote@cite, em, i, li, ol, pre, strike, strong, sub, super, u, ul) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.
Live Comment Preview

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