-
Notifications
You must be signed in to change notification settings - Fork 23
Created dockerfile + updated streaming #7
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 16 commits
a39d77f
5416165
519cad7
98ddb99
321d266
aff0248
264dd17
dfd33c5
76869b1
3028022
c8d362f
87bf363
27f2bed
25230e8
df25c67
2c24b21
e0e3e2f
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 |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| # Use Ubuntu as base for better Claude Code support | ||
| FROM ubuntu:22.04 | ||
|
|
||
| # Prevent interactive prompts during build | ||
| ENV DEBIAN_FRONTEND=noninteractive | ||
|
|
||
| # Install system dependencies including Node.js | ||
| RUN apt-get update && apt-get install -y \ | ||
| curl \ | ||
| git \ | ||
| python3.10 \ | ||
| python3-pip \ | ||
| ca-certificates \ | ||
| bash \ | ||
| sudo \ | ||
| jq \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Upgrade pip and setuptools to latest versions | ||
| RUN pip3 install --upgrade pip setuptools wheel | ||
|
|
||
| # Install Node.js 18+ (required for Claude Code) | ||
| RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \ | ||
| apt-get install -y nodejs && \ | ||
| node --version && npm --version | ||
|
|
||
| # Install Claude Code CLI globally as root (before switching to non-root user) | ||
| RUN npm install -g @anthropic-ai/claude-code && \ | ||
| claude --version | ||
|
|
||
| # Create non-root user for running Claude Code | ||
| RUN useradd -m -s /bin/bash claudeuser && \ | ||
| echo "claudeuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers | ||
|
Comment on lines
+32
to
+33
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. The non-root user
Comment on lines
+32
to
+33
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. Overly permissive sudo access. Granting Limit sudo privileges to only what's necessary, or remove sudo access entirely if not required: RUN useradd -m -s /bin/bash claudeuser && \
- echo "claudeuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
+ # Grant limited sudo only if needed, e.g., for specific commands
+ echo "claudeuser ALL=(ALL) NOPASSWD: /usr/bin/apt-get" >> /etc/sudoersOr remove the line entirely if sudo is not required at runtime. 🤖 Prompt for AI Agents |
||
|
|
||
| # Switch to non-root user | ||
| USER claudeuser | ||
| WORKDIR /home/claudeuser | ||
|
|
||
| # Create Claude config directory | ||
| RUN mkdir -p /home/claudeuser/.config/claude | ||
|
|
||
| # Create workspace directory for Claude Code | ||
| RUN mkdir -p /home/claudeuser/workspace | ||
|
|
||
| # Set up working directory | ||
| WORKDIR /home/claudeuser/app | ||
|
|
||
| # Clone claude-code-api | ||
| RUN git clone https://github.com/christag/claude-code-api.git . | ||
|
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. The Docker image is built by cloning the repository from GitHub using 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. 🛠️ Refactor suggestion | 🟠 Major 🧩 Analysis chainVerify the repository source. The Dockerfile clones from
🏁 Script executed: #!/bin/bash
# Check if this is a fork and identify the upstream repository
gh repo view christag/claude-code-api --json parent,isFork,nameWithOwnerLength of output: 169 Target official upstream and pin revision in Dockerfile 🤖 Prompt for AI Agents |
||
|
|
||
| # Install dependencies using modern pip (avoiding deprecated setup.py) | ||
| RUN pip3 install --user --upgrade pip && \ | ||
| pip3 install --user -e . --use-pep517 || \ | ||
| pip3 install --user -e . | ||
|
|
||
| # Add user's local bin to PATH | ||
| ENV PATH="/home/claudeuser/.local/bin:${PATH}" | ||
|
|
||
| # Expose API port | ||
| EXPOSE 8000 | ||
|
|
||
| # Environment variables (set these at runtime) | ||
| ENV ANTHROPIC_API_KEY="" | ||
| ENV HOST=0.0.0.0 | ||
| ENV PORT=8000 | ||
|
|
||
| # Health check | ||
| HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ | ||
| CMD curl -f http://localhost:8000/health || exit 1 | ||
|
|
||
| # Create entrypoint script - DO NOT configure with API key if using Claude Max | ||
| RUN echo '#!/bin/bash\n\ | ||
| set -e\n\ | ||
| \n\ | ||
| # Only configure API key if explicitly provided and not using Claude Max\n\ | ||
| if [ -n "$ANTHROPIC_API_KEY" ] && [ "$USE_CLAUDE_MAX" != "true" ]; then\n\ | ||
| echo "Configuring Claude Code with API key..."\n\ | ||
| mkdir -p ~/.config/claude\n\ | ||
|
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. |
||
| cat > ~/.config/claude/config.json << EOF\n\ | ||
| {\n\ | ||
| "apiKey": "$ANTHROPIC_API_KEY",\n\ | ||
| "autoUpdate": false\n\ | ||
| }\n\ | ||
| EOF\n\ | ||
| echo "Claude Code configured with API key"\n\ | ||
| elif [ "$USE_CLAUDE_MAX" = "true" ]; then\n\ | ||
| echo "Using Claude Max subscription - please run: docker exec -it claude-code-api claude"\n\ | ||
| echo "Then authenticate via browser when prompted"\n\ | ||
| else\n\ | ||
| echo "No authentication configured. Set ANTHROPIC_API_KEY or USE_CLAUDE_MAX=true"\n\ | ||
| fi\n\ | ||
| \n\ | ||
| # Test Claude Code\n\ | ||
| echo "Testing Claude Code..."\n\ | ||
| claude --version || echo "Claude Code installed"\n\ | ||
| \n\ | ||
| echo "Starting API server..."\n\ | ||
| cd /home/claudeuser/app\n\ | ||
| exec python3 -m claude_code_api.main' > /home/claudeuser/entrypoint.sh && \ | ||
| chmod +x /home/claudeuser/entrypoint.sh | ||
|
Comment on lines
+72
to
+100
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. |
||
|
|
||
| # Start the API server with entrypoint | ||
| ENTRYPOINT ["/home/claudeuser/entrypoint.sh"] | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -69,12 +69,19 @@ async def start( | |||||||||||||||||||||||||||||||||||||||||||||||
| *cmd, | ||||||||||||||||||||||||||||||||||||||||||||||||
| cwd=src_dir, | ||||||||||||||||||||||||||||||||||||||||||||||||
| stdout=asyncio.subprocess.PIPE, | ||||||||||||||||||||||||||||||||||||||||||||||||
| stderr=asyncio.subprocess.PIPE | ||||||||||||||||||||||||||||||||||||||||||||||||
| stderr=asyncio.subprocess.PIPE, | ||||||||||||||||||||||||||||||||||||||||||||||||
| env=os.environ.copy() | ||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Wait for process to complete and capture all output | ||||||||||||||||||||||||||||||||||||||||||||||||
| stdout, stderr = await self.process.communicate() | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Log stdout and stderr for debugging | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Debug logging MUST be here, before any error checking | ||||||||||||||||||||||||||||||||||||||||||||||||
| logger.error(f"=== DEBUG: Exit code: {self.process.returncode} ===") | ||||||||||||||||||||||||||||||||||||||||||||||||
| if stderr: | ||||||||||||||||||||||||||||||||||||||||||||||||
| logger.error(f"=== DEBUG: Claude stderr: {stderr.decode()} ===") | ||||||||||||||||||||||||||||||||||||||||||||||||
| if stdout: | ||||||||||||||||||||||||||||||||||||||||||||||||
| logger.info(f"=== DEBUG: Claude stdout: {stdout.decode()[:1000]} ===") | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+80
to
+84
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. The new debug log messages are using f-strings. Since the project uses
Suggested change
Comment on lines
+78
to
+84
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. 🛠️ Refactor suggestion | 🟠 Major Use appropriate log level for debug messages. Lines 80, 82, and 84 use Apply this diff: - # Log stdout and stderr for debugging
- # Debug logging MUST be here, before any error checking
- logger.error(f"=== DEBUG: Exit code: {self.process.returncode} ===")
+ # Debug logging before error checking
+ logger.debug(f"Exit code: {self.process.returncode}")
if stderr:
- logger.error(f"=== DEBUG: Claude stderr: {stderr.decode()} ===")
+ logger.debug(f"Claude stderr: {stderr.decode()}")
if stdout:
- logger.info(f"=== DEBUG: Claude stdout: {stdout.decode()[:1000]} ===")
+ logger.debug(f"Claude stdout (first 1000 chars): {stdout.decode()[:1000]}")📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
| logger.info( | ||||||||||||||||||||||||||||||||||||||||||||||||
| "Claude process completed", | ||||||||||||||||||||||||||||||||||||||||||||||||
| session_id=self.session_id, | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| services: | ||
| claude-code-api: | ||
| build: . | ||
| container_name: claude-code-api | ||
| ports: | ||
| - "127.0.0.1:8000:8000" # Only bind to localhost since tunnel will handle external access | ||
| environment: | ||
| # Use Claude Max subscription instead of API key | ||
| - USE_CLAUDE_MAX=true | ||
| - HOST=0.0.0.0 | ||
| - PORT=8000 | ||
| # Optional: Project root for Claude Code workspace | ||
| - CLAUDE_PROJECT_ROOT=/home/claudeuser/app/workspace | ||
| volumes: | ||
| # Mount workspace for persistent projects | ||
| - ./workspace:/home/claudeuser/app/workspace | ||
| # Mount Claude config to persist authentication | ||
| - ./claude-config:/home/claudeuser/.config/claude | ||
| # Optional: Mount custom config | ||
| - ./config:/home/claudeuser/app/config | ||
| restart: unless-stopped | ||
| healthcheck: | ||
| test: ["CMD", "curl", "-f", "http://localhost:8000/health"] | ||
| interval: 30s | ||
| timeout: 10s | ||
| retries: 3 | ||
| start_period: 10s | ||
|
Comment on lines
1
to
31
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. This For example, you could add: services:
claude-code-api:
volumes:
- .:/home/claudeuser/appNote that this would be most effective if the |
||
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.
The
apt-get installcommand fornodejsdoes not clean up the apt cache afterwards. This increases the image size unnecessarily. It's a good practice to chainapt-get installwithrm -rf /var/lib/apt/lists/*in the sameRUNlayer to keep the layer small.