-
Notifications
You must be signed in to change notification settings - Fork 616
feat: add Docker deployment support #241
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?
Conversation
Add production-ready Docker deployment with the following features: - **Multi-stage Dockerfile**: Optimized build with separate builder and production stages - **Docker Compose**: Full orchestration with Traefik integration for automatic routing - **Security**: Runs as non-root user (node:node) with minimal runtime dependencies - **Health Checks**: Built-in health monitoring every 30 seconds - **Volume Persistence**: Separate volumes for data and configuration - **Network Isolation**: Dedicated network with Traefik integration via public network - **LinuxServer.io Standards**: Follows container best practices for production deployment Configuration: - Internal port: 3001 - External port: 3002 (configurable via EXTERNAL_PORT env var) - Traefik labels for automatic routing to claudecodeui.fhijazi.com - WebSocket support for real-time communication - Read-only mount of ~/.claude for project discovery Build and deployment tested successfully with health checks passing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
WalkthroughAdds Docker containerization: a Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer / CI
participant Compose as docker-compose
participant Builder as Docker build (builder stage)
participant Prod as Docker build (production stage) / Container
Dev->>Compose: docker-compose build & up
Compose->>Builder: build builder stage (npm ci, build assets)
Builder-->>Compose: built artifacts (dist, server, public, index.html)
Compose->>Prod: assemble runtime image, install prod deps, copy artifacts
Prod-->>Compose: runnable image
Compose->>Prod: start container (node server/index.js)
Prod-->>Dev: healthcheck /api/health -> 200 (service ready)
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Actionable comments posted: 4
🧹 Nitpick comments (1)
docker-compose.yml (1)
38-43: Consider removing the redundant healthcheck from docker-compose.yml.The healthcheck is already defined in the Dockerfile (lines 68–69) and will be inherited by the container. Defining it again in docker-compose.yml is redundant. If you need to override the Dockerfile's healthcheck, keep it here; otherwise, remove it to reduce duplication.
Apply this diff to remove the redundant healthcheck:
networks: - claudecodeui - public - healthcheck: - test: ["CMD", "node", "-e", "require('http').get('http://localhost:3001/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s labels:
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.dockerignore(1 hunks)Dockerfile(1 hunks)docker-compose.yml(1 hunks)
🔇 Additional comments (1)
Dockerfile (1)
68-69: Verify that the application exposes an/api/healthhealth check endpoint.The Dockerfile defines a health check that calls
http://localhost:3001/api/health. Confirm that the application implements this endpoint and returns HTTP 200 for healthy status. If the endpoint is missing or returns a different status code, the container health check will fail.
docker-compose.yml
Outdated
| start_period: 40s | ||
| labels: | ||
| - "traefik.enable=true" | ||
| - "traefik.http.routers.claudecodeui.rule=Host(`claudecodeui.fhijazi.com`)" |
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.
Make the Traefik host domain configurable instead of hardcoding the author's domain.
The hardcoded domain claudecodeui.fhijazi.com is specific to the PR author and will not work for other deployments. Users will need to manually edit the docker-compose.yml file to change the domain, which is error-prone and not maintainable. Use an environment variable with a sensible default (or no default) to allow users to configure their own domain.
Apply this diff to make the domain configurable:
- - "traefik.http.routers.claudecodeui.rule=Host(`claudecodeui.fhijazi.com`)"
+ - "traefik.http.routers.claudecodeui.rule=Host(`${DOMAIN:-localhost}`)"
- "traefik.http.routers.claudecodeui.entrypoints=web"
- "traefik.http.services.claudecodeui.loadbalancer.server.port=3001"
- "traefik.http.routers.claudecodeui.middlewares=common-headers@file"
# WebSocket support
- - "traefik.http.routers.claudecodeui-ws.rule=Host(`claudecodeui.fhijazi.com`) && PathPrefix(`/ws`)"
+ - "traefik.http.routers.claudecodeui-ws.rule=Host(`${DOMAIN:-localhost}`) && PathPrefix(`/ws`)"Then document in a README or deployment guide that users should set the DOMAIN environment variable to their actual domain.
Also applies to: 51-51
🤖 Prompt for AI Agents
In docker-compose.yml around line 46 (and similarly line 51), the Traefik host
rule is hardcoded to claudecodeui.fhijazi.com; change it to use an environment
variable (e.g. ${DOMAIN}) so deployments can supply their own domain, optionally
providing a sensible default like ${DOMAIN:-example.com} or leaving no default
to force explicit configuration, and update README/deployment docs instructing
users to set DOMAIN to their actual domain before running docker-compose.
docker-compose.yml
Outdated
| labels: | ||
| - "traefik.enable=true" | ||
| - "traefik.http.routers.claudecodeui.rule=Host(`claudecodeui.fhijazi.com`)" | ||
| - "traefik.http.routers.claudecodeui.entrypoints=web" |
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.
Add HTTPS/TLS configuration for production security.
The Traefik configuration only uses the web entrypoint (HTTP). For production deployments, HTTPS with TLS is essential. Add the websecure entrypoint and TLS configuration. If TLS is intentionally handled externally (e.g., by an upstream reverse proxy), this should be documented.
Apply this diff to add HTTPS support (adjust based on your Traefik TLS configuration):
- "traefik.http.routers.claudecodeui.rule=Host(`${DOMAIN:-localhost}`)"
- "traefik.http.routers.claudecodeui.entrypoints=web"
+ - "traefik.http.routers.claudecodeui.entrypoints=websecure"
+ - "traefik.http.routers.claudecodeui.tls=true"
- "traefik.http.services.claudecodeui.loadbalancer.server.port=3001"
- "traefik.http.routers.claudecodeui.middlewares=common-headers@file"
# WebSocket support
- "traefik.http.routers.claudecodeui-ws.rule=Host(`${DOMAIN:-localhost}`) && PathPrefix(`/ws`)"
- "traefik.http.routers.claudecodeui-ws.entrypoints=websecure"
+ - "traefik.http.routers.claudecodeui-ws.tls=true"Also applies to: 52-52
🤖 Prompt for AI Agents
In docker-compose.yml around lines 47 and 52, the Traefik labels only expose the
HTTP entrypoint ("web") which leaves production traffic unencrypted; update the
service labels to also reference the "websecure" entrypoint and enable TLS by
adding the appropriate traefik.http.routers.<name>.entrypoints=websecure and
traefik.http.routers.<name>.tls=true labels and configure a cert resolver (e.g.,
traefik.http.routers.<name>.tls.certresolver=le) or, if TLS is managed
externally, add a clear comment in the compose file documenting that choice;
ensure the router names match existing labels and that your Traefik static
configuration defines the websecure entrypoint and the named cert resolver.
| RUN apk add --no-cache \ | ||
| python3 \ | ||
| make \ | ||
| g++ \ | ||
| git \ | ||
| ca-certificates \ | ||
| tzdata |
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.
Remove unnecessary build dependencies from production stage.
The production stage includes build tools (python3, make, g++, git) that are not needed at runtime. These only increase the image size. Keep only runtime dependencies: ca-certificates and tzdata.
Apply this diff to remove build dependencies:
# Install runtime dependencies
RUN apk add --no-cache \
- python3 \
- make \
- g++ \
- git \
- ca-certificates \
+ ca-certificates \
tzdata📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| RUN apk add --no-cache \ | |
| python3 \ | |
| make \ | |
| g++ \ | |
| git \ | |
| ca-certificates \ | |
| tzdata | |
| RUN apk add --no-cache \ | |
| ca-certificates \ | |
| tzdata |
🤖 Prompt for AI Agents
In Dockerfile around lines 31 to 37, the production stage is installing
build-time packages (python3, make, g++, git) that aren't required at runtime;
remove those packages and only install the runtime dependencies ca-certificates
and tzdata to reduce image size. Edit the RUN apk add --no-cache line to drop
python3, make, g++, and git so it only installs ca-certificates and tzdata, and
verify there are no subsequent runtime steps that expect the removed tools.
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.
Actionable comments posted: 0
♻️ Duplicate comments (1)
Dockerfile (1)
31-37: Remove build dependencies from production stage to reduce image bloat.The production stage installs
python3,make,g++, andgit, which are build-time tools and not needed at runtime. These packages unnecessarily inflate the image size and increase the attack surface. Keep only the runtime dependencies:ca-certificatesandtzdata.# Install runtime dependencies RUN apk add --no-cache \ - python3 \ - make \ - g++ \ - git \ ca-certificates \ tzdataNote: This resolves the blocker from the previous review.
🧹 Nitpick comments (1)
.dockerignore (1)
8-9: Remove duplicate.github/entry.Line 9 and line 39 both exclude
.github/, which is redundant. Keep one exclusion (either in the Development or CI/CD section) and remove the duplicate.# Development .git/ - .github/ .vscode/ .idea/ # CI/CD .github/Also applies to: 38-39
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.dockerignore(1 hunks)Dockerfile(1 hunks)docker-compose.yml(1 hunks)
🔇 Additional comments (7)
Dockerfile (2)
1-24: Multi-stage build and builder stage are well-structured.The builder stage correctly isolates build dependencies, and the separation prevents unnecessary artifacts from leaking into production.
52-68: Security and runtime setup is sound.Non-root user execution (line 57), proper permission delegation (lines 53–54), and environment variable configuration (lines 60–62) follow production best practices. The healthcheck-friendly CMD is appropriate for orchestration.
docker-compose.yml (5)
16-18: Good practice:env_filemarked as required.Marking the env file as required (line 18) ensures the composition fails fast if the file is missing, preventing silent misconfiguration.
14-15: Port and environment configuration is flexible and well-structured.External port is configurable via
EXTERNAL_PORTenv var with a sensible default (3002). Environment variables for runtime configuration (PORT, DATABASE_PATH, CONTEXT_WINDOW, CLAUDE_CLI_PATH) follow the twelve-factor app pattern.Also applies to: 19-24
37-42: Healthcheck implementation is solid.The healthcheck queries
/api/healthevery 30 seconds with reasonable timeouts (10s) and retries (3). The 40-second start period allows the service time to initialize before health checks begin.
1-49: Code snippet appears truncated; Traefik labels from previous reviews are not visible.Past review comments reference Traefik labels and hardcoded domain (
claudecodeui.fhijazi.com) and HTTPS/TLS configuration issues at lines around 46–51, but the provided code snippet ends at line 49. If Traefik labels exist beyond the visible range, please verify that:
- The domain is configurable (not hardcoded to
claudecodeui.fhijazi.com)- HTTPS/TLS is configured (not HTTP-only)
If you do not intend to use Traefik, clarify the routing/reverse-proxy strategy in documentation.
31-31: The original review comment is incorrect—.claudemount must remain read-write.The application in
server/projects.jsrequires write access to~/.claude/project-config.jsonto store manually added projects (line 35: "Stored in ~/.claude/project-config.json with 'manuallyAdded' flag"). The:rwflag on line 31 is necessary for this functionality. Changing it to:rowould break the feature. There is no evidence in the PR that a read-only mount was intended.Likely an incorrect or invalid review comment.
Add production-ready Docker deployment with the following features:
Configuration:
Build and deployment tested successfully with health checks passing.
🤖 Generated with Claude Code
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.