Your fleet, live.

A real-time web UI for Docker, remote hosts and Kubernetes, in one small binary.

Run it next to your Docker socket
docker run -d --name fleetops -p 9000:9000 \
  -v fleetops-data:/data \
  -v /var/run/docker.sock:/var/run/docker.sock \
  --group-add "$(stat -c %g /var/run/docker.sock)" \
  fleets/fleetops

Replay: one container failure, fixed in FleetOps

14:01:58. All 12 containers are running on prod-eu. Press play, or press j to step.

Manages

Thirty seconds, five things it did right.

Each moment in the replay is a feature you would use on a bad afternoon.

  1. Live by default

    Lists and detail pages follow Docker's own events over one websocket. Only the rows on screen subscribe to stats. When the connection drops, the page says so and how old its data is; it never passes stale state off as current.

    Updates
    Docker events, Kubernetes watches
    Polling
    None for lists
    Disconnected
    Said plainly, with the data's age
  2. Hands stay on the keys

    The attention bay is a list you walk, not a table you scan. The command palette finds any container, image or Kubernetes object and runs an action on it.

    j k
    Next and previous strip
    ↵
    Open its logs
    ⌘ K
    Jump to anything, act on it
    /
    Filter the list
  3. A log viewer that keeps up

    Virtualized to the newest 200,000 lines, with follow mode that pauses when you scroll up. A reconnect or a restart picks up where the log left off, without repeating lines.

    Search
    Text or regex, next and previous
    Streams
    stdout and stderr toggles
    Colour
    ANSI, as the app wrote it
    Export
    Lines shown, or the full log
  4. Honest when it matters

    Recreate a container with changes and, if the new one fails to start, FleetOps rolls back to the old one. The terminal never silently starts a new shell after a dropped connection, and Docker's error messages are shown exactly as Docker wrote them.

    Recreate
    Rolls back on a failed start
    Duplicate
    Host ports cleared, no clash
    Terminal
    Resize, shell detection, no respawn
  5. Every change on the record

    Every mutating action, every terminal session and every refused request is in the audit log with who did it. Roles are per environment, and on Kubernetes a role can be limited to some namespaces. All of it is in the free edition.

    Viewer
    Reads lists, logs, stats, YAML
    Operator
    Also changes things, opens terminals
    Admin
    Users, environments, access

One UI past one host.

Add remote Docker hosts and Kubernetes clusters next to the local socket. Each gets its own colour and tag, so you always know where you are before you press restart.

PEprod-euDockerLocal socket12 running
E2edge-02DockerAgent, dialled out4 running
SKstaging-k8sKubernetesIn-cluster agent31 pods
LBlabDockerPodman socket3 running

Remote hosts run fleetops-agent, which dials out to the server. The host opens no port and never exposes its Docker socket. Logs, terminals, stats and image builds work there exactly as they do locally.

Kubernetes clusters connect by kubeconfig or an in-cluster agent. Lists follow watch streams; every YAML edit is a dry run shown as a diff before anything is written. Helm releases install, upgrade, roll back and uninstall with the same review step.

Everything that works across environments

Made for the teams that run the hosts.

Five situations FleetOps was designed around.

All solutions

The same afternoon, from the command line.

FleetOps does not replace the CLI. It saves you from typing it under pressure.

StepWith the docker CLIWith FleetOps
Find what brokedocker ps -a | grep -v UpIt is already at the top, under Needs attention.
Read whydocker logs --tail 500 -f orders-apiEnter. 200,000 lines, regex search, nothing repeated on reconnect.
Fix it safelydocker inspect, docker rm, docker run … by handRecreate with the change. A failed start rolls back to the old one.
Say who did itScroll the incident channelIn the audit log, with the user, the target and the outcome.

A socket is root. FleetOps treats it that way.

Every touch of a Docker host is signed in, allowed by a role and written down.

How it is secured
Signed in, every route
Sessions and CSRF on every Docker call; the socket is never anonymous.
Agents dial out
Remote hosts open no port and never expose their socket.
Written down
Every change, terminal session and refused request, with who did it.
No call home
Offline licenses, no telemetry, a distroless non-root image.

Weight is a feature.

A Rust binary with the web UI and a SQLite database inside. Nothing else to run, nothing to upgrade in lockstep.

What you deploy
ServerOne static binary, about 15–17 MBlinux/amd64, linux/arm64
ImageAbout 8 MB compressed per platformdistroless, runs as non-root
StorageOne SQLite file in WAL modeno external database
Memory targetUnder 50 MB idle with about 50 containersa design target, not a benchmark
Heavy partsTerminal and charts load only when openedper tab, on demand

Free to run. Priced by the node when you grow.

Community has no node or user limit. Paid plans add the Enterprise parts and support.

Compare plans

Yearly billing: Starter $99, Scale $199 per 5 nodes. Full pricing

See your own containers in a minute.

Run it next to your Docker socket
docker run -d --name fleetops -p 9000:9000 \
  -v fleetops-data:/data \
  -v /var/run/docker.sock:/var/run/docker.sock \
  --group-add "$(stat -c %g /var/run/docker.sock)" \
  fleets/fleetops