Cloud services like Microsoft Azure do a great job of providing runtimes for webapps — you can deploy a web server from Visual Studio with a couple of clicks. But many applications don’t fit that mould — I found myself needing to deploy a custom MQTT server for IoT applications instead of paying a fortune for messaging services like PubNub. This is where containers come in handy.

Containers are much easier to manage than virtual machines, and lend themselves to really sweet CD workflows. These are my notes on setting up CD with Docker, Bitbucket, DotNet Core and Azure Container Instances, and issues that I’ve encountered.

As a refresher, Continuous X paradimes in order of increasing complexity are

Continuous Testing — unit tests are being run on every commit.

— unit tests are being run on every commit. Continuous Integration — testing connected App +Server + DB

— testing connected App +Server + DB Continuous Delivery — preparing system for one-click deployment. This is what we are trying to accomplish.

— preparing system for one-click deployment. This is what we are trying to accomplish. Continuous Deployment — going all it. A commit to staging will update the test server. A commit to master will update the production server.

Steps in this tutorial:

1 — Setup Project Locally

2 — Put it in Docker

3 — Push it to Dockerhub

4 — Setup Pipelines

5 — Setup Workflow

6 — Deploy to Azure

Working Results

Repository with setup CD and results of the tutorial

Docker Hub repository with containers built

1 — Setup Project Locally

This project is an MQTT broker written in C# and running on .Net Core. The server itself is written as a MQTTnet library and quite easy to use — you can setup topics, respond to messages from clients, save them to database, etc.

If you are not working with C#, the tutorial would work the same way with Node or any other framework, just skip to Docker section.

Get the server working

Create a DotNet Core console application and call it ‘MQTTserver’. Add the MQTTnet library with Nuget:

Install-Package MQTTnet

The meat of the program

Start up a server on port 1833 (standard MQTT port) with no authentication.

(standard MQTT port) with no authentication. Send out a Heartbeat message on the topic ‘ heartbeat ’ saying ‘ I am alive for 10 seconds ’.

’ saying ‘ ’. Close the program if the user types in ‘quit’.

Normally I would have ‘Press any key to exit’, but when when I tested that in Docker, ‘Console.Readline’ would return a null string as soon as container starts, causing the application to shutdown or crash with null exception.

Place the following code inside class Program. Namespace is skipped for readability.

static void Main(string[] args)

{

Console.WriteLine("Server Started!");

Task.Run(async () => await StartServer()).Wait();

} private static async Task StartServer()

{

var optionsBuilder = new MqttServerOptionsBuilder()

.WithConnectionBacklog(100)

.WithDefaultEndpointPort(1883); var mqttServer = new MqttFactory().CreateMqttServer();

await mqttServer.StartAsync(optionsBuilder.Build());

var ct = new CancellationTokenSource();

var heartbeatTask = Task.Run(async () => await ServerHeartbeat(ct.Token, mqttServer));



Console.WriteLine("Type 'quit' to exit"); while (true)

{

//Docker has a habit of sending random shit into CMD

string input = Console.ReadLine();

if (input != null && input.Contains("quit"))

break;

}

ct.Cancel();

await heartbeatTask;

await mqttServer.StopAsync();

}

} private static async Task ServerHeartbeat(CancellationToken token, IMqttServer server)

{

long heartbeat =0;

while (token.IsCancellationRequested == false)

{

var message = new MqttApplicationMessageBuilder()

.WithTopic("heartbeat")

.WithPayload($"I am alive for {heartbeat} seconds")

.WithAtMostOnceQoS()

.WithRetainFlag(false)

.Build();

await server.PublishAsync(message);

await Task.Delay(1000);

heartbeat++;

}

}

Test the application manually

Download any MQTT client, for example MQTTfx, connect to localhost with default settings and subscribe to topic heartbeat. Beware-topic names are case sensitive. You should see messages coming in like clockwork. You can also connect to it from several clients and try ping-ponging MQTT messages — it should work like any other broker.