Unofficial community image for graphs1090, built with LinuxServer.io style container patterns (s6, hardened defaults, practical runtime options) for ADS-B performance graphing workloads. Sponsored and maintained by Blackout Secure.
Important
This repository is not an official LinuxServer.io image release. Want to help make it an officially supported LinuxServer.io Community image? Add your support in linuxserver/discussions/112.
Links: Docker Hub · Balena block · GitHub · Upstream graphs1090
- Quick Start
- Image Availability
- About The graphs1090 Application
- Supported Architectures
- Usage
- Parameters
- Volume Details
- Configuration
- User / Group Identifiers
- Application Setup
- Troubleshooting
- Health Monitoring
- Release & Versioning
- Resources
- License
docker run -d \
--name=graphs1090 \
--restart unless-stopped \
-e TZ=Etc/UTC \
-e GRAPHS1090_DECODER_DIR=/run/readsb \
-p 8080:8080 \
-v graphs1090-config:/config \
-v collectd-rrd:/var/lib/collectd/rrd \
-v /path/to/readsb/json:/run/readsb:ro \
blackoutsecure/graphs1090:latestAccess the web UI at http://<host-ip>:8080/graphs1090/.
For compose files, balena, and more examples, see Usage below.
Docker Hub (Recommended):
- All images published to Docker Hub
- Simple pull command:
docker pull blackoutsecure/graphs1090:latest - Multi-arch support: amd64, arm64
- No registry prefix needed (defaults to Docker Hub)
# Pull latest
docker pull blackoutsecure/graphs1090
# Pull specific version
docker pull blackoutsecure/graphs1090:1.0.1
# Pull architecture-specific (rarely needed)
docker pull blackoutsecure/graphs1090:latest@amd64graphs1090 generates performance graphs for readsb / dump1090-fa ADS-B receivers, providing visual insight into signal strength, message rate, aircraft count, range, CPU, and other metrics over time.
Author and maintenance credits (upstream):
- Primary upstream maintainer: wiedehopf (Matthias Wirth)
- Upstream repository and documentation: wiedehopf/graphs1090
This image is published as a multi-arch manifest. Pulling blackoutsecure/graphs1090:latest retrieves the correct image for your host architecture.
The architectures supported by this image are:
| Architecture | Tag |
|---|---|
| x86-64 | amd64-latest |
| arm64 | arm64v8-latest |
docker-compose (recommended, click here for more info)
---
services:
graphs1090:
image: blackoutsecure/graphs1090:latest
container_name: graphs1090
environment:
- TZ=Etc/UTC
- GRAPHS1090_DECODER_DIR=/run/readsb
volumes:
- config:/config
- collectd-rrd:/var/lib/collectd/rrd
- /path/to/readsb/json:/run/readsb:ro
ports:
- 8080:8080 # Web UI (HTTP)
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETUID
- SETGID
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp
- /run:exec
restart: unless-stopped
volumes:
config:
collectd-rrd:---
services:
readsb:
image: blackoutsecure/readsb:latest
container_name: readsb
environment:
- TZ=Etc/UTC
volumes:
- readsb-config:/config
- readsb-run:/run/readsb
devices:
- /dev/bus/usb:/dev/bus/usb
tmpfs:
- /tmp
- /run:exec
restart: unless-stopped
graphs1090:
image: blackoutsecure/graphs1090:latest
container_name: graphs1090
environment:
- TZ=Etc/UTC
- GRAPHS1090_DECODER_DIR=/run/readsb
volumes:
- graphs1090-config:/config
- collectd-rrd:/var/lib/collectd/rrd
- readsb-run:/run/readsb:ro
ports:
- 8080:8080
depends_on:
- readsb
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETUID
- SETGID
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp
- /run:exec
restart: unless-stopped
volumes:
readsb-config:
readsb-run:
graphs1090-config:
collectd-rrd:docker-cli (click here for more info)
docker run -d \
--name=graphs1090 \
-e TZ=Etc/UTC \
-e GRAPHS1090_DECODER_DIR=/run/readsb \
-p 8080:8080 \
-v /path/to/graphs1090/config:/config \
-v /path/to/collectd/rrd:/var/lib/collectd/rrd \
-v /path/to/readsb/json:/run/readsb:ro \
--restart unless-stopped \
blackoutsecure/graphs1090:latestThis image can be deployed to Balena-powered IoT devices using the included docker-compose.yml file (which contains the required Balena labels):
- Balena block listing: https://hub.balena.io/blocks/2352746/graphs1090
balena push <your-app-slug>For deployment via the web interface, use the deploy button in this repository. See Balena documentation for details.
| Parameter | Function |
|---|---|
-p 8080:8080 |
Web UI (HTTP) |
| Parameter | Function | Required |
|---|---|---|
-e TZ=Etc/UTC |
Timezone (TZ database) | Optional |
-e GRAPHS1090_DECODER_DIR=/run/readsb |
Path to decoder JSON directory (stats.json, aircraft.json) |
Optional |
-e GRAPHS1090_UAT_DIR= |
Path to 978 MHz UAT decoder directory (enables UAT graphs) | Optional |
-e GRAPHS1090_PORT=8080 |
HTTP port for the web UI | Optional |
-e GRAPHS1090_USER=abc |
Runtime user | Optional |
-e PUID=911 |
User ID for file ownership | Optional |
-e PGID=911 |
Group ID for file ownership | Optional |
| Parameter | Function | Required |
|---|---|---|
-v /config |
Persistent configuration | Recommended |
-v /var/lib/collectd/rrd |
RRD database storage — preserves graph history across restarts | Recommended |
-v /run/readsb |
Decoder JSON input directory (mount read-only) | Required |
The container uses three volumes:
- Purpose: Stores persistent configuration and application state
- Example:
-v /path/to/graphs1090/config:/configor-v graphs1090-config:/config
- Purpose: Preserves graph history (RRD databases) across container restarts
- Example:
-v /path/to/collectd/rrd:/var/lib/collectd/rrdor-v collectd-rrd:/var/lib/collectd/rrd
- Purpose: Read-only mount of the decoder JSON output directory from readsb or dump1090-fa
- Required files:
stats.json,aircraft.json - Example:
-v /path/to/readsb/json:/run/readsb:ro
Environment variables are set using -e flags in docker run or the environment: section in docker-compose.
The graphs1090 config file is /etc/default/graphs1090 inside the container. To customize, either mount a file into the container or edit it via docker exec.
| Variable | Default | Description |
|---|---|---|
colorscheme |
default |
Color scheme: default or dark |
range |
nautical |
Range unit: nautical, statute, or metric |
fahrenheit |
0 |
Set to 1 for Fahrenheit |
graph_size |
default |
Graph size: small, default, large, huge, custom |
WWW_TITLE |
graphs1090 |
Browser tab title |
WWW_HEADER |
Performance Graphs |
Page heading |
DRAW_INTERVAL |
60 |
Graph redraw interval in seconds |
HIDE_SYSTEM |
no |
Set yes to hide system resource graphs |
disk |
(blank) | Block device for disk I/O graphs (e.g. mmcblk0) |
ether |
(blank) | Network interface for wired stats (e.g. eth0) |
enable_scatter |
no |
Enable scatter plot data collection |
All options: upstream default config
volumes:
- ./my-graphs1090-config:/etc/default/graphs1090:roBy default, this container runs as the LSIO abc user (non-root) for better security isolation. The abc user is created by the LinuxServer.io base image with UID/GID 911 and remapped at container start via PUID/PGID.
- collectd, graphs1090, and nginx all run as the
abcuser — no root privileges required for normal operation. - Set
PUIDandPGIDonly if you need file ownership on/configand/var/lib/collectd/rrdto match a specific host user. - The mounted decoder JSON directory (
/run/readsb) is read-only — graphs1090 never writes to your decoder's output.
The container runs three services under s6-overlay:
- collectd — polls the decoder's JSON output every 60 seconds via Python plugins and writes metrics to RRD databases
- graphs1090 — periodically generates PNG graph images from the RRD data with escalating intervals (1 min, 5 min, 15 min, 60 min depending on graph timespan)
- nginx — serves the HTML interface and graph images
During normal operation, collectd writes to /run/collectd (memory-backed tmpfs) to minimize disk I/O.
On container start, RRD data is restored from /var/lib/collectd/rrd/localhost.tar.gz to memory, with a fallback cascade: primary tarball, raw folder, this week's auto-backup, last week's auto-backup, or fresh start.
On container stop, RRD data is compressed and written back to disk. A weekly rotating backup is kept automatically with 60-day retention.
-
Verify the decoder JSON directory is mounted and populated:
docker exec graphs1090 ls -la /run/readsb/ docker exec graphs1090 head -c 200 /run/readsb/stats.json
-
If
stats.jsonis missing, the decoder container is not providing data. Check that:- The readsb/dump1090-fa container is running
- The shared volume is mounted correctly (not an empty volume)
- The decoder is writing JSON output
Initial data collection takes up to 10 minutes. Graphs with longer timespans (7-day, 30-day) will fill in gradually.
Map to a different host port:
docker run ... -p 8081:8080 ...docker logs graphs1090
docker logs graphs1090 --tail 100 -fdocker exec graphs1090 s6-svstat /run/service/svc-collectd
docker exec graphs1090 s6-svstat /run/service/svc-graphs1090
docker exec graphs1090 s6-svstat /run/service/svc-nginx- Check upstream graphs1090 documentation
- Review container logs:
docker logs -f graphs1090 - Open an issue on GitHub
The container includes built-in health monitoring at multiple levels:
The image includes a HEALTHCHECK that performs an HTTP GET against the nginx web UI (http://127.0.0.1:${GRAPHS1090_PORT:-8080}/graphs1090/). Docker marks the container as unhealthy after 3 consecutive failures.
| Setting | Value |
|---|---|
| Interval | 30s |
| Timeout | 5s |
| Start period | 30s |
| Retries | 3 |
# Check container health status
docker inspect --format='{{.State.Health.Status}}' graphs1090
# View health check history
docker inspect --format='{{json .State.Health}}' graphs1090 | jq .All long-running services are supervised by s6-overlay and automatically restarted on crash:
# Check individual service status
docker exec graphs1090 s6-svstat /run/service/svc-collectd
docker exec graphs1090 s6-svstat /run/service/svc-graphs1090
docker exec graphs1090 s6-svstat /run/service/svc-nginx# Container health
docker inspect --format='{{.State.Health.Status}}' graphs1090
# Confirm decoder JSON input is reaching the container
docker exec graphs1090 ls -la /run/readsb/
docker exec graphs1090 head -c 200 /run/readsb/stats.json
# Web UI reachability from inside the container
docker exec graphs1090 wget -qO- http://127.0.0.1:8080/graphs1090/ | head -n 5
# Service uptime (all services)
docker exec graphs1090 s6-svstat /run/service/svc-collectd
docker exec graphs1090 s6-svstat /run/service/svc-graphs1090
docker exec graphs1090 s6-svstat /run/service/svc-nginxThis project uses semantic versioning:
- Releases published on GitHub Releases
- Multi-arch images (amd64, arm64v8) built automatically
- Docker Hub tags: version-specific,
latest, and architecture-specific
Update to latest:
docker pull blackoutsecure/graphs1090:latest
docker-compose up -d # if using composeCheck image version:
docker inspect -f '{{ index .Config.Labels "build_version" }}' blackoutsecure/graphs1090:latest- Docker Hub: blackoutsecure/graphs1090
- Balena block: hub.balena.io/blocks/2352746/graphs1090
- Issues / bug reports: GitHub Issues — include Docker version, container logs, and reproduction steps.
- Releases: GitHub Releases
- Upstream: wiedehopf/graphs1090 · wiedehopf/readsb
- Container base: LinuxServer.io · Discord
- References: ADS-B Overview · RRDtool Documentation
MIT — see LICENSE. The upstream graphs1090 project is also MIT licensed.
Sponsored and maintained by Blackout Secure.
