Using ASP.NET Core with MongoDB in containers for local dev, CosmosDB for production

If nothing else is true, containers have made local development on a platform so much easier. If you want to use SQL Server for your backend just docker pull microsoft/mssql-server-linux and you can start up an instance with a few parameters.

Azure CosmosDB is not available as a container, however, MongoDB is available and happens to be a database I have used in previous applications. MongoDB is one of the many APIs that CosmosDB supports; locally I can develop against an instance of Mongo either in a container or installed and simply change the connection string for my production instance.

The flexibility of being able to use MongoDB and then just changing a connection string to use CosmosDB is a nice capability if you have exisiting applications that are using Mongo and you are looking for the globally scalable and features that CosmosDB offers.

If you need to migrate data from MongoDB applications to CosmosDB see this doc for the steps.

Creating the Databases

For MongoDB locally, using Docker is super simple. Run docker pull mongo, and now you can use this in your application.

docker run --name mongo mongo  

Visual Studio Code has a CosmosDB extension as a part of the Azure Extension pack that allows you to interact with Mongo Databases as well as CosmosDB instances.

CosmosDB Extension

This extension also allows you to create your CosmosDB instance right from VS Code, or you can create it in the Azure portal or even using the Azure CLI.

Create Database

However you like to create the instance, it can all happen in the same tool and that's awesome for me.

Local Development

The app is a basic ASP.NET Core Razor Pages application which list "Running Races" that have been reviewed.

run race review page

Both the app and the database are set to use containers and docker-compose to orchestrate them.

Application Dockerfile

FROM microsoft/dotnet:2.1.2-aspnetcore-runtime AS base  
WORKDIR /app  
EXPOSE 443

FROM microsoft/dotnet:2.1.403-sdk AS build  
WORKDIR /src  
COPY runracereview.csproj .  
RUN dotnet restore  
COPY . .  
WORKDIR /src  
RUN dotnet build -c Release -o /app

FROM build AS publish  
RUN dotnet publish -c Release -o /app

FROM base AS final  
WORKDIR /app  
COPY --from=publish /app .  
ENTRYPOINT ["dotnet", "runracereview.dll"]  

docker-compose

version: "3"  
services:  
  runracreview:
    container_name: runracereview
    restart: always
    build:
      context: ./runracereview
      dockerfile: Dockerfile
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=http://+:80
    ports:
      - "57270:80"
      - "44348:443"
    volumes:
      - ${HOME}/.microsoft/usersecrets/:/root/.microsoft/usersecrets
      - ${HOME}/.aspnet/https:/root/.aspnet/https/
    links:
      - mongo
  mongo:
    container_name: mongo
    image: mongo
    volumes:
      - ${WEBAPP_STORAGE_HOME}/site:/data/db
      #- ./data:/data/db
    ports:
      - "27017:27017"

Notice that in the compose file that the mongo image has a volume mapped to ${WEBAPP_STORAGE_HOME}/site:/data/db, this is done to persist the test data locally as to not reload the data everytime the container is spun up.

Check out the Microsoft Learn course : Build a .NET Core app for Azure Cosmos DB in Visual Studio Code - FREE

Setting up the app

Getting the connection to the database are done using the Configuration settings base on the Environment.

In appsettings.Development.json, the configuration for Mongo is added, and for Production, the CosmosDB connection string is set in appsettings.Production.json. The ConfigurationBuilder loads the appropriate file based on the environment.

  "MongoDB": {
    "ConnectionString": "mongodb://localhost:27017",
    "Container" : "mongodb://mongo:27017",
    "Database": "Races"
  },

Startup.cs configures the Settings options.

 services.Configure<Settings>(
      options =>
      {
        options.ConnectionString = Configuration.GetSection("MongoDb:ConnectionString").Value;
        options.Database = Configuration.GetSection("MongoDb:Database").Value;
        options.Container = Configuration.GetSection("MongoDb:Container").Value;
        options.IsContained = Configuration["DOTNET_RUNNING_IN_CONTAINER"] != null;
      });

If you are running .NET Core applications in a container you can inspect the Environment variable DOTNET_RUNNING_IN_CONTAINER to determine if this is true.

If the application is running in a container and in Development then the Settings class returns the proper connection string for the container.

Simple but ...

Being able to work locally and iterate on a simple set of data without having to hit the production data constantly, or be concerned with the UH OH moments when trying new things is an advantage of this setup.

Code for this application is available on GitHub : https://github.com/spboyer/runracereview

Tweet Post Share Update Email RSS

Hi, I'm Shayne Boyer, I write this site, work on ASP.NET Core content and Open Source, speak at national and community events while helping teams architect web and cloud applications.

Tags:
azure mongodb cosmosdb