Monitoring Containers Uptime With Curl

Updated 2024/06/05

Monitoring the uptime of services is a critical task for maintaining their reliability and availability. You want to catch failures as they occur, not when a user complains the app is down!

A great way to monitor the uptime of a containerized services is to have them perform “push” health checks, where the service sends requesta at fixed intervals to an external monitoring system to indicate that it is still operational.

In this blog post, we will walk through adding a snippet to a Docker Compose file to monitor the uptime of a Wireguard VPN link. We will use curl to perform push health checks on an uptime-kuma instance through the tunnel; if curls stop going through, the link’s down.

Before we get started, let’s review some key concepts that are important to understand:

  • Docker Compose: A tool for defining and running multi-container Docker applications. Docker Compose makes it easy to create and manage complex environments by allowing you to define them in a simple YAML file.
  • curl: A command-line tool for transferring data over various network protocols, including HTTP and HTTPS. curl can be used to retrieve data from a web server or to send data to a web server.
  • Wireguard: A fast, secure, and easy-to-use VPN protocol that allows you to create encrypted connections between devices. Wireguard can be used to securely connect devices over the internet, even if they are behind firewalls or NATs.
  • Uptime-kuma: An open-source project that provides a web-based dashboard for monitoring the uptime of services. Uptime-kuma supports various types of health checks, including ping, HTTP, and TCP.

Now, let’s dive into setting things up.

1. Setup a new uptime-kuma monitor

The first step is obviously to setup a new PUSH monitor in your uptime-kuma instance or an equivalent service, such as healthcheck.io.

Here’s an example:
uptime-kuma-push-docker-monitor

2. Append your existing Docker Compose file and add the health check snippet

  curl:
    image: ubuntu:latest
    entrypoint: ""
    command: >
      bash -c "apt-get update &&
               apt-get install -y curl &&
               while true; do
                 curl https://<uptime-kuma-push-url>
                 sleep 60;
               done"      
    restart: unless-stopped
    depends_on:
      - wireguard
    network_mode: service:wireguard
    mem_limit: 1024m
    cpus: 1

This Docker Compose snippet defines a standard ubuntu image. The image does not natively come with curl, which is why we install it when bringing up the container. Now, best practices would suggest we build a custom image or use an image that natively includes curl, but I’ve found this approach reasonable performance-wise given that installing curl is a very lightweigh task anyway.

We therefore run a Bash script that performs the following tasks:

  • Installs the curl package via apt-get.
  • Runs an infinite loop that sends an HTTP POST request to the uptime-kuma instance every five minutes (300 seconds). The <uptime-kuma-push-url> placeholder should be replaced with the appropriate values for your specific setup.

We are also specifying network_mode: service:wireguard to ensure all curl commands - for that matter, all network-related task for of that container - go through the Wireguard link we want to monitor. If the link is done, curl will stop reaching uptime-kuma and we’ll be getting a notification accordingly.

3. Start the Docker Compose environment

docker-compose up -d

4. Verify that the push health checks are being sent by checking the uptime-kuma dashboard and reviewing the logs

In uptime-kuma, you should see HTTP POST coming in:

uptime-kuma-push-docker-health

The logs should show output for installing curl first, then for the curl HTTP POST that run at regular intervals.

> $ docker logs --follow project-curl-1
Get:1 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy InRelease [270 kB]
Get:3 http://security.ubuntu.com/ubuntu jammy-security/multiverse amd64 Packages [44.6 kB]
[...]
Setting up libcurl4:amd64 (7.81.0-1ubuntu1.16) ...
Setting up curl (7.81.0-1ubuntu1.16) ...
[...]
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    11  100    11    0     0     76      0 --:--:-- --:--:-- --:--:--    77
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    11  100    11    0     0     87      0 --:--:-- --:--:-- --:--:--    88
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    11  100    11    0     0     78      0 --:--:-- --:--:-- --:--:--    78

Wrap-up!

That’s it! With this Docker Compose file, we can easily monitor the uptime of a Wireguard VPN link with push health checks using curl. The same logic and compose file would work with other services implementing “push”/passive healthchecks through curl, such as Healthcheck.io.

One final note: when using push health checks to monitor services, it’s important to consider the frequency and duration of the health checks. Sending health checks too frequently can unnecessarily increase network traffic and put unnecessary load on the monitoring system. On the other hand, sending health checks too infrequently can lead to long periods of downtime before the monitoring system detects a problem. As a guideline, we recommend sending push health checks at least once every 5 minutes, and no more than once every minute. This frequency should provide sufficient monitoring coverage while minimizing the impact on network traffic and system load.