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.
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.
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:\Program Files (x86)\NuGet\Config\Microsoft.VisualStudio.Offline.config
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:
ENTRYPOINT ["dotnet", "zeitdotnet.dll"]
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:
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.)
> 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]
> ▲ 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!