Skip to content
Wharfbase

How discovery works

Wharfbase finds the databases on a server by itself: no connection strings to type, no list to keep up to date.

A scan runs in these cases:

  • At startup (WB_SCAN_ON_BOOT).
  • When something changes: Wharfbase follows Docker’s events. A container that starts, stops, is created or removed, or a network that changes, triggers a rescan of just that container, a second and a half after the burst settles (WB_SCAN_EVENT_DEBOUNCE_MS).
  • On demand: the Scan button, or wb scan.
  • On a schedule (Pro): Settings → Alerts.

If Docker goes away during a scan, the scan says so and nothing is lost: databases on containers that couldn’t be checked keep their last known state instead of being marked gone. When Docker is back, the event stream reconnects and a rescan catches up.

Every scan goes through the socket-guard, which only lets read calls through. For each container, Wharfbase reads:

  1. The image and the command line, against patterns for each engine (postgres, bitnami/postgresql, timescale/timescaledb, valkey/valkey, …). Variants such as Supabase, PostGIS, Percona or Dragonfly are recognized as their engine.

  2. The ports it listens on and publishes, and engine hints in the environment and arguments (PGPORT, --port 6380). A database with an unusual image is still found by its ports and data directory.

  3. The mounts: where the data lives (a named volume, a bind mount, or nothing, which is a finding), and how big the volume is.

  4. The environment, by name only: variables like POSTGRES_USER tell Wharfbase which user and database to suggest. Secret values are read only when you ask for a credential hint (WB_SECRET_HINTS), and that request is audited.

  5. Labels: Compose project and service, and Wharfbase’s own labels. Labels always win over guesses:

    Label Effect
    wharfbase.enable=false Hides the container
    wharfbase.engine=postgres Forces the engine
    wharfbase.port=6543 Forces the port
    wharfbase.name, wharfbase.tags Display name and tags
    wharfbase.environment=production Production: read-only by default
    wharfbase.user, wharfbase.database, wharfbase.password-env Credential hints for custom images
    wharfbase.sqlite.paths, wharfbase.sqlite.enable=false SQLite files to check, or none

Then Wharfbase probes each candidate it can reach: a TCP connect and the engine’s own handshake, without credentials. That confirms the engine and reads its version. With WB_FINDINGS_ACTIVE_CHECKS on (the default), a few harmless unauthenticated calls also check whether authentication is on, such as MongoDB’s listDatabases.

SQLite files are found inside container volumes. Wharfbase looks for .db, .sqlite and .sqlite3 names (and checks the file header), reading at most 256 MB of archive per container (WB_SQLITE_SCAN_MAX_BYTES_PER_CONTAINER). The host scan adds databases installed on the host itself.

Wharfbase also works out who uses each database: services in the same Compose project, containers whose environment points at it (DATABASE_URL, REDIS_HOST, …) and shared networks. The Topology view and wb topology draw that graph. Live consumers (Pro) adds the clients actually connected right now.

Each scan checks what it found:

Rule Severity What
F001 high Database port published on all interfaces
F002 high, critical if exposed Redis or Valkey without a password
F003 high, critical if exposed MongoDB without authentication
F004 high A well-known default password
F005 medium A password on the command line (visible in docker inspect and ps)
F006 high PostgreSQL trust authentication
F007 high A root account without a password
F008 high Elasticsearch security turned off
F009 low Image version not pinned
F010 medium Version past end of life (from endoflife.date)
F011 high Data stored inside the container, lost when it’s recreated
F012 info No healthcheck
F014 critical PostgreSQL 18 data outside the mounted volume

They show on each database and in the Findings view (wb findings), and alerts (Pro) can notify you when a new one appears.

In a cluster, Wharfbase reads pods, Services and their neighbours through the API instead of Docker, and classifies each pod’s containers the same way. The Services that select a pod give it its addresses, and NetworkPolicies explain an unreachable one. See Kubernetes.

Finding a database is not the same as reaching it. Wharfbase connects over the database’s Docker network, joining it when needed: see Networks. The Reachability tab of each database says how Wharfbase can reach it, or why it can’t.