This project demonstrates how to create a new F# based ASP.NET web project and deploy it in to a docker container.
You can follow this tutorial on Windows, Linux or Mac. You can also follow this along in other languages other than F#.
You can either generate your code from scratch or you can clone this repo and base on that. I prefer the generating option FWIW (teach a man to fish and all that).
Before you begin, you'll need to install these things.
- .NET Core SDK
- Visual Studio Code
- Docker
- Node.js - for the build tools
- Bower NPM Package
- yo NPM Package
- generator-aspnet NPM Package
- Gulp
I prefer to use the Windows Subsystem for Linux based Bash environment for my dev work. Follow this tutorial for a nice environment of your own: Setting up a Shiny Development Environment within Linux on Windows 10. I also really like Hyper as my terminal (follow this).
P.S. Get the Ubuntu Mono font - it's sweet regardless of your platform.
We'll be using node to do some stuff (template generation etc).
Note: If you are using Windows Subsystem for Linux, you will need to install Node in your Windows and Linux OS.
Also note: Linux is Linux and Windows is Windows. With Linux on Windows, you need to be aware that building a .NET app on the Linux bash will not work on Windows - which affects your debugging experience.
Once node is running, install bower
, yo
and generator-aspnet
.
npm install -g yo
npm install -g generator-aspnet
npm install -g bower
npm install -g gulp
The src
folder here in this repo is generated by typing yo aspnet
and choosing the F# web project option.
Yes - it's ready to launch!
dotnet restore
dotnet run
Open up your browser and navigate to localhost:5000. Easy!
Note: if you've checked out the code sample from this repo, you'll need to switch to the "src" directory and also run bower install
to restore the JavaScript and other libs.
If you've already installed Visual Studio Code, you can now type code .
and Code will open your project ready for editing.
Note: You'll need the new Windows 10 Creators Update and updated Linux environment for the code shortcut to work properly.
Note: If you like my icons and would like them in your VSCode, follow this post.
Now that you're in the editor, let's get the build going. Visual Studio Code is not an IDE - instead it's a code editor. It's very flexible and powerful at the cost of some creature comforts such as a project system etc. However by using tasks and launch configurations you can make a nice build and debug setup.
Press ctrl-shift-b
to start off a build. You'll notice the error along the top saying that no build task has been defined.
The first time I saw this, I was a little disappointed. Why wouldn't VSCode just set it all up for me like Visual Studio 2017 would?? It turns out, it's a blessing in disguise. The task system in VSCode is super configurable, and in modern OSS app development developers want full control over their build and other processes that happen as they work.
In the error message, click on "Configure Build Task". If you closed that, press ctrl-shift-p
and search for "Configure Task Runner". In the drop down that appears, select ".NET Core". Now press ctrl-shift-b
again (you may need to restart your VSCode instance to get it to pick up the new settings).
You may get an error in your new build - this is becasue you must first run dotnet restore
from your terminal. To bring up the terminal inside VSCode press ctrl-shift-~
. This might not work the first time on Windows - you may have to use CMD or PowerShell from your project directory to run dotnet restore
.
Note: Make sure that your .NET SDK versions are the same on your Bash and Windows environments when using Windows Subsystem for Linux bash. Type dotnet --version
to find which version you are running.
... or you can just type dotnet restore
in the file path area of the folder.
Note on Terminals - I like to use Bash and Linux as my terminal in Code - to set this, bring up the preferences (ctrl+,
) and add the setting:
"terminal.integrated.shell.windows": "\\WINDOWS\\sysnative\\bash.exe",
But please be aware this will not work properly with .NET Core apps you're debugging in Code (terminal will restore Linux versions of packages, whilst code will run the Windows version - it's not compatible!)
Now that a build task is present, try and press "F5" to launch program and start debugging. Similar to before with the task.json file, there is now no launch.json which tells Code how to fire up the new app.
Press F5 and select ".NET Core" from the drop down or open the command palette ctrl-shift-p
, search for "launch" and select "Debug: Open launch.json" and again, select ".NET Core". You'll be taken to a new launch.json template file for launching a .NET Core app.
This is a web app, so delete the first configuration section with a name of ".NET Core Launch (console)".
Next we need to set the "program" path. When you build, you can see the file path to the executable on the "OUTPUT" tab down the bottom.
WebApplicationBasic -> c:\Users\jak\demo\WebApplicationBasic\bin\Debug\netcoreapp1.0\WebApplicationBasic.dll
Copy that in to the path after "${workspaceRoot}" - you'll have to flip the "\" on Windows to "/".
"program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/WebApplicationBasic.dll",
Switch to the debug tab on the left and select .NET Core Launch (web) from the drop down.
If you see and error similar to this remember to switch build configs on the debug tab: "Configuration '.NET Core Launch (console)' is missing in 'launch.json'.
You might also see an error "Run 'Debug: Download .NET Core Debugger' ...". Press ctrl-shift-p
and type "Debug: Download .NET Core Debugger" and let it finish.
Pressing "F5" now will run the app.
You can set breakpoints and everything!
One of the best things about .NET Core is that it runs on Linux - and thus works well inside docker containers. The .NET Core team has worked hard to make the docker experience as nice as possible - so it's super easy to get your new F# .NET Core app up and running inside a container.
In the root of your new project, add a new file called "Dockerfile" and copy the following in to it:
FROM microsoft/aspnetcore:1.0
WORKDIR /app
COPY ./src/bin/Debug/netcoreapp1.0/publish .
EXPOSE 80
ENTRYPOINT ["dotnet", "<your app name>.dll"]
This file tells docker how to deploy your app in to the Docker container. It tells the container where to copy the program files, which port to expose and how to start the app. It also tell it the base container name to use from Docker Hub so you don't have to configure it yourself.
Note: In this example there is a ./src on the front of the COPY command. If your dotnet src code is not in a sub directory, you can remove this - just make sure this path points to where your files ended up being published.
Before this will work however, the app needs to be prepared - a special release build needs to be performed.
In your terminal (Powershell, bash etc. ) type dotnet publish
. This will create an output in "bin\Debug\netcoreapp1.0\publish". Check that the files have been output here.
Now you're ready to run some docker commands to build the app. You can do this from the terminal, or you could install the Docker extension for Visual Studio Code .
Before you can run a docker container you need to build it.
docker build -t <containerName> .
Then you can start the docker container.
docker run -t -P -d <containerName>
Now you can view the site running in docker. But first you'll need to know where to look for it!
It changes a little depending on your OS becasue of the way the docker vm runs. On Mac for example the docker virtual machine runs on another IP that you need to find:
docker-machine ip
will give you this IP. On Windows, it's in Hyper-V so you don't need to worry - it's running on localhost.
Then you need to find the port that your image is running on.
docker ps
will show you all running docker processes - including their ports - navigate to the machine ip / or localhost (on Windows) : port number and you should see your site!
Note on Mac - you may need to run a command in each terminal instance for it to know how to talk to docker. If you're getting issues like cannot find the docker-machine - type this before trying again: eval "$(docker-machine env default)"
.
The process to build the code, publish it, compose the docker container, stop old containers and run the new container version can be a bit time consuming and is not great for quick development iteration.
I've added a sample gulpfile that can help with this. It contains a series of gulp tasks that can be run to help build the bits.
You can run gulp docker:full
to to the lot - build the app, publish, compose and run (and stop old ones! Careful, the code will stop all running containers!).
Browse the gulp file for other tasks that you can run separately.
These tasks can be linked an run from VSCode tasks - see the tasks.json file for examples.
I mentioned it a few times throughout this artical but just to be double sure: You cannot do a dotnet restore
on Linux (i.e. bash.exe inside Code etc) and then "F5" run it in Code as the Linux restore will load the Linux bits (nugets, runtimes etc.) but Code will try and run it using Windows bits. This is not a problem on Mac.