Running a Minecraft server on Azure using ACI

24/12/2019

It is Christmas, the time of the year where you need to be indoor and play some computer games with family and friends. And what better game to play than Minecraft?

But in order to play with the extended family you want a private internet accessible server where you don’t have strangers destroying your creations. So you need run your own server somewhere, preferably in the cloud.

Luckily, the Minecraft community maintains a great server docker image that can easily be spun up on your favorite cloud. This article describes how to run a docker based Minecraft server on Azure Container Instances (ACI). ACI is a service for running containers on-demand for shorter time periods, if you plan to run the server 24×7 then ACI is not a cost effective hosting option. But starting the server on-demand should probably be sufficient for a family oriented Minecraft server as you are most likely going to agree on certain times where you want to play, and then start the server.

In the following I will describe the interesting aspects of the ARM template, that I created to setup the Minecraft server. Using an ARM template makes it super easy to create a new server, it literally requires a single click to create a new Minecraft server with a custom domain name.

The ACI services is really out-of-the-box designed for running stateless docker images, but when running a Minecraft server we would want our world to be persisted between server restarts. So we need to configure ACI with some persistent storage. The preferred storage solution is to mount an Azure Storage File Share with the container, so that it can store all the needed files here. In ACI you can mount external storage by defining a volume as part of the containerGroup, in the

"volumes": [
{
"name": "data",
"azureFile": {
"readOnly": false,
"shareName": "[variables('fileShareName')]",
"storageAccountName": "[parameters('storageAccountName')]",
"storageAccountKey": "[listKeys(parameters('storageAccountName'),'2017-10-01').keys[0].value]"
}
}
]

Since an Azure storage account per default comes without any Azure file shares when it is created, we need to somehow ensure that a file share is created before we attempt to mount it from the Minecraft server. To accomplish that we used to, have to run a docker container running an Azure CLI command to created the file share. But since API version 2019-04-01 this hack is no longer needed, now we can create the file share using a standard ARM resource.

{
"type": "Microsoft.Storage/storageAccounts/fileServices/shares",
"apiVersion": "2019-04-01",
"name": "[concat(parameters('storageAccountName'), '/default/', parameters('fileShareName'))]",
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
]
}

All that is left for us to setup our minecraft server is now to decide on the configuration of the server. The few important settings, that I left for you to tweak in the variable section of the template is that you need to pick between the itzg/minecraft-server and itzg/minecraft-bedrock-server docker images, where the later is for the most recent non-java Minecraft client (if you installed Minecraft from the Microsoft Store you need the bedrock version). Also the CPU and memory needs to be configured in accordance with the number of people you intend to invite to play on the server, I noticed that anything under 2 GB of memory and the server would have trouble starting.

Enough talk, the entire ARM template is uploaded on github, and I added a nice deploy to azure button in the readme over there. https://github.com/sjkp/azure-arm-aci-minecraft-server.

The cost of running the server can be calculated to around 5 cent per hour for the 1 CPU + 2 GB configuration, if you compare that with commercial Minecraft server hosting, then it is not cheap (you can get a similar configuration for 5$/month) – but this is not meant as competitor to those professional Minecraft hosting companies, maybe we can look into how we can compete with those prices in another blog post :).