I've been thinking of creating a personal professional website for some time now. I was looking for a place to publish blog articles, my resume, slide decks and project portfolio. As always I was also looking for an opportunity to get exposure to some technology I have not had an opportunity to utilize in my day job.
For this project I had some non-functional requirements that I wanted to include.
- Inexpensive cloud hosting
- Must support https and custom domain name
- Utilizes Kentico Cloud for CMS
- Utilizes ASP.NET Core
- Deployed with Docker containers
I knew from experience that Azure would probably run me about $53/month when I combined custom domain and https requirements and that was way out of budget for this project. I could do a little better with AWS Elastic Beanstalk, but I know from past experience that the configuration can be a trick to get set up to support https and I wanted to spend that time learning something new.
Then one day I ran across AWS Lightsail. AWS created this service to provide developers like myself with an easy to configure cloud solution that will grow with my needs or just be a low cost place to host example projects. This was exactly what I needed and I found that I could get a low end Linux host for $3.50/month. I was disappointed to learn that https through Lightsail requires the Lightsail load balancer, which would be awesome, but not for $20/month. Luckily, I found an example to use Let's Encrypt with Docker and Nginx to enable https for FREE.
After reading a number of blog articles and watching videos on how to configure my application to use docker, I put together the solution in the diagram below.
This diagram shows how I configured docker images to host my website.
Ningx as a reverse proxy handles the https requests and runs in a container on the same virtual network as my website. My website is an ASP.NET Core Razer Pages project created in Visual Studio 2017 and published into a Linux container. A certbot container is spun up on a chron job periodically to generate a new Let's Encrypt cert since they expire every 90 days.
All of my content is hosted in Kentico Cloud. Kentico Cloud is a Headless CMS, which means I get all of the awesome capabilities of CMS without the hassle of maintaining a CMS or trying to get my code to run inside of a CMS. All of my code, CSS and page templates are in the ASP.NET Core application.
For now I'm caching the content requests in memory, but I may add a Redis cache container to handle the content caching in the future.
I'm also considering options for storing secrets in the Docker ecosystem. Unfortunately, the options available are not very clear cut. I am liking the idea of running Spring Cloud Config server in a container that is back ended with a private Git repository. If I can find a trustworthy container with Spring Cloud Config server, I will go that route.
For the most part this solution can be recreated with relative ease. The tricky part is getting the initial Let's Encrypt certificate issued without https enabled. I have put together the steps and will share them in a future blog article.
Some of the resources I used to create this solution: