container

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 21, 2026 License: Apache-2.0 Imports: 29 Imported by: 0

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

View Source
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 NewClient

func NewClient(opts ...ClientOpt) (*Client, error)

func (*Client) AttachAndStartSession

func (c *Client) AttachAndStartSession(ctx context.Context, containerID string) error

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) Close

func (c *Client) Close() error

func (*Client) ContainerLogs

func (c *Client) ContainerLogs(ctx context.Context, containerID string, tail int) (string, error)

ContainerLogs returns the last n lines of a container's log output.

func (*Client) ContainerStartedAt

func (c *Client) ContainerStartedAt(ctx context.Context, containerID string) time.Time

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

func (c *Client) ContainerStatus(ctx context.Context, containerID string) string

ContainerStatus returns a short status string for a container (e.g. "running", "exited (1)").

func (*Client) CreateNetwork

func (c *Client) CreateNetwork(ctx context.Context, name string) (NetworkInfo, error)

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

func (c *Client) EnsureImage(ctx context.Context, ref string, quiet bool) (bool, error)

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

func (c *Client) EnsureVolume(ctx context.Context, name string, uid int, user string) error

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

func (c *Client) ExecSession(ctx context.Context, containerID string) error

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

func (c *Client) FindAnySessionContainer(ctx context.Context, projectDir string) (string, error)

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

func (c *Client) FindControlPort(ctx context.Context, containerID string) (int, error)

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

func (c *Client) FindProxyContainerID(ctx context.Context, sessionID string) (string, error)

FindProxyContainerID returns the container ID of the proxy for a session.

func (*Client) FindProxyIP

func (c *Client) FindProxyIP(ctx context.Context) (string, error)

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

func (c *Client) ImageRepoDigest(ctx context.Context, ref string) (string, error)

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) PullImage

func (c *Client) PullImage(ctx context.Context, ref string, quiet bool) error

PullImage pulls the latest version of the image.

func (*Client) RemoveNetwork

func (c *Client) RemoveNetwork(ctx context.Context, networkID string) error

func (*Client) RemoveVolume

func (c *Client) RemoveVolume(ctx context.Context, name string) error

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

func (c *Client) SessionIDFromContainer(ctx context.Context, containerID string) (string, error)

SessionIDFromContainer inspects a container and returns its session ID label.

func (*Client) StartContainer

func (c *Client) StartContainer(ctx context.Context, containerID string) error

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

func (c *Client) StopAndRemove(ctx context.Context, containerID string) error

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.

func (*Client) StreamLogs

func (c *Client) StreamLogs(ctx context.Context, containerID string, w io.Writer) error

StreamLogs follows the container log output and copies it to the given writer.

type ClientOpt

type ClientOpt func(*Client) error

func WithDebug

func WithDebug(debug bool) ClientOpt

type ExitError

type ExitError struct {
	Code int
}

ExitError is returned when a container or exec process exits with a non-zero status code.

func (*ExitError) Error

func (e *ExitError) Error() string

type NetworkInfo

type NetworkInfo struct {
	ID        string
	ProxyIP   string
	SandboxIP string
}

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

type RunningSession struct {
	ContainerID string
	SessionID   string
	ProjectDir  string
}

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

type SessionContainer struct {
	ID   string
	Name string
	Role string // "proxy" or "sandbox"
}

SessionContainer describes a container belonging to a session.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL