Continuous Internet Performance Monitoring via Docker-Based Speedtest and Grafana Orchestration

The necessity of maintaining high-bandwidth, low-latency connectivity has transitioned from a luxury to a fundamental requirement for modern digital infrastructure. Whether managing a remote workforce, hosting high-availability microservices, or maintaining a sophisticated home laboratory, the ability to verify that an Internet Service Provider (ISP) is delivering the promised throughput is critical. Relying on manual, sporadic speed tests is insufficient for identifying intermittent packet loss, jitter spikes, or periodic throttling. To address this, a continuous, automated monitoring stack can be deployed using containerized technologies. By leveraging Docker to orchestrate a suite of tools including Speedtest CLI runners, time-series databases like InfluxDB or Prometheus, and visualization engines like Grafiona, administrators can establish a historical record of network performance. This allows for the identification of patterns in ISP downtime and the accumulation of forensic evidence when service level agreements (SLAs) are not met.

Architecting the Monitoring Stack

A robust network monitoring architecture relies on three distinct functional layers: the Data Collector (the runner), the Data Persistence Layer (the database), and the Visualization Layer (the dashboard). In a Dockerized environment, these layers are decoupled, allowing for modular updates and scalable configurations.

The Data Collector acts as the active agent. It utilizes tools such as the Ookla Speedtest CLI to execute periodic network probes. These probes measure several key metrics: download speed, upload speed, latency, and jitter. The frequency of these tests is a critical configuration parameter; setting the interval too low can consume excessive bandwidth and generate unnecessary noise, while setting it too high might miss transient period of degradation.

The Data Persistence Layer is responsible for storing the high-cardinality time-series data generated by the collector. In many implementations, InfluxDB serves as the primary repository. InfluxDB is optimized for time-stamped data, making it ideal for tracking how download speeds fluctuate over weeks or months. Alternatively, for environments already utilizing a Prometheus ecosystem, exporters can be used to bridge speedtest results into Prometheus metrics.

The Visualization Layer, typically Grafana, queries the persistence layer to render human-readable graphs. A well-configured Grafana dashboard does not merely show current speeds; it provides context through historical trends, heatmaps of latency, and comparative analysis across different test servers or client hosts.

Deployment Strategies for Speedtest Tracker

The "Speedtest Tracker" approach focuses on a self-hosted application designed specifically to monitor internet performance and uptime. This implementation is particularly effective for users who require a turnkey solution for building a history of ISP performance.

The primary utility of this containerized application is the ability to provide verifiable data regarding the performance of the internet connection. By using distributed test servers across the globe, the tracker can determine if a slowdown is local to the user's network or a broader issue with the ISP's infrastructure.

Core Metrics and Capabilities

The Speedtest Tracker monitors several critical indicators of network health:

  • Download speed: The rate at which data is received from the internet.
  • Upload speed: The rate at which data is sent to the internet.
  • Latency: The time delay in a communication through the network, measured in milliseconds.
  • Jitter: The variation in latency over time, which is crucial for real-time applications like VoIP or gaming.
  • Uptime: The continuous duration of connection availability, used to track ISP reliability.

Configuration and InfluxDB Integration

For advanced users, the tracker can be configured to export results directly into an InfluxDB instance. This integration enables the use of complex Grafana dashboards that can perform advanced SQL-like queries on the stored data.

A common deployment workflow involves:

  1. Initializing the Docker environment with the desired container images.
  2. Configuring the connection strings for InfluxDB (host, database name, username, and password).
  3. Setting the frequency of the speedtest execution via environment variables.

Implementation via Docker-Compose and Environment Variables

For those seeking a more granular control over the monitoring stack, a docker-compose configuration can be used to orchestrate a stack consisting of Grafana, InfluxDB, and a Speedtest.net CLI runner. This method allows for the precise definition of network bridges and volume mounts for persistent data storage.

Environment Variable Configuration

The behavior of the Speedtest container and the associated services is governed by environment variables. Precise configuration of these variables is essential for the stability of the monitoring service.

| Environment Variable | Default Value | Description |
| --- | --- and --- | --- |
| GRAFANAPORT | 3000 | The port on the host system used to access the Grafana web interface. |
| SPEEDTEST
SPEEDTESTINTERVAL | 3600 | The duration, in seconds, between consecutive speed tests. |
| SPEEDTEST
HOST | local | The display name assigned to the client being tested. |
| SPEEDTESTSERVER | none | An optional specific Speedtest.net server ID to force a test against a particular location. |
| INFLUXDB
DB | speedtest | The name of the specific database within InfluxDB where results are stored. |
| INFLUXDBHOST | influxdb | The network hostname or container name of the InfluxDB instance. |
| INFLUXDB
USERNAME | root | The authentication username for the InfluxDB service. |
| INFLUXDB_PASSWORD | root | The authentication password for the InfluxDB service. |

Deployment Workflow

To deploy a pre-configured stack, the following terminal commands are utilized:

  1. Clone the repository containing the configuration files:
    git clone https://github.com/frdmn/docker-speedtest-grafana
  2. Navigate to the directory:
    cd docker-speedtest-grafana
  3. Prepare the environment file by copying the sample:
    cp .env.sample .env
  4. Adjust the .env file with the appropriate credentials and intervals.
  5. Execute the deployment:
    docker-compose up -d

The deployment process will result in the creation and initialization of the following containers:
- speedtest_influxdb_1
- speedtest_grafana_1
- speedtest_speedtest_1

To manage the lifecycle of these containers, users can use standard Docker commands. For example, to stop the entire stack:
docker-compose stop

To perform an update on the images and recreate the containers:
docker-compose pull
docker-compose rm
docker-compose up -d

Advanced Prometheus and Grafana Integration

In more complex DevOps environments, integrating speedtest metrics into an existing Prometheus/Grafana stack is preferred. This involves using a Prometheus exporter that translates speedtest results into Prometheus-compatible metrics.

Prometheus Exporter Setup

The jraviles/prometheus_speedtest:latest image can be deployed to act as a collector that exposes metrics on a specific port. The deployment requires a shared Docker network to allow Prometheus to scrape the exporter.

The command to run the exporter is:
docker run -d --net prometheus_network -p 9516:9516/tcp --name prometheus_speedtest jraviles/prometheus_speedtest:latest

Configuring Prometheus Scrape Jobs

Once the exporter is running, the prometheus.yml configuration file must be updated to include a new job that targets the exporter's endpoint. The configuration must specify the metrics_path and the static_configs for the targets.

A sample prometheus.yml configuration is as follows:

```yaml
global:
scrapeinterval: 2m
scrape
timeout: 2m

scrapeconfigs:
- job
name: 'speedtest'
metricspath: /probe
static
configs:
- targets: ['prometheus_speedtest:9516']
```

After updating the configuration, the Prometheus container must be restarted or reloaded to recognize the new job. The deployment command for Prometheus would look like this:

docker run -d --net prometheus_network -p 9090:9090/tcp -v $PWD/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml --name prometheus prom/prometheus:latest

Multi-Server Monitoring via Script Exporters

For advanced users who need to monitor the latency and throughput of multiple geographic locations simultaneously, a custom approach using script_exporter or a modified Prometheus exporter is possible. This involves passing a list of specific Speedtest server IDs to the container.

In a specialized implementation, the billimek/prometheus-speedtest-exporter:latest image can be configured with an environment variable containing a comma-separated list of server IDs:

yaml speedtest: image: "billimek/prometheus-speedtest-exporter:latest" restart: "on-failure" ports: - 9469:9469 environment: - server_ids=3855,1782,2225

In this example, the exporter will sequentially test against DTAC Bangkok (3855), Comcast Seattle (1782), and Telstra Melbourne (2225). The resulting metrics are then labeled with the server_id, allowing for highly granular dashboarding:

  • speedtest_latency_seconds{server_id="3855"} 17.363
  • speedtest_download_bytes{server_id="1782"} 5852661

Data Visualization and Dashboard Configuration

The final stage of the pipeline is the configuration of Grafana. Whether using InfluxDB or Prometheus as a data source, the goal is to create a dashboard that provides actionable insights.

Grafana Dashboard Deployment

Dashboards are often distributed as dashboard.json files. To implement a pre-made dashboard, such as the Speedtest dashboard (ID 13053 or 13306), the user must upload the exported JSON file into the Grafana interface.

For InfluxDB-based setups, the dashboard relies on Flux or InfluxQL queries. A critical aspect of these queries is the use of the WHERE clause to filter data by specific hosts or tags. For example, to view the download time series for a specific local client:

sql SELECT mean("value") FROM "download" WHERE $timeFilter and host = 'local' GROUP BY time($interval) fill(null)

Data Tagging for Granular Analysis

To maximize the utility of the historical data, the collector should be configured to attach metadata tags to each measurement. This allows users to pivot their analysis based on various dimensions. Recommended tags include:

  • isp: The name of the service provider.
  • external_ip: The public-facing IP address of the tester.
  • server_id: The unique identifier of the test server.
  • server_name: The human-readable name of the test server.
  • server_location: The geographic location of the test server.
  • speedtest_url: A direct link to the test results for individual verification.

Maintenance and Operational Best Practices

Running a continuous monitoring service requires adherence to operational standards to ensure data integrity and system availability.

Container Lifecycle Management

It is vital to periodically update the container images to ensure that the Speedtest CLI and the Grafana engine are patched against security vulnerabilities and include the latest performance improvements. A regular maintenance cycle should include:

  • Pulling the latest images: docker-compose pull
  • Removing orphaned containers: docker-compose rm
  • Verifying logs for errors: docker-compose logs -f

Resource Management and Optimization

The kjake/internet-speedtest-docker image demonstrates an optimization pattern where unnecessary components are excluded to slim down the image size and reduce the attack surface. This "slimming down" process is essential for deployment in resource-constrained environments like edge gateways or low-power Raspberry Pi devices.

Furthermore, when deploying in a production-like environment, it is recommended to use a dedicated Docker network for the monitoring stack. This prevents the monitoring containers from being exposed to the host's primary network unless explicitly required, providing an additional layer of isolation.

Technical Analysis of the Monitoring Ecosystem

The implementation of a Dockerized Speedtest and Grafana stack represents a significant shift from reactive to proactive network management. By utilizing a time-series-centric architecture, administrators move away from anecdotal evidence of "slow internet" toward a mathematically verifiable record of network performance.

The architectural strength of this solution lies in its modularity. The separation of the collection agent (Speedtest CLI), the storage engine (InfluxDB/Prometheus), and the visualization engine (Grafana) allows for independent scaling. For instance, an organization could expand their monitoring from a single local client to hundreds of global edge locations by simply deploying more exporter containers and updating the Prometheus scrape configuration.

However, the complexity of this setup introduces new challenges in configuration management. The reliance on environment variables for critical parameters like INFLUXDB_PASSWORD or SPEEDTEST_SERVER necessitates a robust secret management strategy. Furthermore, the precision of the scrape_interval must be balanced against the computational overhead of the monitoring stack itself. A too-frequent interval could inadvertently cause the monitoring system to compete with actual network traffic for bandwidth, thereby skewing the very metrics it intends to measure.

In conclusion, the deployment of a containerized speedtest monitoring stack is a sophisticated undertaking that provides unparalleled visibility into network reliability. Through the strategic use of Docker, InfluxDB, and Grafana, users can transform transient network fluctuations into permanent, actionable data, ensuring that the infrastructure of the future remains resilient and performant.

Sources

  1. Speedtest Tracker Documentation
  2. Docker Speedtest Grafana Repository
  3. Grafana Dashboard 13053
  4. Grafana Dashboard 13306
  5. kjake Internet SpeedTest Docker
  6. Prometheus Speedtest Dashboard Implementation

Related Posts