Setting up a MongoDB Replica Set with Docker and Connecting to It With a .NET Core App

Easily setting up realistic non-production (e.g. dev, test, QA, etc.) environments is really critical in order to reduce the feedback loop. In this blog post, I want to talk about how you can achieve this if your application relies on MongoDB Replica Set by showing you how to set it up with Docker for non-production environments.
2018-01-31 10:10
Tugberk Ugurlu

Easily setting up realistic non-production (e.g. dev, test, QA, etc.) environments is really critical in order to reduce the feedback loop. In this blog post, I want to talk about how you can achieve this if your application relies on MongoDB Replica Set by showing you how to set it up with Docker for non-production environments.

Hold on! I want to watch, not read!

I got you covered there! I have also recorded a ~5m covering the content of this blog post, where I also walks you through the steps visually. If you find this option useful, let me know through the comments below and I can aim harder to repeat that :)

What are we trying to do here and why?



If you have an application which works against a MongoDB database, it’s very common to have a replica set in production. This approach ensures the high availability of the data, especially for read scenarios. However, applications mostly end up working against a single MongoDB instance, because setting up a Replica Set in isolation is a tedious process. As mentioned at the beginning of the post, we want to reflect the production environment to the process of developing or testing the software applications as much as possible. The reason for that is to catch unexpected behaviour which may only occur under a production environment. This approach is valuable because it would allow us to reduce the feedback loop on those exceptional cases.

Docker makes this all easy!

This is where Docker enters into the picture! Docker is containerization technology and it allows us to have repeatable process to provision environments in a declarative way. It also gives us a try and tear down model where we can experiment and easily start again from the initial state. Docker can also help us with easily setting up a MongoDB Replica Set. Within our Docker Host, we can create Docker Network which would give us the isolated DNS resolution across containers. Then we can start creating the MongoDB docker containers. They would initially be unaware of each other. However, we can initialise the replication by connecting to one of the containers and running the replica set initialisation command. Finally,  we can deploy our application container under the same docker network.


There are a handful of advantages to setting up this with Docker and I want to specifically touch on some of them:

  •  It can be automated easily. This is especially crucial for test environments which are provisioned on demand.
  • It’s repeatable! The declarative nature of the Dockerfile makes it possible to end up with the same environment setup even if you run the scripts months later after your initial setup.
  • Familiarity! Docker is a widely known and used tool for lots of other purposes and familiarity to the tool is high. Of course, this may depend on your development environment

Let’s make it work!

First of all, I need to create a docker network. I can achieve this by running the "docker network create” command and giving it a unique name.

docker network create my-mongo-cluster

The next step is to create the MongoDB docker containers and start them. I can use “docker run” command for this. Also, MongoDB has an official image on Docker Hub. So, I can reuse that to simplify the acqusition of MongoDB. For convenience, I will name the container with a number suffix. The container also needs to be tied to the network we have previously created. Finally, I need to specify the name of the replica set for each container.

docker run --name mongo-node1 -d --net my-mongo-cluster mongo --replSet “rs0"

First container is created and I need to run the same command to create two more MongoDB containers. The only difference is with the container names.

docker run --name mongo-node2 -d --net my-mongo-cluster mongo --replSet "rs0"
docker run --name mongo-node3 -d --net my-mongo-cluster mongo --replSet “rs0"

I can see that all of my MongoDB containers are at the running state by executing the “docker ps” command.


In order to form a replica set, I need to initialise the replication. I will do that by connecting to one of the containers through the “docker exec” command and starting the mongo shell client.

docker exec -it mongo-node1 mongo


As I now have a connection to the server, I can initialise the replication. This requires me to declare a config object which will include connection details of all the servers.

config = {
      "_id" : "rs0",
      "members" : [
              "_id" : 0,
              "host" : "mongo-node1:27017"
              "_id" : 1,
              "host" : "mongo-node2:27017"
              "_id" : 2,
              "host" : "mongo-node3:27017"

Finally, we can run “rs.initialize" command to complete the set up.

You will notice that the server I am connected to will be elected as the primary in the replica set shortly. By running “rs.status()”, I can view the status of other MongoDB servers within the replica set. We can see that there are two secondaries and one primary in the replica set.

.NET Core Application

As a scenario, I want to run my .NET Core application which writes data to a MongoDB database and start reading it in a loop. This application will be connecting to the MongoDB replica set which we have just created.  This is a standard .NET Core console application which you can create by running the following script:

dotnet new console

The csproj file for this application looks like below.

<Project Sdk="Microsoft.NET.Sdk">
    <PackageReference Include="Bogus" Version="18.0.2" />
    <PackageReference Include="MongoDB.Driver" Version="2.4.4" />
    <PackageReference Include="Polly" Version="5.3.1" />

Notice that I have two interesting dependencies there. Polly is used to retry the read calls to MongoDB based on defined policies. This bit is interesting as I would expect the MongoDB client to handle that for read calls. However, it might be also a good way of explicitly stating which calls can be retried inside your application. Bogus, on the other hand, is just here to be able to create fake names to make the application a bit more realistic :)

Finally, this is the code to make this application work:

partial class Program
    static void Main(string[] args)
        var settings = new MongoClientSettings
            Servers = new[]
                new MongoServerAddress("mongo-node1", 27017),
                new MongoServerAddress("mongo-node2", 27017),
                new MongoServerAddress("mongo-node3", 27017)
            ConnectionMode = ConnectionMode.ReplicaSet,
            ReplicaSetName = "rs0"

        var client = new MongoClient(settings);
        var database = client.GetDatabase("mydatabase");
        var collection = database.GetCollection<User>("users");

        System.Console.WriteLine("Cluster Id: {0}", client.Cluster.ClusterId);
        client.Cluster.DescriptionChanged += (object sender, ClusterDescriptionChangedEventArgs foo) => 
            System.Console.WriteLine("New Cluster Id: {0}", foo.NewClusterDescription.ClusterId);

        for (int i = 0; i < 100; i++)
            var user = new User { Id = ObjectId.GenerateNewId(), Name = new Bogus.Faker().Name.FullName() };

        while (true)
            var randomUser = collection.GetRandom();


This is not the most beautiful and optimized code ever but should demonstrate what we are trying to achieve by having a replica set. It's actually the GetRandom method on the MongoDB collection object which handles the retry:

public static class CollectionExtensions 
    private readonly static Random random = new Random();

    public static T GetRandom<T>(this IMongoCollection<T> collection) 
        var retryPolicy = Policy
            .WaitAndRetry(2, retryAttempt => 
                TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) 

        return retryPolicy.Execute(() => GetRandomImpl(collection));

    private static T GetRandomImpl<T>(this IMongoCollection<T> collection)

        return collection.Find(FilterDefinition<T>.Empty)

I will run this through docker as well and here is the dockerfile for this: 

FROM microsoft/dotnet:2-sdk

COPY ./mongodb-replica-set.csproj /app/
RUN dotnet --info
RUN dotnet restore
ADD ./ /app/
RUN dotnet publish -c DEBUG -o out
ENTRYPOINT ["dotnet", "out/mongodb-replica-set.dll"]

When it starts, we can see that it will output the result to the console:


Prove that It Works!

In order to demonstrate the effect of the replica set, I want to take down the primary node. First of all, we need to have look at the output of rs.status command we have previously ran in order to identify the primary node. We can see that it’s node1! 


Secondly, we need to get the container id for that node. 


Finally, we can kill the container by running the “docker stop command”. Once the container is stopped, you will notice that application will gracefully recover and continue reading the data. 


Speaking at SQL in the City 2017, Register Now!

I'm quite happy to tell you that I'll be speaking at SQL in the City 2017 on the 13th of December about Latest SQL Compare features and support for SQL Server 2017 with my colleague and fellow MVP, Steve Jones.
2017-12-05 18:27
Tugberk Ugurlu

I'm quite happy to tell you that I'll be speaking at SQL in the City 2017 on the 13th of December about latest SQL Compare features and support for SQL Server 2017 with my colleague and fellow MVP, Steve Jones.


SQL in the City Redgate's annual virtual event and this year's livestream event focuses on enabling you to be more productive. Technical sessions will dive into the latest Microsoft SQL Server releases, and cover topical issues such as data compliance, protection & privacy.

This year's agenda is full of really great sessions from enabling DevOps for databases by automating your deployments to rapid (and magic!) database provisioning with SQL Clone. This year Data Platform MVPs Steve Jones and Grant Fritchey will be joined by Kathi Kellenberger, Editor of Simple Talk and many more who are behind the great tools we build!

Register Now!

Register now to confirm your attendance, and be the first to get access to Grant Fritchey’s new eBook, SQL Server Execution Plans, when it's released in 2018.

Understanding Graphs and Their Application on Software Systems

Lately, I wanted to spend a little bit time on going back to fundamental computer science concepts. I am going to start with Graphs, specifically Depth First Traversal (a.k.a. Depth First Search or DFS) and Breadth First Traversal (a.k.a Breadth First Search or BFS). However, this post is only about the definition of Graph and its application in software systems.
2017-09-19 17:21
Tugberk Ugurlu

Lately, I wanted to spend a little bit time on going back to fundamental computer science concepts. Hopefully, I will be able to write about these while I am looking into them in order to offload the knowledge from my brain to the magic hands of the Web :) I am going to start with Graphs, specifically Depth First Traversal (a.k.a. Depth First Search or DFS) and Breadth First Traversal (a.k.a Breadth First Search or BFS). However, this post is only about the definition of Graph and its application in software systems.

What is a Graph?

I am sure you are capable of Googling what a Graph is and ironically maybe that’s why you are reading this sentence now. However, I am not going to put the fancy explanation of a Graph here. Wikipedia already has a great definition on a Graph which can be useful to start with.

Let’s start with a picture:


This is a graph and there are some unique characteristics of this which makes it a graph.

  • Vertices (a.k.a. Nodes): Each circle with a label inside the above picture is called a vertex or node. They are fundamental building blocks of a graph.
  • Edges (a.k.a. Arc, Line, Link, Branch): A line that joins two vertices together is called as edge. An edge could be in three forms: undirected and directed. We will get to what these actually mean.

At this point you might be asking what is the difference between a graph and a tree? A tree is actually a graph with some special constraints applied to. A few of these that I know:

  • A tree cannot contain a cycle but a graph can (see the A, B and E nodes and their edges inside the above picture).
  • A tree always has a specific root node, whereas you don’t have this concept with a graph.
  • A tree can only has one edge between its two nodes whereas we can have unidirectional and bidirectional edges between nodes within a graph

I am sure there are more but I believe these are the ones that matter the most.

As we can see with the tree example, graphs comes in many forms. There are many types of graphs and each type has its own unique characteristics and real world use cases. Undirected and directed graphs are two of these types as I briefly mentioned while explaining the edges. I believe the best example to describe the difference between them is to have a look at the fundamental concept of Facebook and Twitter.

Application of Graphs

Graphs are amazing, I absolutely love the concept of a graph! Everyone interacts with a system everyday which somehow makes use of graphs. Facebook, Google Maps, Foursquare, the fraud check system that your bank applies are all making use of a graph and there are many, many more. One application of graph concept which I love is a recommendation engine. There are many forms of this but a very basis one is called Collaborative Filtering. At its basis, it works under a notion of “Steve and Mark liked BMW, Mercedes and Toyota, you like BMW and Toyota, and you may like Mercedes, too?”.

There are some really good graph databases with their own query languages as well. One that I love about is Neo4j which uses Cypher query language to make its data available to be consumed. On their web site, there are a few key applications of Neo4j listed and they are fundamentally real world applications of the graph concept.

You can also come across some interesting problems in the space of mathematics which has solutions based on a type of graph like Seven Bridges of Königsberg problem (and I think this problem is the cornerstone in the history of graph theory).

Here is My Proudest Achievement, What is Yours?

It's very common that you get asked about your proudest achievement. I wanted to put mine here publicly so that I would have a place to direct people to. So, here it is :)
2017-09-18 16:59
Tugberk Ugurlu

It's very common that you get asked about your proudest achievement. I wanted to put mine here publicly so that I would have a place to direct people to. So, here it is :)

My proudest achievement to this day dates back to 2010. I was working at a local Travel Agency in Turkey while still studying Travel Management at the university and we had a Web site for our customers to book their airport transfers from/to their hotels by paying online. However, the application didn't allow our customers to book additional services with extra cost such as baby booster seat. In addition to this, we were unable to reflect our pricing accurately for particular conditions due to the limitations on the system. At the time, I was working at the reservations and booking department but I had a huge interest on software development, especially on web applications.

When our web developer left the company, I prototyped the algorithm to calculate the airport transfer pricing on SQL Server based on the number of passengers, arrival and departure dates. I presented this to my manager who was also in charge of the company's online sales, and asked for a budget and time for developing a new airport transfer booking system for the company. I explained that this system would have the same features as the old system along with the additional features we have always wanted. This was going to allow us to provide better service to our customers and reflect cheaper prices by having a maintainable system to build upon. My manger believed in me, and gave me time and budget to invest on this. I spent a month to develop the system and its content management system by coding the business logic in C# (while learning it at the same time), developing the user interface as a web application using HTML, CSS and JavaScript, and integrating it with an online payment system. I had to deal with lots of things I hadn't known about but having a good support from my manager made me always trust myself and keep pushing to come through all the obstacles. We rolled out the system under a different domain name first and advertised it through Google AdWords‎ (you could see that version see here even if the styles and functionality don't quite work on Within the first 5 hours, we sold a Private Minibus Transfer through the system Over the weeks, we directed all our transfer booking channels to this new system and kept evolving it. After two years, the system sold 32% more transfers than the old system and yielded 26% more revenue. The final look of the system is still running here and maintained by the company (I should point out that I am not entirely responsible for the new look of the site , especially for those red primary action buttons!). Proving myself with this achievement also gave me a chance to take more responsibility on software engineering at the company and I was able to get a budget for an accommodation booking system (it can been found on which yielded extra revenue for the company for a few years.

Lots of things happened after this and I achieved so much more such as being part of several successful teams to create valuable software products, being published, having the Microsoft MVP award for 5 years in a row, speaking at lots of international conferences, maintaining a successful blog for 7+ years and many more. However, nothing was able to beat that because it was a unique opportunity to be able to fight for something I truly believed in. Besides that, having a true leader as your manager is a unique opportunity. He trusted me and my skills, and when looking back at this now, it's very clear to see that I would never have become a good software developer without this trust and my confident in myself.

What's Your Proudest Achievement?

Well, it's your turn. Hopefully I encouraged you to share yours publicly as well. Please share yours as a comment here, preferably by linking to your blog post which you are about to write :)

Defining What Good Looks Like for a Software Engineer

What does good look like for a software engineer? This is a question you might be asking frequently to yourself and I tried to share my thoughts on the topic with this blog post.
2017-03-18 15:00
Tugberk Ugurlu

If you are a software engineer, this is a very common question you will get to ask yourself a lot. This is going to be especially very frequent if you are being part of the recruitment process in your company. As you may know, I work at Redgate, and we have a good culture for development teams. Besides that, common characteristics of a good engineer with examples and counter examples for each engineering role are defined, too. This is a really good guidance for the employer to reflect their culture for a particular role. It’s also good for the employees to understand where they are on being an effective employee.

(Image is from

I got inspired by this and I wanted to share the list of principals I value and look for within a software engineer. Obvious disclaimer: this is not the list of principals that my employer values even if the most of them are pretty similar. As we got the disclaimer out of our way, let's see these principals:

  • Knows the fundamental concepts, data structures and common algorithms rather than only being too good with a programming language or a specific framework w/o understanding the basics. In other words, know the basics and be polyglot.
  • Has good communication skills - both verbal and written. Without this, it's impossible to be a good software engineer.
  • Being pragmatic - Works incrementally and balances delivering value frequently with delivering high quality.
  • Iterates fast - Values Continuous Integration (CI) and Continuous Delivery (CD), makes their code fail fast, enforce consistency and keep master branch releasable. Your release process should as easy as adding a git tag as a valid semantic version.
  • Cares for sustainability - Strives for producing code which will sustain for years, even decades. Not one-off, works-now-who-knows-when-it-will-stop-working ones.
  • Knows the business - Cares to understand the business domain and strives for establishing an ubiquitous language between the software product team and stakeholders.
  • Strives for THE BEST UX - Makes user experience the part of the product completeness.
  • Being a team player - Works with their peers, gets/gives code review from/to them. Develops their skills while they are developing their own. Should strive for being transparent to the team all the time.
  • Knows the metrics but also has a vision - Should know the metrics and how to get them to make decisions. However, they should have a vision at the same time, too. They should not have the "Let’s ask the users” mindset as the default approach for product feature decisions. Remember, good artists copy; great artists steal! The problem you are trying to solve has been probably solved within the same or a different context. Find that, bend it and apply differently.
  • Disagrees and commits when needed - Should not be shy about getting their opinions out and pursue them. However, they should also know that a decision has to be made, and when that’s the case, they should commit fully and try to get the best out of it even if it’s not the decision they wanted to see.
  • Values open source and contributing back to software community - Has a blog, gives talks at conferences or user groups, contributes back to open source projects. Simply shares what they are proud of with others openly.

There are probably more but these are the most important ones that I care about and value at a very high level. However, I wonder what yours are, too. Therefore, please share them with me here by send me a comment.