Deploying My .NET Blog to Google Cloud Run
I moved my personal blog from a slow host to Google Cloud Platform because I wanted faster load times and some real cloud deployment experience. Here is how it went, warts and all.
Setting up the project
I created a new project in GCP and enabled the services I needed:
- Cloud Run for hosting the container
- Artifact Registry to store Docker images
- IAM roles so my account could actually deploy
I also installed the Google Cloud SDK and checked I could talk to GCP from the command line.
Getting the app ready
My blog is a .NET app, so the first step was making sure it would run inside a container. The gotcha: Cloud Run expects your app to listen on port 8080 (or whatever is in the PORT environment variable).
- My app was originally set to run on port 5000 for no good reason.
I updated Program.cs so it uses the provided port:
var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
app.Urls.Add($"http://0.0.0.0:{port}");
app.Run();
Before pushing anything, I checked the container locally:
docker build -t myblog-app .
docker run -p 8080:8080 -e PORT=8080 myblog-app
Everything worked at http://localhost:8080.
Pushing to Artifact Registry
I originally tried pushing to Container Registry (GCR) but ran into 403 permission errors on Windows. I fought with OAuth and IAM for a while, then switched to Artifact Registry to get unstuck:
docker tag myblog-app europe-west2-docker.pkg.dev/my-blog-website-470819/myblog-app-repo/myblog-app:latest
docker push europe-west2-docker.pkg.dev/my-blog-website-470819/myblog-app-repo/myblog-app:latest
Deploying to Cloud Run
Once the image was in Artifact Registry, deployment was straightforward:
gcloud run deploy myblog-app \
--image europe-west2-docker.pkg.dev/my-blog-website-470819/myblog-app-repo/myblog-app:latest \
--platform managed \
--region europe-west2 \
--allow-unauthenticated \
--min-instances 1
Cloud Run handles scaling, HTTPS, and keeping instances warm if you want that.
After a few minutes, the blog was live.
Cost tweaks
I noticed it was costing around 9p for 12 hours with one instance always running. That is tiny, but it adds up if you leave it on for months.
- CPU and memory: I dropped the instance size from 1 vCPU / 512MB to 0.25 vCPU / 256MB. The blog is light, so it did not need the bigger size.
- Minimum instances: If I set it to zero I save money, but the first request after idle gets a cold start. Keeping one small instance warm gives me faster load times for a small baseline cost.
Right now I am experimenting with the best balance.
What I learned
- Port config matters: Cloud Run provides
$PORTand you need to bind to it. - Local testing helps: running the container locally saved me a lot of headache.
- Artifact Registry is easier: less OAuth pain on Windows (for me, anyway).
Next steps
I want to:
- Set up a custom domain
- Trim the Docker image size to speed up cold starts
- Add logging and monitoring so I can see traffic and errors properly
Overall this was fun, and my blog is definitely quicker now.