diff --git a/Dockerfile b/Dockerfile index fe34ee4..c557aa1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,10 +42,8 @@ RUN npm install --omit=dev # Copy application code COPY . . -# Copy scripts -COPY claude-wrapper.sh /app/ -COPY startup.sh /app/ -RUN chmod +x /app/claude-wrapper.sh /app/startup.sh +# Make startup script executable +RUN chmod +x /app/scripts/runtime/startup.sh # Note: Docker socket will be mounted at runtime, no need to create it here @@ -63,4 +61,4 @@ ENV NODE_ENV=production \ # (The container will need to run with Docker socket mounted) # Run the startup script -CMD ["/app/startup.sh"] \ No newline at end of file +CMD ["bash", "/app/scripts/runtime/startup.sh"] \ No newline at end of file diff --git a/docs/container-pooling-lessons.md b/docs/container-pooling-lessons.md new file mode 100644 index 0000000..a68e3bc --- /dev/null +++ b/docs/container-pooling-lessons.md @@ -0,0 +1,70 @@ +# Container Pooling Implementation - Lessons Learned + +## Original Problem +User requested container pooling to improve performance by keeping containers ready instead of creating them on-demand for each request. + +## What We Tried + +### 1. Container Persistence Issues +- **Problem**: Containers were exiting immediately after creation +- **Root Cause**: Original `claudecode:latest` image was designed for single-command execution with `--rm` flag +- **Solution**: Changed container creation to use `tail -f /dev/null` to keep containers alive +- **Result**: ✅ Containers now stay running + +### 2. Execution Model Mismatch +- **Problem**: Pooled containers needed different execution approach than on-demand containers +- **Original Clean Execution**: Single Docker run command with full entrypoint setup +- **Pooled Execution Attempt**: Complex multi-step process: + 1. Clone repository into running container + 2. Set up environment + 3. Execute Claude Code directly +- **Issues**: + - Broke the clean single-command execution model + - Required complex command file handling + - Made error handling more complex + - Lost the simplicity of the original design + +### 3. Architecture Conflicts +- **Original Design**: Stateless containers that handle everything from scratch +- **Pooled Design**: Stateful containers that need workspace management +- **Conflict**: The execution logic became significantly more complex + +## Key Insights + +1. **Container Persistence**: Using `--entrypoint="/bin/bash" -c "echo 'ready'; exec tail -f /dev/null"` keeps containers alive +2. **Execution Complexity**: Pooled containers require fundamentally different execution logic +3. **Clean Design**: The original single Docker run command was elegant and reliable +4. **Workspace Management**: Pooled containers need careful workspace cleanup between uses + +## Recommended Approach + +Instead of complex pooled execution, consider: + +1. **Container Pre-warming**: Keep containers running but use the same execution model +2. **Simpler Pool Usage**: + - Use pooled containers for faster startup + - But execute using the same clean entrypoint approach + - Pass the same environment variables and let the entrypoint handle setup +3. **Hybrid Approach**: + - Keep the clean `docker run` execution model + - But reuse container instances by removing `--rm` flag + - Clean up containers after use rather than during creation + +## Next Steps + +1. Revert to original clean execution approach +2. Implement simpler pooling that doesn't change execution complexity +3. Focus on container reuse rather than execution model changes + +## Code Locations + +- Container pool service: `src/services/containerPoolService.js` +- Execution logic: `src/services/claudeService.js:170-210` +- Container creation: Modified Docker command in pool service + +## Performance Gains Observed + +- ✅ Container creation time reduced (containers stay alive) +- ❌ Execution complexity increased significantly +- ❌ Error handling became more complex +- ❌ Lost single-command simplicity \ No newline at end of file