Enhance Config and Manager for Container Path Management

- Added ContainerWorkDir and ContainerIPCSocket fields to the Config struct for better container path configuration.
- Updated DefaultConfig to initialize new fields with default values.
- Modified the Manager to apply defaults for container paths and utilize them in container creation and execution methods, improving flexibility and reliability in container management.
This commit is contained in:
Max 2026-01-29 19:53:30 +08:00
parent 1ece4b0f48
commit 0394727f29
2 changed files with 59 additions and 14 deletions

View file

@ -16,16 +16,22 @@ type Config struct {
IdleTimeout time.Duration `json:"idle_timeout,omitempty"` // Idle timeout before stopping container
MaxMemory string `json:"max_memory,omitempty"` // Memory limit, e.g., "2g"
MaxCPU float64 `json:"max_cpu,omitempty"` // CPU limit, e.g., 1.0
// Container internal paths
ContainerWorkDir string `json:"container_workdir,omitempty"` // Container working directory, default: /workspace
ContainerIPCSocket string `json:"container_ipc_socket,omitempty"` // Container IPC socket path, default: /tmp/yao.sock
}
// DefaultConfig returns a Config with default values
func DefaultConfig() *Config {
return &Config{
Image: "yaoapp/sandbox-claude:latest",
MaxContainers: 100,
IdleTimeout: 30 * time.Minute,
MaxMemory: "2g",
MaxCPU: 1.0,
Image: "yaoapp/sandbox-claude:latest",
MaxContainers: 100,
IdleTimeout: 30 * time.Minute,
MaxMemory: "2g",
MaxCPU: 1.0,
ContainerWorkDir: "/workspace",
ContainerIPCSocket: "/tmp/yao.sock",
}
}
@ -91,4 +97,17 @@ func (c *Config) Init(dataRoot string) {
}
// Invalid env value: keep existing/default value
}
// Container internal paths
if env := os.Getenv("YAO_SANDBOX_CONTAINER_WORKDIR"); env != "" {
c.ContainerWorkDir = env
} else if c.ContainerWorkDir == "" {
c.ContainerWorkDir = "/workspace"
}
if env := os.Getenv("YAO_SANDBOX_CONTAINER_IPC"); env != "" {
c.ContainerIPCSocket = env
} else if c.ContainerIPCSocket == "" {
c.ContainerIPCSocket = "/tmp/yao.sock"
}
}

View file

@ -48,6 +48,14 @@ func NewManager(config *Config) (*Manager, error) {
config = DefaultConfig()
}
// Apply defaults for missing container paths
if config.ContainerWorkDir == "" {
config.ContainerWorkDir = "/workspace"
}
if config.ContainerIPCSocket == "" {
config.ContainerIPCSocket = "/tmp/yao.sock"
}
// Initialize Docker client
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
@ -153,18 +161,23 @@ func (m *Manager) createContainer(ctx context.Context, userID, chatID string) (*
containerConfig := &container.Config{
Image: m.config.Image,
Cmd: []string{"sleep", "infinity"},
WorkingDir: "/workspace",
WorkingDir: m.config.ContainerWorkDir,
Env: []string{
"YAO_IPC_SOCKET=/tmp/yao.sock",
"YAO_IPC_SOCKET=" + m.config.ContainerIPCSocket,
},
}
// Host configuration
// Host configuration - only mount IPC socket if it exists
binds := []string{
workspaceHost + ":" + m.config.ContainerWorkDir,
}
// Only mount IPC socket if the file exists (it's created by IPC manager)
if _, err := os.Stat(ipcSocketHost); err == nil {
binds = append(binds, ipcSocketHost+":"+m.config.ContainerIPCSocket)
}
hostConfig := &container.HostConfig{
Binds: []string{
workspaceHost + ":/workspace",
ipcSocketHost + ":/tmp/yao.sock",
},
Binds: binds,
Resources: container.Resources{
Memory: parseMemory(m.config.MaxMemory),
NanoCPUs: int64(m.config.MaxCPU * 1e9),
@ -342,7 +355,7 @@ func (m *Manager) Exec(ctx context.Context, name string, cmd []string, opts *Exe
// Default options
if opts.WorkDir == "" {
opts.WorkDir = "/workspace"
opts.WorkDir = m.config.ContainerWorkDir
}
// Create exec instance
@ -544,9 +557,22 @@ func (m *Manager) WriteFile(ctx context.Context, name, path string, content []by
// Ensure parent directory exists
dir := filepath.Dir(path)
if dir != "/" && dir != "." {
if _, err := m.Exec(ctx, name, []string{"mkdir", "-p", dir}, nil); err != nil {
result, err := m.Exec(ctx, name, []string{"mkdir", "-p", dir}, nil)
if err != nil {
return fmt.Errorf("failed to create parent directory: %w", err)
}
if result.ExitCode != 0 {
return fmt.Errorf("mkdir failed with exit code %d: %s", result.ExitCode, result.Stdout)
}
// Verify directory was created
verifyResult, err := m.Exec(ctx, name, []string{"test", "-d", dir}, nil)
if err != nil {
return fmt.Errorf("failed to verify directory: %w", err)
}
if verifyResult.ExitCode != 0 {
return fmt.Errorf("directory %s was not created", dir)
}
}
// Create a tar archive with the file