DockerMap is a local web app that helps you understand what is running on one self-hosted machine.
It shows Docker containers, Compose files, host services, ports, volumes, logs, and related runtime signals in one place. The goal is simple: when something is running on your server, DockerMap should help you answer what it is, what its recorded Compose start order declares, where its data lives, and what would change if you edited a Compose mount or routing rule.
DockerMap is read-only today. It inspects your machine, but it does not restart services, change containers, edit Compose files, or delete data.
The supported private-alpha path is the split Docker Compose deployment. Create a protected environment file outside the checkout so the required browser and daemon credentials are never stored in Git:
sudo install -d -m 0700 /etc/dockermap
sudo sh -c 'umask 077; printf "DOCKERMAP_API_TOKEN=%s\nDOCKERMAP_DAEMON_TOKEN=%s\nDOCKER_GID=%s\n" "$(openssl rand -hex 32)" "$(openssl rand -hex 32)" "$(stat -c %g /var/run/docker.sock)" > /etc/dockermap/dockermap.env'
sudo docker compose --env-file /etc/dockermap/dockermap.env \
-p dockermap-alpha2 up --build -dThen open:
http://127.0.0.1:3233
For local compatibility testing, the less-isolated single-container image also works with the same protected credentials:
docker build -t dockermap:local .
docker run --rm --env-file /etc/dockermap/dockermap.env \
-p 127.0.0.1:3233:3233 \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
dockermap:localThe frontend port is bound to loopback and the browser API requires the token
stored in /etc/dockermap/dockermap.env. The collector has no host-published
port. Follow the exact-ref clean-host, smoke, reboot, rollback, and reinstall
procedure in Docker setup before treating a build
as release evidence.
That Docker socket mount is passed to the Docker Read Gateway. A read-only mount does not make the Docker API read-only, so the gateway independently limits it to the reviewed inventory and bounded-log reads. Plain Docker is a local compatibility profile; use the split Compose deployment for component isolation.
Use this path if you are developing DockerMap or want the three local services running directly on your machine.
Requirements:
- Node.js 22.x LTS
- npm
- Rust, using the version pinned in rust-toolchain.toml
- Docker for live runtime data. Without Docker, the API is unavailable by default;
synthetic mock fallback requires the explicit test/internal opt-in
DOCKERMAP_ALLOW_MOCK=true(separate from the browser's Demo Mode).
Install and start the local stack:
npm install
npm run dev:stackThis starts:
- Web app:
http://127.0.0.1:3233 - Node API:
http://127.0.0.1:4000 - Rust daemon:
http://127.0.0.1:4100
- See containers, images, networks, volumes, and logs.
- See Compose files, declared mounts, named volumes, and dry-run edit plans.
- See a broader runtime map when host tools are available, including systemd, cron, PM2, tmux, listening sockets, Tailscale or Headscale, reverse-proxy markers, and local DNS markers.
- Use the Runtime Map workspace to inspect provider nodes, diagnostics, and cross-provider edges in one read-only view.
- Compare what Compose says should exist with what Docker is actually running.
- Review up to 64 identity-free container inventory deltas retained during the current daemon process. These are snapshot observations, not persistent Docker events or causal/deployment claims.
- Use mock fallback data when Docker is not available AND mock fallback is
enabled. When the daemon is unreachable, the Node API substitutes
route-local mock responses ONLY when
DOCKERMAP_ALLOW_MOCK=true(the hardened deployment runs with itfalse, so daemon-unreachable routes return errors instead of fabricated data); with it enabled, the responses are stampedmode: mock/source: "mock"so consumers can tell the bytes are sample data. Separately, the browser can enter Demo Mode, which serves fabricated sample data entirely inside the web app (no API calls) so the UI can be inspected without any backend.
DockerMap is for understanding a host, not controlling it. Write actions are planned only after diff previews, backups, confirmations, and rollback behavior exist.
If the app opens but looks empty:
-
Confirm Docker is running.
-
Confirm the Docker socket is mounted when using Docker:
/var/run/docker.sock:/var/run/docker.sock:ro -
Check the API health endpoint:
http://127.0.0.1:4000/api/health -
Check the daemon health endpoint:
http://127.0.0.1:4100/daemon/health
If Docker is not reachable and DOCKERMAP_ALLOW_MOCK=true, DockerMap can serve
explicitly stamped mock fallback data so the UI can be inspected. With that
setting disabled, unavailable Docker routes fail rather than fabricate data.
GET /api/status returns a compact, widget-friendly summary of the whole
host, intended for dashboards such as Homepage
rather than the main UI. It is also available at the versioned alias
/api/v1/status.
{
"service": "dockermap",
"status": "ok",
"mode": "docker",
"dockerReachable": true,
"containers": 12,
"containersRunning": 11,
"networks": 3,
"volumes": 5,
"images": 14,
"healthy": 10,
"attention": 1,
"offline": 1,
"version": "0.1.0-alpha.2"
}Field meanings:
status—ok,degraded, oroffline(derived from Docker reachability and container state).mode—docker(real Docker data),mock(an explicitly enabled daemon or Node fallback when live authority is unavailable), ormixed.mixedmeans/daemon/healthand/daemon/snapshotresolved from DIFFERENT sources in one response (e.g. health from live Docker while the snapshot fell back to route-local mock): the counts in that payload must not be read as if they share the reported source.sourceCoherentandsnapshotSourceexpose the split explicitly. This is distinct from the browser's Demo Mode, which serves fabricated sample data entirely inside the web app without any API calls; a demo-mode browser never showsmode: mock.healthy/attention/offline— container counts by state, wherecontainers = healthy + attention + offline.
Like every browser API route, /api/status requires a Bearer token when
DOCKERMAP_API_TOKEN is set (or equivalent reverse-proxy forward-auth).
Homepage custom-widget example (place under your Homepage services.yaml):
- DockerMap:
icon: docker
href: http://127.0.0.1:3233
widget:
type: customapi
url: http://127.0.0.1:4000/api/status
headers:
Authorization: Bearer ${DOCKERMAP_API_TOKEN}
display: list
mappings:
- field: status
label: Status
- field: containersRunning
label: Running
format: number
- field: containers
label: Containers
format: number
- field: attention
label: Needs attention
format: numberDockerMap treats host data as sensitive. Its current safety rules are:
- Bind to loopback by default.
- Keep daemon routes read-only.
- Use fixed provider commands, not user-supplied shell commands.
- Keep Compose edits as dry-run previews only.
- Require bearer-token auth for every browser API route when
DOCKERMAP_API_TOKENis set. - Require a daemon bearer token for every daemon route when
DOCKERMAP_DAEMON_TOKEN(or itsDOCKERMAP_API_TOKENfallback) is set; refuse non-loopback daemon binding without one. - Redact or omit secrets from provider output where collectors may encounter service files, process args, package config, proxy config, logs, or env values.
More detail is in docs/security/THREAT_MODEL.md.
Start with the DockerMap wiki. It links to the short roadmap, deployment notes, testing plan, architecture reference, and release checklist.
Useful entry points:
Run the normal local gate before merging code:
npm run checkUseful narrower checks:
npm run typecheck
npm run build
npm run test:js
npm run test:api
npm run test:contracts
npm run test:rust
npm run test:e2eRun live-Docker tests only on a host where Docker is available:
npm run test:live-dockerapps/web: React/Vite browser app.apps/api: Express API for the browser.crates/dockermap-daemon: Rust daemon that reads Docker and host runtime signals.crates/dockermap-core: Rust domain model, Compose parser, and graph logic.packages/contracts: TypeScript API contracts shared by the web and API.tests: shared fixtures and Playwright smoke tests.
DockerMap is built for people who run their own servers and want fewer blind spots before they touch anything.