ZEIT now deployments of open source ASP.NET Core web apps with Docker
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.
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.
About Newsletter
λ 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?
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/
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.
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 .
تانک ازت
Comments are closed.
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.