-
-
Notifications
You must be signed in to change notification settings - Fork 253
fix(Docker): Add claude-devtools-config.json volume to Docker Compose #179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,6 +19,7 @@ services: | |||||||||||||||||
| - "3456:3456" | ||||||||||||||||||
| volumes: | ||||||||||||||||||
| - ${CLAUDE_DIR:-~/.claude}:/data/.claude:ro | ||||||||||||||||||
| - ${CLAUDE_DIR:-~/.claude}/claude-devtools-config.json:/data/.claude/claude-devtools-config.json:rw | ||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: In the current Docker Compose (v5.x as of 2026, following the Compose Specification), when a bind-mount source path targets a file that does not exist on the host: - Using short syntax (e.g., ./myfile.conf:/container/path/myfile.conf): Compose creates a directory at the source path (for backward compatibility with legacy docker-compose). The mount then fails because Docker expects the source to match the target type (file), but a directory was created instead. Result: error "invalid mount config for type 'bind': bind source path does not exist" or similar. - Using long syntax without bind.create_host_path (e.g., type: bind, source: ./myfile.conf, target: /container/path/myfile.conf): Compose does not create the source path. Docker fails the mount with "bind source path does not exist". - To explicitly create the path (mimicking short syntax behavior): bind: { create_host_path: true }. But since the target is a file, creating a directory causes a mismatch and failure. Overall behavior: The operation fails with an error. Docker does not create the missing file; it requires the exact source file to exist beforehand for a successful file bind-mount. If the source is missing, no file is created in the container—either an error occurs or (in directory auto-creation cases) a directory is mounted instead, leading to app failures. bind.create_host_path: false is fully supported in long-syntax bind mounts (per Compose Specification). Semantics: Prevents automatic creation of the missing host source path (default is true). If the path does not exist, the mount fails immediately (error as above). This is useful to enforce that the host file must pre-exist, avoiding accidental directory creation. Note: There was a bug in early v5.x (issue Citations:
🏁 Script executed: # First, examine the docker-compose.yml around the reviewed lines
head -30 docker-compose.yml | tail -15Repository: matt1398/claude-devtools Length of output: 545 🏁 Script executed: # Search for any initialization or setup scripts that might create the config file
fd -type f \( -name "*.sh" -o -name "*.json" -o -name "*.ts" -o -name "*.js" \) | xargs rg -l "claude-devtools-config" 2>/dev/null | head -20Repository: matt1398/claude-devtools Length of output: 421 🏁 Script executed: # Check ConfigManager to see if it auto-creates the file or depends on pre-existing file
rg -A 10 -B 5 "persistConfig" src/main/services/infrastructure/ConfigManager.tsRepository: matt1398/claude-devtools Length of output: 707 🏁 Script executed: # Search for default config or initialization
rg -B 5 -A 5 "configPath\|default.*config\|initialize.*config" src/main/services/infrastructure/ConfigManager.ts | head -50Repository: matt1398/claude-devtools Length of output: 50 🏁 Script executed: # Check if there's a setup script or README with initialization instructions
cat README.md 2>/dev/null | grep -A 10 -i "setup\|install\|docker" | head -40Repository: matt1398/claude-devtools Length of output: 1490 🏁 Script executed: # Search for any place where the config file is pre-created or defaults are set
rg -l "\.claude.*json\|configPath.*=" src/ | xargs cat 2>/dev/null | head -100Repository: matt1398/claude-devtools Length of output: 50 🏁 Script executed: # Find ConfigManager constructor and full class initialization
rg -B 3 -A 20 "class ConfigManager\|constructor\(" src/main/services/infrastructure/ConfigManager.ts | head -80Repository: matt1398/claude-devtools Length of output: 50 🏁 Script executed: # Check if there's a bootstrap or initialization entry point
rg -l "ConfigManager\|bootstrap\|initialize" src/main/*.tsRepository: matt1398/claude-devtools Length of output: 50 🏁 Script executed: # Look for any Docker setup documentation or entrypoint script
find . -name "entrypoint.sh" -o -name "docker-entrypoint.sh" -o -name "start.sh" 2>/dev/nullRepository: matt1398/claude-devtools Length of output: 50 🏁 Script executed: # Get the full ConfigManager.ts to understand initialization
wc -l src/main/services/infrastructure/ConfigManager.tsRepository: matt1398/claude-devtools Length of output: 121 🏁 Script executed: # Read ConfigManager.ts completely
cat -n src/main/services/infrastructure/ConfigManager.ts | head -150Repository: matt1398/claude-devtools Length of output: 6071 🏁 Script executed: # Also check how ConfigManager is instantiated in the main application
rg -B 5 -A 5 "new ConfigManager\|ConfigManager\(" src/main/standalone.tsRepository: matt1398/claude-devtools Length of output: 50 🏁 Script executed: # Read the constructor and initialization section
cat -n src/main/services/infrastructure/ConfigManager.ts | sed -n '200,350p'Repository: matt1398/claude-devtools Length of output: 5210 🏁 Script executed: # Search for constructor definition specifically
rg -n "constructor\|loadConfig\|private.*load" src/main/services/infrastructure/ConfigManager.ts | head -20Repository: matt1398/claude-devtools Length of output: 50 🏁 Script executed: # Find loadConfig method implementation
rg -n -A 30 "private.*loadConfig\|loadConfig.*Promise" src/main/services/infrastructure/ConfigManager.ts | head -60Repository: matt1398/claude-devtools Length of output: 50 🏁 Script executed: # Search more broadly for loadConfig
rg -n "loadConfig" src/main/services/infrastructure/ConfigManager.tsRepository: matt1398/claude-devtools Length of output: 216 🏁 Script executed: # Get the section around line 332 where loadConfig is called
cat -n src/main/services/infrastructure/ConfigManager.ts | sed -n '330,450p'Repository: matt1398/claude-devtools Length of output: 4921 🏁 Script executed: # Check docker-compose documentation or comments about first-run setup
grep -i "first\|setup\|init\|claude.*dir" docker-compose.ymlRepository: matt1398/claude-devtools Length of output: 223 🏁 Script executed: # Check if there's any documentation about CLAUDE_DIR
grep -r "CLAUDE_DIR\|\.claude" . --include="*.md" --include="*.txt" 2>/dev/null | head -20Repository: matt1398/claude-devtools Length of output: 5246 Bind-file mount fails on first Docker startup if the config file doesn't exist. When To fail fast instead of silently creating a directory, use the long syntax: Suggested Compose change volumes:
- ${CLAUDE_DIR:-~/.claude}:/data/.claude:ro
- - ${CLAUDE_DIR:-~/.claude}/claude-devtools-config.json:/data/.claude/claude-devtools-config.json:rw
+ - type: bind
+ source: ${CLAUDE_DIR:-~/.claude}/claude-devtools-config.json
+ target: /data/.claude/claude-devtools-config.json
+ read_only: false
+ bind:
+ create_host_path: falseThis change prevents auto-creation of a directory and makes the error clear. However, users will still need the file to exist beforehand—consider documenting this requirement or auto-creating a default config on first run. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| environment: | ||||||||||||||||||
| - NODE_ENV=production | ||||||||||||||||||
| - CLAUDE_ROOT=/data/.claude | ||||||||||||||||||
|
|
||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mounting a specific file as a volume can be problematic if the file does not already exist on the host. If
claude-devtools-config.jsonis missing from the host's.claudedirectory whendocker compose upis run, Docker will create a directory with that name instead of a file. This will cause the application to fail with anEISDIR(Illegal operation on a directory) error when it attempts to read or write the configuration. It is recommended to ensure the file exists on the host before starting the container, or to consider mounting the entire${CLAUDE_DIR:-~/.claude}directory asrwif the read-only restriction on session data is not strictly required for your use case.