Skip to content

Container Usage with sbsh

sbsh provides official Docker images for running persistent terminals in containerized environments. Use the pre-built images to quickly deploy sbsh in Docker, Kubernetes, or any container orchestration platform.

Key Benefits for Container Usage

  • Pre-built Images: Ready-to-use Docker images for multiple architectures
  • Persistence: Terminal sessions survive container restarts when volumes are properly configured
  • Isolation: Run sbsh in isolated environments without affecting the host system
  • Portability: Same image works across different container platforms
  • CI/CD Integration: Use containers in CI/CD pipelines for reproducible environments

Pulling sbsh Images

sbsh images are published on the GitHub Container Registry at ghcr.io/eminwux/sbsh. Images are multi-arch manifests supporting linux/amd64 and linux/arm64, tagged with the release version:

docker pull ghcr.io/eminwux/sbsh:v0.6.0

Or use the latest tag to always pull the most recent release:

docker pull ghcr.io/eminwux/sbsh:latest

Docker automatically selects the correct architecture for your host.

Image Architecture

The sbsh Docker image is built using a multi-stage build process:

Build Stage

  • Base: golang:1.25-bookworm (builder stage)
  • Build Process: Compiles sbsh binary for the target architecture
  • Build Args: VERSION (plus TARGETOS / TARGETARCH provided by Docker Buildx)

Runtime Stage

  • Base: debian:bookworm-slim (minimal Debian image)
  • Dependencies: procps package (for process management utilities)
  • Binary: /bin/sbsh and /bin/sb (hard-linked)
  • Default CMD: ["/bin/sbsh", "terminal"] (runs terminal only by default; can be overridden to use CMD ["/bin/sbsh"] for client+terminal)

Image Structure

/bin/sbsh          # Main sbsh binary
/bin/sb            # Hard link to sbsh (client tool)

Choosing the Right CMD

The sbsh Docker image supports two different CMD options depending on your use case:

CMD ["/bin/sbsh"] - Client + Terminal (Interactive)

Runs a client attached to a terminal. This is the default behavior when using sbsh interactively:

  • Client: Manages the terminal and stays attached
  • Terminal: Interactive shell session
  • Use case: Interactive development, debugging, login shells
  • Behavior: You interact directly with the terminal; client stays attached

Example Dockerfile:

FROM ghcr.io/eminwux/sbsh:v0.6.0
CMD ["/bin/sbsh"]

When to use:

  • Interactive containers where you need to attach and detach
  • Login shell scenarios
  • Development environments where you want direct terminal access
  • When you need the client to manage the terminal lifecycle

CMD ["/bin/sbsh", "terminal"] - Terminal Only

Runs just a terminal without a client. The client is launched externally when you attach:

  • Client: Not running initially; launched when you execute sb attach <name> from outside
  • Terminal: Independent terminal session that runs on its own
  • Use case: Background services, automation, CI/CD pipelines
  • Behavior: Terminal runs independently; client is created when you attach via sb attach
  • Important: Always use --name <name> with sbsh terminal to identify the terminal for later attachment

Example Dockerfile:

FROM ghcr.io/eminwux/sbsh:v0.6.0
CMD ["/bin/sbsh", "terminal", "--name", "my-terminal"]

When to use:

  • Background terminals that need to persist
  • Automation and CI/CD pipelines
  • Services that should run detached
  • When terminals need to survive client restarts
  • When you want to attach to the terminal later from outside the container

Attaching to the terminal:

# From outside the container (if you have sb installed):
sb attach my-terminal

# Or from within the container:
docker exec -it <container> sb attach my-terminal

Comparison

Feature CMD ["/bin/sbsh"] CMD ["/bin/sbsh", "terminal"]
Client Launched and attached Not running initially; launched when you attach
Terminal Managed by client Independent, runs on its own
Use case Interactive development Background services
Detach Press Ctrl-] twice No client attached initially
Attach Already attached Launch client with sb attach <name>
Name required Optional Required (use --name)

Basic Usage

Running sbsh Interactively

Run sbsh with an attached client and terminal:

docker run -it --rm \
  -v ~/.sbsh:/root/.sbsh \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sbsh

Key Points:

  • -v ~/.sbsh:/root/.sbsh: Mounts your local sbsh directory to persist terminals and metadata
  • -it: Interactive terminal mode
  • --rm: Remove container when it exits (optional)
  • Default user is root; adjust paths if using a different user

Running a Detached Terminal

Launch a terminal that runs independently (no client initially). Important: Always use --name to identify the terminal:

docker run -d \
  --name my-sbsh-terminal \
  -v ~/.sbsh:/root/.sbsh \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sbsh terminal --name my-terminal

The terminal runs independently. A client is not running initially - it will be launched when you attach via sb attach.

Attaching to a Running Terminal

Use the sb client to attach to a terminal running in a container:

docker exec -it my-sbsh-terminal sb attach my-terminal

Or from the host, if you have sb installed locally:

sb attach my-terminal

This works because the ~/.sbsh volume is shared between the container and host.

Volume Requirements

sbsh requires persistent storage for terminal metadata, sockets, and logs. Mount the ~/.sbsh directory as a volume:

Volume Mount

-v ~/.sbsh:/root/.sbsh

What Gets Stored

The ~/.sbsh directory contains:

  • ~/.sbsh/run/terminals/: Terminal metadata and socket files
  • ~/.sbsh/run/clients/: Client metadata
  • ~/.sbsh/profiles.d/: Profile definitions (optional)

Using Named Volumes

For better Docker management, use named volumes:

docker volume create sbsh-data

docker run -it --rm \
  -v sbsh-data:/root/.sbsh \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sbsh

Using Bind Mounts

For direct access to files from the host:

docker run -it --rm \
  -v /home/user/.sbsh:/root/.sbsh \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sbsh

Running sbsh Commands

Interactive Mode (sbsh)

Launch a client with an attached terminal:

docker run -it --rm \
  -v ~/.sbsh:/root/.sbsh \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sbsh -p terraform-prd

Detached Terminal (sbsh terminal)

Create a terminal that runs independently:

docker run -d \
  --name terraform-terminal \
  -v ~/.sbsh:/root/.sbsh \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sbsh terminal --name terraform-prd -p terraform-prd

Client Commands (sb)

List terminals, attach, or manage sessions:

# List terminals
docker run --rm \
  -v ~/.sbsh:/root/.sbsh \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sb get terminals

# Attach to a terminal
docker run -it --rm \
  -v ~/.sbsh:/root/.sbsh \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sb attach my-terminal

# List profiles
docker run --rm \
  -v ~/.sbsh:/root/.sbsh \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sb get profiles

Using sbsh as a Base Image

You can use the sbsh image as a base for custom Dockerfiles:

Example 1: Interactive Development Environment (Client + Terminal)

Use CMD ["/bin/sbsh"] for interactive development where you want the client attached:

FROM ghcr.io/eminwux/sbsh:v0.6.0

# Install additional tools
RUN apt-get update && apt-get install -y \
    git \
    vim \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Copy custom profiles
COPY profiles.d/ /root/.sbsh/profiles.d/

# Set working directory
WORKDIR /workspace

# Run client + terminal (interactive)
CMD ["/bin/sbsh"]

Building and Running:

docker build -t my-sbsh-env .
docker run -it --rm \
  -v ~/.sbsh:/root/.sbsh \
  -v $(pwd):/workspace \
  my-sbsh-env

This runs an interactive terminal with an attached client. Press Ctrl-] twice to detach.

Example 2: Background Terminal Service (Terminal Only)

Use CMD ["/bin/sbsh", "terminal"] for background terminals that run independently. Important: Always specify --name to identify the terminal for later attachment:

FROM ghcr.io/eminwux/sbsh:v0.6.0

# Install additional tools
RUN apt-get update && apt-get install -y \
    git \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Copy custom profiles
COPY profiles.d/ /root/.sbsh/profiles.d/

# Set working directory
WORKDIR /workspace

# Run terminal only (no client initially)
# The client will be launched when you attach via sb attach
CMD ["/bin/sbsh", "terminal", "--name", "background-terminal", "-p", "default"]

Building and Running:

docker build -t my-sbsh-background .
docker run -d \
  --name my-terminal-service \
  -v ~/.sbsh:/root/.sbsh \
  my-sbsh-background

# Attach later - this launches a client to connect to the terminal:
docker exec -it my-terminal-service sb attach background-terminal
# Or from host (if sb is installed):
sb attach background-terminal

This runs a terminal that continues independently. The client is not running initially - it's launched when you execute sb attach background-terminal, which creates a client to connect to the existing terminal.

Docker Compose Example

Use Docker Compose for easier management:

version: "3.8"

services:
  sbsh:
    image: ghcr.io/eminwux/sbsh:v0.6.0
    container_name: sbsh
    volumes:
      - ~/.sbsh:/root/.sbsh
      - ./workspace:/workspace
    stdin_open: true
    tty: true
    command: sbsh -p default
    environment:
      - TERM=xterm-256color

Run with:

docker-compose up

Multi-Architecture Support

sbsh images are published as multi-arch manifests supporting:

  • linux/amd64: x86_64 processors (Intel, AMD)
  • linux/arm64: ARM64 processors (Apple Silicon, AWS Graviton, etc.)

Docker automatically selects the correct architecture when pulling from the manifest:

docker pull ghcr.io/eminwux/sbsh:v0.6.0

Building Multi-Architecture Images Locally

To build the sbsh image yourself for multiple architectures, use Docker Buildx:

docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64 \
  -t ghcr.io/eminwux/sbsh:v0.6.0 \
  --push .

Docker-in-Docker (DinD)

If you need to run Docker commands inside sbsh containers, you can use Docker-in-Docker:

Using Docker Socket

docker run -it --rm \
  -v ~/.sbsh:/root/.sbsh \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sbsh

Then install Docker client inside the container or use a profile that includes it.

Using DinD Container

docker run -it --rm \
  -v ~/.sbsh:/root/.sbsh \
  --privileged \
  ghcr.io/eminwux/sbsh:v0.6.0 \
  sbsh

Security Note: Using --privileged or mounting the Docker socket grants extensive permissions. Use with caution in production environments.

Kubernetes Integration

Deployment Example

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sbsh
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sbsh
  template:
    metadata:
      labels:
        app: sbsh
    spec:
      containers:
        - name: sbsh
          image: ghcr.io/eminwux/sbsh:v0.6.0
          command: ["/bin/sbsh", "terminal", "--name", "k8s-terminal"]
          volumeMounts:
            - name: sbsh-data
              mountPath: /root/.sbsh
          stdin: true
          tty: true
      volumes:
        - name: sbsh-data
          persistentVolumeClaim:
            claimName: sbsh-pvc

Persistent Volume Claim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sbsh-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

Troubleshooting

Permission Denied Errors

Problem: Cannot write to ~/.sbsh directory

Solutions:

  • Check volume mount permissions
  • Ensure directory exists: mkdir -p ~/.sbsh
  • Use --user flag if running as non-root:
    docker run -it --rm \
      --user $(id -u):$(id -g) \
      -v ~/.sbsh:/home/user/.sbsh \
      ghcr.io/eminwux/sbsh:v0.6.0 \
      sbsh
    

Terminals Not Persisting

Problem: Terminals disappear after container restart

Solutions:

  • Verify volume mount is correct: docker inspect <container> | grep Mounts
  • Check that ~/.sbsh directory is mounted as a volume
  • Ensure volume is not using --tmpfs or ephemeral storage
  • Use named volumes or bind mounts, not temporary filesystems

Socket Connection Errors

Problem: Cannot connect to terminal sockets

Solutions:

  • Verify sockets are accessible: ls -la ~/.sbsh/run/terminals/*/socket
  • Check socket file permissions
  • Ensure volume is shared between containers if using multi-container setup
  • Verify network mode allows Unix socket access

Profile Not Found

Problem: Profile not available in container

Solutions:

  • Mount profiles directory: -v ~/.sbsh/profiles.d:/root/.sbsh/profiles.d:ro
  • Copy profile during image build (if using as base image)
  • Verify profiles directory in container: /root/.sbsh/profiles.d/
  • Use sb get profiles to list available profiles

Architecture Mismatch

Problem: Image won't run on host architecture

Solutions:

  • Pull the multi-arch image — Docker selects the correct architecture automatically: ghcr.io/eminwux/sbsh:v0.6.0
  • Use docker manifest inspect ghcr.io/eminwux/sbsh:v0.6.0 to verify the available architectures
  • Verify host architecture: uname -m

Container Exits Immediately

Problem: Container starts and immediately exits

Solutions:

  • Use -it flags for interactive mode
  • Check logs: docker logs <container>
  • Verify command syntax
  • Ensure CMD is appropriate for your use case

Best Practices

  1. Use Named Volumes: For production, use named volumes instead of bind mounts for better portability
  2. Version Pinning: Always pin to specific version tags (e.g., v0.6.0) instead of latest
  3. Profile Management: Store profiles in version control and mount them as volumes
  4. Resource Limits: Set appropriate CPU and memory limits for containers
  5. Security: Avoid using --privileged unless absolutely necessary
  6. Backup: Regularly backup ~/.sbsh volumes for important terminal sessions
  7. Multi-Container: Use Docker Compose for complex setups with multiple services

See Also