Containerizing Blazor Apps
Blazor is a hot new framework from Microsoft for creating interactive front end applications in C#. In this article, we’re going to show how you can put your Blazor applications into containers for development and deployment. We’ll use the .NET Core CLI, so the commands shown will work the same regardless of platform.
Blazor Hosting Models
There are two hosting models for Blazor development, and their requirements are different, so I’ll split this post based on those two models:
Blazor WebAssembly: A web framework to run client-side in a browser with WebAssembly.
Blazor Server: A web framework that runs server-side and uses SignalR to communicate with the browser.
You can find out more about the different hosting models here.
WebAssembly Hosting Model
The goal of the WebAssembly hosting model is to host the entire application within the browser. The artifacts from a Blazor WebAssembly application are HTML, JavaScript, a version of the .NET Runtime, and your binaries. They’re all run within the browser, so you can host this as a static website. No server runtime or interpreter is required.
Blazor WebAssembly is still in Preview mode, so you must manually install the template to create Blazor WebAssembly applications. This may have changed by the time you read this. If the Blazor templates are still not available, you can run the following from the command line to get the preview version:
dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.1.0-preview4.19579.2
Now that you have the template installed you can create a new WebAssembly application with the following .NET CLI command:
dotnet new blazorwasm -o wasmtest
This will create a new Blazor WebAssembly application with the name of “wasmtest”. You can change “wasmtest” to the name of your project.
When you’ve built and tested your app, it’s ready to publish. Run the dotnet publish command:
dotnet publish -c Release
and you should see a screen that looks like this:
Here we can see paths to the artifacts if we want to run this as a .NET Core application (dotnet run)
/home/jeremy/Projects/wasmtest/bin/Debug/netstandard2.1/publish/
Here’s one of the cool features: static files as artifacts. We also have a Blazor output folder. This folder is where the static files are published.
In my case, with a project name of wasmtest (yours will be different), the folder is located here:
bin/Release/netstandard2.1/publish/wasmtest/dist
The “dist” folder only contains only static files:
You can run this file from any static web host. I will create a new folder for the container, and an artifacts folder, then copy everything from the dist folder into artifacts.
mkdir -p ~/Projects/wasmcontainer/artifacts
cp -r ~/Projects/wasmtest/bin/Release/netstandard2.1/publish/wasmtest/dist/* ~/Projects/wasmcontainer/artifacts/
In our wasmcontainer folder, we’ll create a simple Dockerfile:
FROM nginx
COPY artifacts /usr/share/nginx/html
This file pulls down the nginx image, then copies the files from artifacts in on your machine to /usr/share/nginx/html
(default nginx folder) in your container’s filesystem. It will do this every time the image is built, so if you make changes to the artifacts, you’ll need to rebuild the image.
This is all we’ll need to get up and running with the Blazor WebAssembly static files. Now we’ll create an image:
docker build -t jeremy/wasmtest:latest .
Then we can run it:
docker run --name wasm1 -p 80:80 -d jeremy/wasmtest:latest
This runs the container as a daemon, so it will run until you decide to stop it.
We now have a static nginx server running our application on Port 80. You can browse to it and see it on your local machine:
In a production environment, you’ll want to do a lot more with the NGINX configuration. However these steps will host your Blazor WebAssembly application in a container for development.
Blazor Server Hosting Model
For the server model, you need the .NET Core runtime 3.0 or greater. A Blazor server app is created with the blazorserver template. In this case I’m naming the application servertest.
dotnet new blazorserver -o servertest
Once you’re done modifying the application, and you’re ready to deploy it, run the following command to publish:
dotnet publish -c Release
The artifacts will be located in:
/app/bin/Release/netcoreapp3.1/publish/
We’ll create another folder as we did before:
mkdir -p ~/Projects/servercontainer/artifacts
cp -r bin/Release/netcoreapp3.1/publish/* ~/Projects/servercontainer/artifacts/
Here’s what the artifacts look like:
Now we’ll create another Dockerfile in our servercontainer folder that looks like this:
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
COPY artifacts/ app/
ENTRYPOINT ["dotnet", "app/servertest.dll"]
This file is only one line more than our last Dockerfile. It brings in the aspnet runtime image, copies over the artifacts, and then sets an entry point for the application, which in my case is servertest.dll because the project name is servertest.
We can build our image with the following command:
docker build -t jeremy/servertest:latest .
It should look like this:
And we’ll run it with the following command:
docker run --name server1 -p 80:80 -d jeremy/servertest:latest
Again we’re running this as a daemon so it will run until the container is stopped. This will run your Blazor Server application on port 80:
It’s that easy!
Conclusion
It’s a straightforward process to build containers for Blazor deployment. It’s essential to keep in mind the different hosting models for each and build your images accordingly. The images shown here are fine for development and testing; however, if you want to deploy these in a production environment, you should do the following:
- Use SSL instead of open over port 80
- Configure NGINX for Blazor WASM (caching optimization at least)
- Configure NGINX or another reverse proxy for your Blazor Server applications
I hope this post has helped show how to containerize your Blazor applications.