Skip to content

containerFS

containerFS(manager, resolver?, self?, auditLoggers?, healthRunners?): Fileserver

Defined in: packages/runtime/src/container/container-fs.ts:439

Expose a ContainerManager as a synthetic Fileserver — Plan 9 style, where container state is read and controlled via file operations on a mount point (conventionally /dev/container).

ContainerManager

The ContainerManager whose containers this server exposes.

ImageResolver

Optional ImageResolver used by the root ctl create <json> command; omit to disable image-by-name creation.

ContainerSelfInfo

Optional self-introspection info for the hosting container (rendered under /self/). Defaults to a root sentinel.

Map<string, AuditLogger>

Optional map of container-name → audit logger. When present for a container, /children/<name>/audit becomes readable and is listed in readdir; absent entries ENOENT.

Map<string, HealthCheckRunner>

Optional map of container-name → health-check runner. Drives /children/<name>/health follow-mode reads.

Fileserver

A Fileserver with the mount layout documented in @remarks.

Mount layout (all paths relative to the mount point):

  • / — readdir: self, children, ctl
  • /ctl — 0222, write-only: create <json> creates containers via resolver (EINVAL when resolver is unset)
  • /self/ — readdir: name, status, depth, spec, limits, capabilities
  • /self/name — 0444, read: hosting container’s name
  • /self/status — 0444, read: current ContainerState
  • /self/depth — 0444, read: nesting depth (0 = root)
  • /self/spec — 0444, read: JSON-serialized ContainerSpec
  • /self/limits — 0444, read: resource limits as key=value lines
  • /self/capabilities — 0444, read: computed capabilities JSON (snapshot at open)
  • /children/ — readdir: child container names plus .logs, .errors
  • /children/.logs — 0444, read: tagged, merged follow stream of all children
  • /children/.errors — 0444, read: snapshot of failed children’s exit context
  • /children/<name>/ — readdir: status, spec, ctl, env, ns, log, pid, error, cons, wait, capabilities, health, and audit (only when audit logger is registered)
  • /children/<name>/status — 0444, read: <state> [exit=<code>]
  • /children/<name>/spec — 0444, read: JSON-serialized ContainerSpec (sanitized)
  • /children/<name>/ctl — 0222, write-only: stop, start, kill, remove, drain, restart, force-remove. Verbs accept key=value args (e.g. stop timeout=5000). Per-name mutex serializes commands; writes buffer until newline.
  • /children/<name>/env — 0444, read: sorted KEY=VALUE lines
  • /children/<name>/ns — 0444, read: sorted <path>\t<type> lines (one per mount)
  • /children/<name>/log — 0444, read: snapshot for stopped containers; snapshot followed by live subscription for running containers
  • /children/<name>/pid — 0444, read: PID 1 decimal (persists after exit)
  • /children/<name>/error — 0444, read: exit-context key=value lines (empty pre-exit)
  • /children/<name>/cons — 0666, read/write: full-duplex console bridge; EPERM if container is not running/draining
  • /children/<name>/wait — 0444, read: blocks until container exits, returns <exit-code>\n
  • /children/<name>/capabilities — 0444, read: computed capabilities JSON
  • /children/<name>/health — 0444, read: first read returns health=<state> snapshot; subsequent reads block until state changes
  • /children/<name>/audit — 0444, read: audit log snapshot at open (only when auditLoggers has this container)

mkdir, remove, rename, and wstat all throw EPERM — the namespace is controlled exclusively through the ctl channels.

The names ctl, self, and children are reserved and cannot be used as container names.

Mount a container namespace into a Unix image and control it via files:

import { Unix } from '@fishnet/core'
import { containerFS } from '@fishnet/runtime/container/container-fs'
const ns = containerFS(manager, resolver)
const sys = await Unix().use({ mounts: { '/dev/container': ns } }).build().boot()
// Create a container by writing to /dev/container/ctl
await sys.run('echo "create {\\"image\\":\\"alpine\\",\\"name\\":\\"web\\"}" > /dev/container/ctl')
// Observe and control it as files
await sys.run('cat /dev/container/children/web/status')
await sys.run('echo stop > /dev/container/children/web/ctl')

FsError ENOENT on unknown paths or unknown container names

FsError EPERM on writes to read-only files or on reads of write-only ctl

FsError EINVAL on malformed ctl commands or unknown verbs

FsError EISDIR on reads of directory paths