A read-only container monitor for the terminal. It shows what docker stats shows, plus the VRAM each container holds.

  NAME                STATUS      ↻   UPTIME      CPU%   MEM_GB  VRAM_GB
────────────────────────────────────────────────────────────────────────
▼ llm-inference       ● running       47m        81.5%    11.2G    18.7G
  ├             cur        min        max
  ├ CPU       81.5%      12.3%      95.2%  ▃▅▆▇▆▅▇▇▆▅▄▆▇▇▆▅▆▇█▇▆▅▄▃▅▆▇▆▅▇
  ├ MEM       11.2G      10.8G      11.5G  ▆▆▇▇▆▆▇▇▆▆▇▇▆▆▇▇▆▆▇▇▆▆▇▇▆▆▇▇▆▆
  ├ VRAM      18.7G      17.2G      19.1G  ▆▆▆▆▇▇▇▆▆▆▆▇▇▇▆▆▆▇▇▇▆▆▆▆▇▇▇▆▆▇
  ├ NET↑     5 KB/s     2 KB/s    12 KB/s  ▁▁▂▁▁▂▁▁▂▁▁▂▁▁▂▁▁▂▁▁▂▁▁▂▁▁▂▁▁▂
  └ NET↓     8 KB/s     4 KB/s    15 KB/s  ▂▁▂▃▁▂▁▃▂▁▂▃▄▂▃▂▁▃▂▁▂▁▂▃▁▂▃▂▁▂
  ml-worker           ● running       1h 12m     43.2%     6.8G     4.2G
  postgres-db         ● healthy       2d 4h       2.1%     1.4G        -
▼ crashed-job         ✗ exited    ↻ 7 3m          0.0%     0.0G        -
  ├             cur        min        max
  ├ CPU        0.0%       0.0%       0.0%  ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
  ├ MEM        0.0G       0.0G       0.0G  ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
  ├ NET↑      0 B/s      0 B/s      0 B/s  ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
  └ NET↓      0 B/s      0 B/s      0 B/s  ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
  ├ ── logs ────────────────────────────────────────────────────────────
  ├ Error: CUDA out of memory. Tried to allocate 2.00 GiB
  ├ Traceback (most recent call last):
  ├   File "train.py", line 47, in run_epoch
  └     raise RuntimeError("GPU allocation failed")
  nginx-proxy         ● running   ↻ 2 2d 4h       0.3%     0.1G        -
  redis-cache         ● running       2d 4h       0.1%     0.2G        -

Background

docker stats exposes CPU and memory. nvidia-smi exposes total GPU utilization and VRAM by process PID. Neither tells you which container is consuming how much VRAM. Getting from a PID to a container requires walking from State.Pid through /proc/{pid}/cgroup and matching the cgroup scope against the NVML process list. cgroup v2 systemd format is docker-{container_id}.scope, revealing the mapping.

Motivation

When running multiple inference containers on a single GPU node, watch docker stats is not enough, and nvidia-smi does not know about containers. Correlating the two by hand is annoying at best, and frustrating when things are crashing. This friction should not exist.

What Boje Does

A terminal UI for docker ps. Fixed-column list of running containers with live CPU, memory, net I/O, and per-container VRAM. Select a container to expand inline cur/min/max statistics and a 30-sample sparkline per metric. Press l for a live log tail without leaving the view.

Implementation

Rust with ratatui for rendering and bollard for the Docker API. NVML is synchronous and runs on a dedicated thread rather than on the tokio runtime to avoid blocking the event loop.

The VRAM-per-container mapping is re-derived each tick from cgroup v2 scopes, which handles container restarts without special-casing.

Linux only; requires cgroup v2 and systemd.