From 6dc61277b707aae93a078cf8d81bf307a1972c88 Mon Sep 17 00:00:00 2001 From: qiniu-ci Date: Tue, 26 Aug 2025 15:47:37 +0800 Subject: [PATCH 1/3] =?UTF-8?q?Initial=20plan=20for=20Issue=20#330:=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8DClaude=20Docker=E5=AE=B9=E5=99=A8=E5=86=85git?= =?UTF-8?q?=20safe=20directory=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From 264f0d82a1328074a9c855243be51b41bd57ec4a Mon Sep 17 00:00:00 2001 From: qiniu-ci Date: Tue, 26 Aug 2025 15:50:42 +0800 Subject: [PATCH 2/3] fix: resolve Git safe directory error in Docker containers Fix "fatal: detected dubious ownership in repository" errors that occur when Git operations are performed inside Claude and Gemini Docker containers with mounted host directories. The issue stems from UID mismatch between the container user 'codeagent' (uid 24368) and the host user, causing Git to consider mounted directories unsafe due to cross-user ownership. Changes: - Add global Git safe directory configuration in Dockerfile - Implement runtime Git configuration for mounted workspace - Add shared utility function for consistent Git setup - Apply fix to both Claude and Gemini Docker providers This ensures Git operations work seamlessly with mounted workspaces without compromising security. Closes #330 --- Dockerfile | 3 +++ internal/code/claude_docker.go | 7 +++++++ internal/code/gemini_docker.go | 7 +++++++ internal/code/utils.go | 19 +++++++++++++++++++ 4 files changed, 36 insertions(+) diff --git a/Dockerfile b/Dockerfile index 5d74249..c03c67a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,6 +37,9 @@ RUN apt-get clean && rm -rf /var/lib/apt/lists/* # 切换用户 USER codeagent +# 配置 Git safe directory 以解决跨用户挂载的权限问题 +RUN git config --global safe.directory '*' + # 设置工作目录 WORKDIR /workspace diff --git a/internal/code/claude_docker.go b/internal/code/claude_docker.go index 1141d3f..0c37305 100644 --- a/internal/code/claude_docker.go +++ b/internal/code/claude_docker.go @@ -134,6 +134,12 @@ func NewClaudeDocker(workspace *models.Workspace, cfg *config.Config) (Code, err log.Infof("docker container started successfully") + // Configure Git safe directory inside the container to fix ownership issues + if err := configureGitSafeDirectoryInContainer(containerName); err != nil { + log.Warnf("Failed to configure Git safe directory in container: %v", err) + // Don't fail the container creation, just warn + } + return &claudeCode{ containerName: containerName, }, nil @@ -241,3 +247,4 @@ func copyHostClaudeConfig(isolatedConfigDir string) error { log.Infof("Successfully copied host Claude config to isolated directory") return nil } + diff --git a/internal/code/gemini_docker.go b/internal/code/gemini_docker.go index 0a78895..67442cf 100644 --- a/internal/code/gemini_docker.go +++ b/internal/code/gemini_docker.go @@ -140,6 +140,12 @@ func NewGeminiDocker(workspace *models.Workspace, cfg *config.Config) (Code, err log.Infof("docker container started successfully") + // Configure Git safe directory inside the container to fix ownership issues + if err := configureGitSafeDirectoryInContainer(containerName); err != nil { + log.Warnf("Failed to configure Git safe directory in container: %v", err) + // Don't fail the container creation, just warn + } + return &geminiDocker{ containerName: containerName, }, nil @@ -178,3 +184,4 @@ func (g *geminiDocker) Close() error { stopCmd := exec.Command("docker", "rm", "-f", g.containerName) return stopCmd.Run() } + diff --git a/internal/code/utils.go b/internal/code/utils.go index 38657bd..16fa734 100644 --- a/internal/code/utils.go +++ b/internal/code/utils.go @@ -1,6 +1,7 @@ package code import ( + "bytes" "context" "fmt" "os/exec" @@ -212,3 +213,21 @@ func generateConfigDirName(provider, org, repoName string, workspace *models.Wor return fmt.Sprintf(".%s-%s-%s-workspace-%d", provider, org, repoName, timestamp) } } + +// configureGitSafeDirectoryInContainer configures Git safe directory inside the Docker container +// to prevent "fatal: unsafe repository" errors when Git operations are performed +func configureGitSafeDirectoryInContainer(containerName string) error { + // Configure Git to treat /workspace as a safe directory + cmd := exec.Command("docker", "exec", containerName, "git", "config", "--global", "safe.directory", "/workspace") + + var stderr bytes.Buffer + cmd.Stderr = &stderr + + if err := cmd.Run(); err != nil { + log.Errorf("Failed to configure Git safe directory: %v, stderr: %s", err, stderr.String()) + return fmt.Errorf("failed to configure Git safe directory: %w", err) + } + + log.Infof("Successfully configured Git safe directory in container %s", containerName) + return nil +} From 1ea9704180ba6ac096006b792317b3aafcf47ae7 Mon Sep 17 00:00:00 2001 From: qiniu-ci Date: Tue, 26 Aug 2025 16:08:14 +0800 Subject: [PATCH 3/3] fix: improve Git safe directory configuration in Dockerfile Move Git safe directory configuration after WORKDIR and restrict to specific /workspace path instead of using wildcard for better security. Changes: - Move RUN git config command after WORKDIR /workspace - Replace safe.directory '*' with safe.directory /workspace - Ensure proper order: USER -> WORKDIR -> Git config This provides more targeted security by only trusting the specific mounted workspace directory rather than all directories. Closes #330 --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index c03c67a..3e5f933 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,11 +37,11 @@ RUN apt-get clean && rm -rf /var/lib/apt/lists/* # 切换用户 USER codeagent -# 配置 Git safe directory 以解决跨用户挂载的权限问题 -RUN git config --global safe.directory '*' - # 设置工作目录 WORKDIR /workspace +# 配置 Git safe directory 以解决跨用户挂载的权限问题 +RUN git config --global safe.directory /workspace + # 默认命令 CMD ["tail", "-f", "/dev/null"]