Documentation
¶
Overview ¶
Package container provides Docker/Podman API wrappers for vibepit.
TTY session handling ¶
The runTTYSession function implements interactive terminal forwarding between the host and a hijacked Docker connection. It is modelled after the Docker CLI's hijackedIOStreamer (cli/command/container/hijack.go).
The following gaps relative to the Docker CLI are known and deferred:
Detach key support: the Docker CLI wraps stdin in an EscapeProxy that intercepts ctrl-p,ctrl-q (or a custom sequence) to cleanly detach from a session without stopping the container. We currently have no detach support — the user must exit the shell or kill the process.
Signal forwarding: the Docker CLI forwards all signals (except SIGCHLD, SIGPIPE, SIGURG) to the container via ContainerKill when sig-proxy is enabled. In TTY mode the kernel's PTY layer handles most signals, so this is less critical for our use case.
stdcopy for non-TTY: when TTY is disabled, Docker multiplexes stdout and stderr over a single connection with 8-byte frame headers. The CLI uses stdcopy.StdCopy to demultiplex. We always use TTY mode, so this is not currently needed, but would be required to support non-TTY.
Index ¶
- Constants
- type Client
- func (c *Client) AttachAndStartSession(ctx context.Context, containerID string) error
- func (c *Client) Close() error
- func (c *Client) ContainerLogs(ctx context.Context, containerID string, tail int) (string, error)
- func (c *Client) ContainerStartedAt(ctx context.Context, containerID string) time.Time
- func (c *Client) ContainerStatus(ctx context.Context, containerID string) string
- func (c *Client) CreateNetwork(ctx context.Context, name string) (NetworkInfo, error)
- func (c *Client) CreateSandboxContainer(ctx context.Context, cfg SandboxContainerConfig) (string, error)
- func (c *Client) EnsureImage(ctx context.Context, ref string, quiet bool) (bool, error)
- func (c *Client) EnsureVolume(ctx context.Context, name string, uid int, user string) error
- func (c *Client) ExecSession(ctx context.Context, containerID string) error
- func (c *Client) FindAnySessionContainer(ctx context.Context, projectDir string) (string, error)
- func (c *Client) FindControlPort(ctx context.Context, containerID string) (int, error)
- func (c *Client) FindProxyContainerID(ctx context.Context, sessionID string) (string, error)
- func (c *Client) FindProxyIP(ctx context.Context) (string, error)
- func (c *Client) FindPublishedPort(ctx context.Context, containerID string, containerPort string) (int, error)
- func (c *Client) FindRunningSession(ctx context.Context, projectDir string) (*RunningSession, error)
- func (c *Client) ImageRepoDigest(ctx context.Context, ref string) (string, error)
- func (c *Client) ListProxySessions(ctx context.Context) ([]ProxySession, error)
- func (c *Client) PullImage(ctx context.Context, ref string, quiet bool) error
- func (c *Client) RemoveNetwork(ctx context.Context, networkID string) error
- func (c *Client) RemoveVolume(ctx context.Context, name string) error
- func (c *Client) SessionContainers(ctx context.Context, sessionID string) ([]SessionContainer, error)
- func (c *Client) SessionIDFromContainer(ctx context.Context, containerID string) (string, error)
- func (c *Client) StartContainer(ctx context.Context, containerID string) error
- func (c *Client) StartProxyContainer(ctx context.Context, cfg ProxyContainerConfig) (string, string, error)
- func (c *Client) StopAndRemove(ctx context.Context, containerID string) error
- func (c *Client) StreamLogs(ctx context.Context, containerID string, w io.Writer) error
- type ClientOpt
- type ExitError
- type NetworkInfo
- type ProxyContainerConfig
- type ProxySession
- type RunningSession
- type SandboxContainerConfig
- type SessionContainer
Constants ¶
const ( LabelVibepit = "vibepit" LabelRole = "vibepit.role" LabelUID = "vibepit.uid" LabelUser = "vibepit.user" LabelVolumeHome = "vibepit.volume.home" LabelVolumeLinuxbrew = "vibepit.volume.linuxbrew" LabelProjectDir = "vibepit.project.dir" LabelSessionID = "vibepit.session-id" RoleProxy = "proxy" RoleSandbox = "sandbox" ProxyBinaryPath = "/vibepit" SandboxBinaryPath = "/vibed" ProxyConfigPath = "/config.json" HomeMountPath = "/home/code" LinuxbrewMountPath = "/home/linuxbrew" ContainerHostname = "vibes" ProxyImage = "gcr.io/distroless/base-debian13:latest" LabelControlPort = "vibepit.control-port" SSHContainerPort = "2222/tcp" SSHHostKeyPath = "/etc/vibepit/sshd/host-key" SSHHostPubPath = "/etc/vibepit/sshd/host-key.pub" SSHPubKeyEnv = "VIBEPIT_SSH_PUBKEY" SessionStatePath = "/tmp/vibed-sessions.json" )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client wraps the Docker/Podman API, trying Docker first then falling back to the Podman-compatible socket.
func (*Client) AttachAndStartSession ¶
AttachAndStartSession connects to a container's main process stdio, then starts it. This ensures startup output from the entrypoint is visible to the attached client. When the user exits the shell, the container's entrypoint exits and the container stops on its own. Returns an *ExitError if the container exits with a non-zero status code.
func (*Client) ContainerLogs ¶
ContainerLogs returns the last n lines of a container's log output.
func (*Client) ContainerStartedAt ¶
ContainerStartedAt returns the time a container was started, as reported by the container runtime. Returns the zero time if the container cannot be inspected or has not been started.
func (*Client) ContainerStatus ¶
ContainerStatus returns a short status string for a container (e.g. "running", "exited (1)").
func (*Client) CreateNetwork ¶
CreateNetwork creates an internal Docker network with a random /24 subnet and derives a static IP for the proxy (gateway + 1). The subnet is explicitly specified so that Docker allows static IP assignment.
func (*Client) CreateSandboxContainer ¶
func (c *Client) CreateSandboxContainer(ctx context.Context, cfg SandboxContainerConfig) (string, error)
CreateSandboxContainer creates the sandboxed development container with proxy environment variables and a read-only root filesystem.
func (*Client) EnsureImage ¶
EnsureImage pulls the image if it is not available locally. Returns true if the image was pulled, false if it was already present.
func (*Client) EnsureVolume ¶
EnsureVolume creates a named volume if it does not already exist, labelling it with the owner UID and username for later identification.
func (*Client) ExecSession ¶
ExecSession starts a new interactive shell inside a running container. Used when reattaching to an existing session. Returns an *ExitError if the shell exits with a non-zero status code.
func (*Client) FindAnySessionContainer ¶
FindAnySessionContainer returns the session ID for any container (sandbox or proxy) matching the given project directory. This is useful for cleanup when the sandbox may have crashed but the proxy is still running.
func (*Client) FindControlPort ¶
FindControlPort returns the host-published control API port for a proxy container. It reads the container port from the control port label and looks up the published binding.
func (*Client) FindProxyContainerID ¶
FindProxyContainerID returns the container ID of the proxy for a session.
func (*Client) FindProxyIP ¶
FindProxyIP returns the IP address of the running vibepit proxy container by inspecting its network settings. Returns an error if no proxy is running.
func (*Client) FindPublishedPort ¶
func (c *Client) FindPublishedPort(ctx context.Context, containerID string, containerPort string) (int, error)
FindPublishedPort inspects a container and returns the host port bound to the given container port (e.g. "2222/tcp"). Returns an error if the port is not published.
func (*Client) FindRunningSession ¶
func (c *Client) FindRunningSession(ctx context.Context, projectDir string) (*RunningSession, error)
FindRunningSession returns a running sandbox container for the given project directory, or nil if none is found.
func (*Client) ImageRepoDigest ¶
ImageRepoDigest returns the repo digest for a locally available image (e.g., "ghcr.io/bernd/vibepit@sha256:abc123"). This pins the exact image content independently of mutable tags.
func (*Client) ListProxySessions ¶
func (c *Client) ListProxySessions(ctx context.Context) ([]ProxySession, error)
ListProxySessions returns all running vibepit proxy containers with their session metadata. The control port is read from the container label, falling back to the first published port binding for older containers.
func (*Client) RemoveNetwork ¶
func (*Client) SessionContainers ¶
func (c *Client) SessionContainers(ctx context.Context, sessionID string) ([]SessionContainer, error)
SessionContainers returns all containers for a session with their roles.
func (*Client) SessionIDFromContainer ¶
SessionIDFromContainer inspects a container and returns its session ID label.
func (*Client) StartContainer ¶
StartContainer starts a previously created container without attaching.
func (*Client) StartProxyContainer ¶
func (c *Client) StartProxyContainer(ctx context.Context, cfg ProxyContainerConfig) (string, string, error)
StartProxyContainer creates and starts a minimal container that runs the vibepit proxy binary, then connects it to the bridge network so it can reach the internet. The control API port is published to 127.0.0.1 with an OS-assigned host port. Returns the container ID and the assigned host port.
func (*Client) StopAndRemove ¶
StopAndRemove stops a container (best-effort) then forcibly removes it. Uses a short stop timeout since callers invoke this after the workload has already exited.
type ExitError ¶
type ExitError struct {
Code int
}
ExitError is returned when a container or exec process exits with a non-zero status code.
type NetworkInfo ¶
NetworkInfo is returned by CreateNetwork with the Docker-assigned addresses.
type ProxyContainerConfig ¶
type ProxyContainerConfig struct {
BinaryPath string
ConfigPath string
NetworkID string
ProxyIP string
ControlAPIPort int
Name string
SessionID string
TLSKeyPEM string
TLSCertPEM string
CACertPEM string
ProjectDir string
NoRestart bool // when true, omits the restart policy so the proxy stops with the session
SSHPort int // when > 0, publish this port for SSH forwarding to sandbox
ExtraHosts []string
}
ProxyContainerConfig holds the parameters for starting the in-network proxy.
type ProxySession ¶
type ProxySession struct {
ContainerID string
SessionID string
ControlPort string
ProjectDir string
StartedAt time.Time
}
ProxySession describes a running proxy for session discovery.
type RunningSession ¶
RunningSession describes a running sandbox container found by FindRunningSession.
type SandboxContainerConfig ¶
type SandboxContainerConfig struct {
Image string
ProjectDir string
WorkDir string
RuntimeDir string
HomeVolumeName string
LinuxbrewVolumeName string
NetworkID string
ProxyIP string
SandboxIP string // static IP on the session network (for SSH forwarding)
ProxyPort int
Name string
Term string
ColorTerm string
UID int
User string
SessionID string // session identifier for labeling
Daemon bool // when true, creates daemon-mode container
DaemonBinaryPath string // host path to vibepit binary (bind-mounted at /vibepit)
DaemonHostKeyPath string // host path to SSH host key (bind-mounted at /etc/vibepit/sshd/host-key)
DaemonHostPubPath string // host path to SSH host pub key
DaemonAuthorizedKey string // SSH public key for client auth (set as VIBEPIT_SSH_PUBKEY env)
DaemonEntrypoint []string // entrypoint override for daemon mode
}
SandboxContainerConfig holds the parameters for the sandboxed sandbox container.
type SessionContainer ¶
SessionContainer describes a container belonging to a session.