Uptime Kuma in Azure Web App for Containers
Uptime Kuma ist ein self-hosted Monitoring System, das es erlaubt, die Verfügbarkeit von unterschiedlichen Services zu überwachen. Es bietet eine Vielzahl von Monitoring-Typen an, darunter für verschiedene Arten von HTTP-Endpunkte wie Websites oder REST-APIs.
Da es auch als fertiges Docker Image zur Verfügung steht, kann man es einfach als Azure App Service deployen. Für ein Ausrollen mittels Terraform genügt eine einfache Konfiguration.
Der Terraform-Code zu diesem Post findet sich auf Github: https://github.com/davull/uptime-kuma-azure-app-service
Azure App Service
Um einen Docker Container in Azure als Web App for Container zu betreiben, benötigen wir einen App Service, welcher in einem App Service Plan beheimatet ist. Alternativ kann man Container auch in Azure Container App
oder Azure Kubernetes Service
betreiben, eine Übersicht bietet Microsoft hier.
Damit die von Uptime Kuma gesammelten Daten (eine SQLite Datenbank) nicht bei jedem Neustart des Containers verloren gehen, persistieren wir sie in einem Storage Account.
Resource Group
Um die Ressourcen in Azure zu organisieren, legen wir eine neue Resource Group an. Dazu suchen wir im Azure Marketplace nach Recource Group
und klicken Create
.
Wir vergeben einen Namen, wählen eine Region und klicken Review + Create
. Anschließend können wir unsere Services innerhalb der Resource Group anlegen.
Storage Account
Beim Anlegen des Storage Accounts
wählen wir die zuvor erstellte Resource Group aus, legen Namen und Region fest und das Redundanz-Level. Für nicht-kritische Anwendungen genügt die günstigste Variante Local-redundant storage (LRS)
. Die übrigen Einstellungen können beibehalten werden.
Sobald unser Storage Account provisioniert ist, können wir ein File share
anlegen. Als Tier wählen wir Hot
, die Backup-Option können wir nach Bedarf an- oder abschalten.
App Service Plan und Web App for Container
Um einen App Service Plan
anzulegen, gehen wir analog vor. Als Operation System
wählen wir Linux
, der kleinste nicht kostenlose Pricing Plan Basic B1
genügt. Dieser schlägt mit ca. 13 € / Monat zu Buche. Er bietet 1.75 GB Arbeitsspeicher und 1 vCPU. Je nach Anzahl der zu überwachenden Services kann es sinnvoll sein, einen größeren Plan zu wählen. Ein Scale-Up ist aber auch später jederzeit möglich.
Nachdem nun ein App Service Plan und Storage zur Verfügung stehen, können den eigentlichen App Service anlegen. Um den Wizard zu starten, suchen wir im Azure Portal nach Web App for Containers
oder Web App
. Im Marketplace werden diese als unterschiedliche Einträge geführt, es handelt sich aber um den gleichen Service.
Als Publish-Methode wählen wir Docker
und als Operating System Linux
. Der hier gewählte Name ist auch zugleich die Subdomain, unter der der Service später verfügbar ist (<name>.azurewebsites.net).
Im nächsten Reiter Docker
wechseln wir die Image Source auf Docker Hub
und tragen das gewünschte Image inkl. Tag ein, z.B. louislam/uptime-kuma:latest
.
Nachdem wir den Wizard abgeschlossen haben, ruft Azure das Docker Image aus dem Hub ab und starten unseren Container. Beim ersten Start von Uptime Kuma dauert es einige Zeit, bis der Service läuft und die Webseite verfügbar ist. Unter dem Eintrag Deployment Center
im Reiter Logs
kann man den Prozess verfolgen.
Azure File Share mounten
Damit die Datenbank von Uptime Kuma nicht bei jedem Neustart des Containers verloren geht, mounten wir das zuvor angelegte File Share in den Container. Dazu wählen wir den Punkt Configuration
und wechseln in den Reiter Path mappings
. Dort fügen wir einen neuen Eintrag hinzu. Hier wählen wir den zuvor angelegten Storage Account und den für das File Share erstellten Storage Container aus. Als Storage Type wählen wir Azure File
. Der Pfad, unter dem das File Share im Container gemountet wird, muss /app/data
lauten. Hier legt Uptime Kuma seine Anwendungsdaten ab. Nach dem Speichern wird der Container neu gestartet die Daten landen nun in unserem Storage Container.
Rufen wir nun die Website der Web App auf, begrüßt uns Uptime Kuma mit dem Setup-Dialog, in dem wir den Admin-Nutzer anlegen können.
Terraform
Als Alternative zum Azure Portal bietet es sich an, die Konfiguration unserer Anwendung in bester Infrastructure as Code-Manier mittels Terraform zu verwalten. Hierzu bemühen wir den azurerm Provider. Die verschiedenen Arten zur Authentifizierung sind in der Dokumentation beschrieben. Wir legen die gleichen Ressourcen an, wie wir es im Portal getan haben.
Die gesamte Konfigurationsdatei sieht wie folgt aus:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.79"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg_kuma" {
name = var.resource_group_name
location = var.location
}
resource "azurerm_storage_account" "sa_kuma" {
name = var.storage_account_name
resource_group_name = azurerm_resource_group.rg_kuma.name
location = azurerm_resource_group.rg_kuma.location
account_tier = "Standard"
account_replication_type = "LRS"
min_tls_version = "TLS1_2"
}
resource "azurerm_storage_share" "share_kuma" {
name = "kumashare"
storage_account_name = azurerm_storage_account.sa_kuma.name
quota = var.storage_quota
access_tier = "Hot"
}
resource "azurerm_service_plan" "service_plan_kuma" {
name = "service-plan-kuma"
resource_group_name = azurerm_resource_group.rg_kuma.name
location = azurerm_resource_group.rg_kuma.location
os_type = "Linux"
sku_name = var.service_plan_sku
}
resource "azurerm_linux_web_app" "web_app_kuma" {
name = var.web_app_name
resource_group_name = azurerm_resource_group.rg_kuma.name
location = azurerm_resource_group.rg_kuma.location
service_plan_id = azurerm_service_plan.service_plan_kuma.id
https_only = true
site_config {
http2_enabled = true
minimum_tls_version = "1.2"
application_stack {
docker_image_name = var.docker_image
docker_registry_url = "https://index.docker.io"
}
}
app_settings = {
"DOCKER_ENABLE_CI" = "true"
}
storage_account {
access_key = azurerm_storage_account.sa_kuma.primary_access_key
account_name = azurerm_storage_account.sa_kuma.name
name = "webappstorage"
type = "AzureFiles"
share_name = azurerm_storage_share.share_kuma.name
mount_path = "/app/data"
}
}
Die Variablen werden in einer separaten Datei definiert.
variable "resource_group_name" {
type = string
}
variable "storage_account_name" {
type = string
}
variable "web_app_name" {
type = string
}
variable "location" {
type = string
default = "westeurope"
}
variable "storage_quota" {
type = number
default = 50
}
variable "service_plan_sku" {
type = string
default = "B1"
}
variable "docker_image" {
type = string
default = "louislam/uptime-kuma:latest"
}
In einer .tfvar
-Datei werde die Werte für die Variablen gesetzt.
resource_group_name = "rg-kuma"
storage_account_name = "<your-storage-account-name>"
web_app_name = "<your-web-app-name>"
Nun können wir mit einem einzigen Befehl die gesamte Umgebung erzeugen und auch wieder löschen.
terraform apply -var-file="terraform.tfvar"
terraform destroy -var-file="terraform.tfvar"