A very good question - my goal was to get some sort of .Net core application up and running in Cloud Foundry. As part of my development plans I want to increase my skills in programming in languages like .Net and Java.
While I have started to learn .Net using a number of tutorials (I’m lucky Pivotal give me access to Safaribooks and Pluralsight for my development needs) I started to think how can I quickly demo .Net and Cloud Foundry?
To do this I want to quickly create a web application in front of peoples eyes to reduce the chance they think I am using some kind of smoke and/or mirror. After a little bit of investigation I cam across the ability on my Mac to use the dotnet
CLI. The result is a being able to create a boilerplate template;
$ dotnet new -h
Usage: new [options]
Options:
-h, --help Displays help for this command.
-l, --list Lists templates containing the specified name. If no name is specified, lists all templates.
-n, --name The name for the output being created. If no name is specified, the name of the current directory is used.
-o, --output Location to place the generated output.
-i, --install Installs a source or a template pack.
-u, --uninstall Uninstalls a source or a template pack.
--type Filters templates based on available types. Predefined values are "project", "item" or "other".
--force Forces content to be generated even if it would change existing files.
-lang, --language Specifies the language of the template to create.
Usage: new [options]
Options:
-h, --help Displays help for this command.
-l, --list Lists templates containing the specified name. If no name is specified, lists all templates.
-n, --name The name for the output being created. If no name is specified, the name of the current directory is used.
-o, --output Location to place the generated output.
-i, --install Installs a source or a template pack.
-u, --uninstall Uninstalls a source or a template pack.
--type Filters templates based on available types. Predefined values are "project", "item" or "other".
--force Forces content to be generated even if it would change existing files.
-lang, --language Specifies the language of the template to create.
Templates Short Name Language Tags
--------------------------------------------------------------------------------------------------------
Console Application console [C#], F#, VB Common/Console
Class library classlib [C#], F#, VB Common/Library
Unit Test Project mstest [C#], F#, VB Test/MSTest
xUnit Test Project xunit [C#], F#, VB Test/xUnit
ASP.NET Core Empty web [C#], F# Web/Empty
ASP.NET Core Web App (Model-View-Controller) mvc [C#], F# Web/MVC
ASP.NET Core Web App razor [C#] Web/MVC/Razor Pages
ASP.NET Core with Angular angular [C#] Web/MVC/SPA
ASP.NET Core with React.js react [C#] Web/MVC/SPA
ASP.NET Core with React.js and Redux reactredux [C#] Web/MVC/SPA
ASP.NET Core Web API webapi [C#], F# Web/WebAPI
global.json file globaljson Config
NuGet Config nugetconfig Config
Web Config webconfig Config
Solution File sln Solution
Razor Page page Web/ASP.NET
MVC ViewImports viewimports Web/ASP.NET
MVC ViewStart viewstart Web/ASP.NET
Examples:
dotnet new mvc --auth Individual
dotnet new web
dotnet new --help
Looking at the output from the help flag we can see templates like MVC/web/razor/angular etc. As a result we can very quickly get a angular web application example created.
$ dotnet new razor
The template "ASP.NET Core Web App" was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/template-3pn for details.
Processing post-creation actions...
Running 'dotnet restore' on /Users/redwards/workspace/customers/demo-zone/razor-demo/razor-demo.csproj...
Restoring packages for /Users/redwards/workspace/customers/demo-zone/razor-demo/razor-demo.csproj...
Restore completed in 60.93 ms for /Users/redwards/workspace/customers/demo-zone/razor-demo/razor-demo.csproj.
Generating MSBuild file /Users/redwards/workspace/customers/demo-zone/razor-demo/obj/razor-demo.csproj.nuget.g.props.
Generating MSBuild file /Users/redwards/workspace/customers/demo-zone/razor-demo/obj/razor-demo.csproj.nuget.g.targets.
Restore completed in 983.69 ms for /Users/redwards/workspace/customers/demo-zone/razor-demo/razor-demo.csproj.
Restore succeeded.
This generates a number of files and directories;
$ tree -L 2
.
├── Pages
│ ├── About.cshtml
│ ├── About.cshtml.cs
│ ├── Contact.cshtml
│ ├── Contact.cshtml.cs
│ ├── Error.cshtml
│ ├── Error.cshtml.cs
│ ├── Index.cshtml
│ ├── Index.cshtml.cs
│ ├── _Layout.cshtml
│ ├── _ValidationScriptsPartial.cshtml
│ ├── _ViewImports.cshtml
│ └── _ViewStart.cshtml
├── Program.cs
├── Startup.cs
├── appsettings.Development.json
├── appsettings.json
├── bundleconfig.json
├── obj
│ ├── project.assets.json
│ ├── razor-demo.csproj.nuget.cache
│ ├── razor-demo.csproj.nuget.g.props
│ └── razor-demo.csproj.nuget.g.targets
├── razor-demo.csproj
└── wwwroot
├── css
├── favicon.ico
├── images
├── js
└── lib
7 directories, 23 files
We now have a basic razor web application that will run with .Net Core.
Up and running locally
What does this template look like? You can quickly get it up and running locally on your machine;
$ dotnet run
Hosting environment: Production
Content root path: /Users/redwards/workspace/customers/demo-zone/razor-demo
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
This is all well and good for local testing however what I wanted to do was get this working in Cloud Foundry.
Up and running on PCF
The good news is to get the code running in Cloud Foundry all I need to do is a cf push
.
$ cf push razor-demo
Creating app razor-demo in org redwards / space redwards as redwards...
OK
Creating route razor-demo.<domain>...
OK
Binding razor-demo.<domain> to razor-demo...
OK
Uploading razor-demo...
Uploading app files from: /Users/redwards/workspace/customers/demo-zone/razor-demo
Uploading 232.5K, 67 files
Done uploading
OK
Starting app razor-demo in org redwards / space redwards as redwards...
Downloading binary_buildpack...
Downloading php_buildpack...
Downloading dotnet_core_buildpack...
Downloading ruby_buildpack...
Downloading staticfile_buildpack...
Downloaded php_buildpack
Downloading hwc_buildpack...
Downloaded binary_buildpack
Downloading java_buildpack_offline...
Downloaded dotnet_core_buildpack
Downloading nodejs_buildpack...
Downloaded staticfile_buildpack
Downloading go_buildpack...
Downloaded ruby_buildpack
Downloading python_buildpack...
Downloaded python_buildpack
Downloaded java_buildpack_offline
Downloaded hwc_buildpack
Downloaded nodejs_buildpack
Downloaded go_buildpack
Creating container
Successfully created container
Downloading app package...
Downloaded app package (589.4K)
-----> Dotnet-Core Buildpack version 2.0.2
-----> Supplying Dotnet Core
-----> Installing libunwind 1.2.1
Copy [/tmp/buildpacks/d373489b7b8da40d0f24fff3d0e73ecd/dependencies/35a6b4e9cad7a7fe8f8990e063509f7b/libunwind-1.2.1-linux-x64-80af276a.tgz]
-----> Installing dotnet 2.0.3
Copy [/tmp/buildpacks/d373489b7b8da40d0f24fff3d0e73ecd/dependencies/a36740596ac4c9b8b9a0fb84a6e303bf/dotnet.2.0.3.linux-amd64-b56d13fc.tar.xz]
-----> Finalizing Dotnet Core
-----> Restore dotnet dependencies
Restoring packages for /tmp/app/razor-demo.csproj...
Restoring packages for /tmp/app/razor-demo.csproj...
Installing System.Xml.XmlSerializer 4.0.11.
#<........Removed for brevaty.......>
Installing System.Runtime.InteropServices.Runtimr.m.3sdd talling Sysm Generating MSBuild file /tmp/app/obj/razor-demo.csproj.nuget.g.props.
Generating MSBuild file /tmp/app/obj/razor-demo.csproj.nuget.g.targets.
Restore completed in 7.8 sec for /tmp/app/razor-demo.csproj.
Required dotnetframework versions: [2.0.0 2.0.5]
-----> Installing dotnet-framework 2.0.0
Copy [/tmp/buildpacks/d373489b7b8da40d0f24fff3d0e73ecd/dependencies/c8e245c37838e1b497606c9125af2132/dotnet-framework.2.0.0.linux-amd64-13cb2a76.tar.xz]
**WARNING** A newer version of dotnet-framework is available in this buildpack. Please adjust your app to use version 2.0.5 instead of version 2.0.0 as soon as possible. Old versions of dotnet-framework are only provided to assist in migrating to newer versions.
-----> Installing dotnet-framework 2.0.5
Copy [/tmp/buildpacks/d373489b7b8da40d0f24fff3d0e73ecd/dependencies/07d1c50ee2f84a1f4a5a43e741e4a25f/dotnet-framework.2.0.5.linux-amd64-62cc2fb0.tar.xz]
-----> Publish dotnet
Microsoft (R) Build Engine version 15.4.8.50001 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
razor-demo -> /tmp/app/bin/Debug/netcoreapp2.0/ubuntu.14.04-x64/razor-demo.dll
razor-demo -> /tmp/contents177473746/deps/0/dotnet_publish/
-----> Cleaning staging area
Removing .nuget
Removing .local
Removing dotnet
Exit status 0
Uploading droplet, build artifacts cache...
Uploading build artifacts cache...
Uploading droplet...
Uploaded build artifacts cache (223B)
Uploaded droplet (39.1M)
Uploading complete
Stopping instance b9279880-2745-4d1d-ad94-b9ef73590d0b
Destroying container
Successfully destroyed container
1 of 1 instances running
App started
OK
App razor-demo was started using this command `cd ${DEPS_DIR}/0/dotnet_publish && ./razor-demo --server.urls http://0.0.0.0:${PORT}`
Showing health and status for app razor-demo in org redwards / space redwards as redwards...
OK
requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: razor-demo.<domain>
last uploaded: Thu Feb 15 21:20:06 UTC 2018
stack: cflinuxfs2
buildpack: dotnet-core
state since cpu memory disk details
#0 running 2018-02-15 09:21:05 PM 0.0% 36.2M of 1G 106.6M of 1G
Voila we have something running;
My Cloud Foundry deployment made use of the OOTB .Net, dotnet_core_buildpack
buildpack to get the app running. The cf push
of the source code did the following;
- Installs .NET Core runtime – version specify via global.json, else the build pack chooses
- Restores application dependencies
- Generates the command to run the application which builds the application before it runs it
To list the buildpacks use the following command;
cf buildpacks
Getting buildpacks...
buildpack position enabled locked filename
hwc_buildpack 1 true false hwc_buildpack-cached-v2.3.11.zip
staticfile_buildpack 2 true false staticfile_buildpack-cached-v1.4.18.zip
java_buildpack_offline 3 true false java-buildpack-offline-v4.7.1.zip
ruby_buildpack 4 true false ruby_buildpack-cached-v1.7.5.zip
nodejs_buildpack 5 true false nodejs_buildpack-cached-v1.6.10.zip
go_buildpack 6 true false go_buildpack-cached-v1.8.13.zip
python_buildpack 7 true false python_buildpack-cached-v1.6.1.zip
php_buildpack 8 true false php_buildpack-cached-v4.3.43.zip
dotnet_core_buildpack 9 true false dotnet-core_buildpack-cached-v2.0.2+1518187691.zip
binary_buildpack 10 true false binary_buildpack-cached-v1.0.15.zip
Answer
It turns out the answer to the question can be very quickly, in fact it takes about 5 minutes to create and deploy the application template. Obviously it is a pretty useless app and if you want it to actually do anything some time will need to be invested focusing on developing functionality.