package agent import ( "encoding/json" "os" "path/filepath" "runtime" "sync" ) // DockerConfig 是用户可配置的 Docker 连接信息。 type DockerConfig struct { // Socket 是用户配置的 Docker 连接地址,支持 // unix:///var/run/docker.sock、npipe:////./pipe/docker_engine、tcp://host:2375 等。 // 为空时使用默认的本地 Docker。 Socket string `json:"socket,omitempty"` } // DockerConfigStore 持久化用户的 Docker socket 配置,并给出默认值。 type DockerConfigStore struct { mu sync.RWMutex path string config DockerConfig defaultSocket string } func NewDockerConfigStore(dataDir string) (*DockerConfigStore, error) { defaultSocket := getenv("AGENT_DOCKER_SOCKET", "") if defaultSocket == "" { defaultSocket = defaultDockerSocket() } store := &DockerConfigStore{ path: filepath.Join(dataDir, "docker-config.json"), defaultSocket: defaultSocket, } store.load() return store, nil } func defaultDockerSocket() string { if runtime.GOOS == "windows" { return "npipe:////./pipe/docker_engine" } return "unix:///var/run/docker.sock" } func (s *DockerConfigStore) load() { data, err := os.ReadFile(s.path) if err != nil { return } if len(data) == 0 { return } var config DockerConfig if err := json.Unmarshal(data, &config); err != nil { return } s.config = config } // Socket 返回当前生效的 docker 连接地址:用户配置优先,否则使用默认本地 Docker。 func (s *DockerConfigStore) Socket() string { s.mu.RLock() defer s.mu.RUnlock() if s.config.Socket != "" { return s.config.Socket } return s.defaultSocket } // DefaultSocket 返回未配置时使用的默认地址。 func (s *DockerConfigStore) DefaultSocket() string { return s.defaultSocket } // IsConfigured 报告用户是否手动配置过 socket。 func (s *DockerConfigStore) IsConfigured() bool { s.mu.RLock() defer s.mu.RUnlock() return s.config.Socket != "" } // SetSocket 保存用户的 socket 配置;传入空字符串表示清除配置、恢复默认。 func (s *DockerConfigStore) SetSocket(socket string) error { s.mu.Lock() defer s.mu.Unlock() s.config.Socket = socket data, err := json.MarshalIndent(s.config, "", " ") if err != nil { return err } tmp := s.path + ".tmp" if err := os.WriteFile(tmp, data, 0o600); err != nil { return err } return os.Rename(tmp, s.path) }