-
Notifications
You must be signed in to change notification settings - Fork 619
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?
Changes from 1 commit
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,46 @@ | ||
| # Dependencies | ||
| node_modules/ | ||
| npm-debug.log* | ||
| yarn-debug.log* | ||
| yarn-error.log* | ||
|
|
||
| # Development | ||
| .git/ | ||
| .github/ | ||
| .vscode/ | ||
| .idea/ | ||
|
|
||
| # Build outputs | ||
| dist/ | ||
| build/ | ||
|
|
||
| # Environment files | ||
| .env.local | ||
| .env.development | ||
| .env.test | ||
|
|
||
| # Testing | ||
| coverage/ | ||
| .nyc_output/ | ||
|
|
||
| # Misc | ||
| *.log | ||
| *.swp | ||
| *.swo | ||
| *~ | ||
| .DS_Store | ||
| Thumbs.db | ||
|
|
||
| # Documentation | ||
| *.md | ||
| !README.md | ||
|
|
||
| # CI/CD | ||
| .github/ | ||
| .gitlab-ci.yml | ||
| .travis.yml | ||
|
|
||
| # Docker | ||
| Dockerfile* | ||
| docker-compose* | ||
| .dockerignore | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,72 @@ | ||||||||||||||||||||||
| FROM node:20-alpine AS builder | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Install build dependencies | ||||||||||||||||||||||
| RUN apk add --no-cache \ | ||||||||||||||||||||||
| python3 \ | ||||||||||||||||||||||
| make \ | ||||||||||||||||||||||
| g++ \ | ||||||||||||||||||||||
| git | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| WORKDIR /app | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Copy package files | ||||||||||||||||||||||
| COPY package*.json ./ | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Install all dependencies (including dev dependencies for building) | ||||||||||||||||||||||
| RUN npm ci && \ | ||||||||||||||||||||||
| npm cache clean --force | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Copy source code | ||||||||||||||||||||||
| COPY . . | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Build frontend | ||||||||||||||||||||||
| RUN npm run build | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # ============================================================================= | ||||||||||||||||||||||
| # Production stage | ||||||||||||||||||||||
| # ============================================================================= | ||||||||||||||||||||||
| FROM node:20-alpine | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Install runtime dependencies | ||||||||||||||||||||||
| RUN apk add --no-cache \ | ||||||||||||||||||||||
| python3 \ | ||||||||||||||||||||||
| make \ | ||||||||||||||||||||||
| g++ \ | ||||||||||||||||||||||
| git \ | ||||||||||||||||||||||
| ca-certificates \ | ||||||||||||||||||||||
| tzdata | ||||||||||||||||||||||
|
Comment on lines
+31
to
+37
Contributor
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. Remove unnecessary build dependencies from production stage. The production stage includes build tools ( 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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| WORKDIR /app | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Copy package files and install production dependencies | ||||||||||||||||||||||
| COPY package*.json ./ | ||||||||||||||||||||||
| RUN npm ci --only=production && \ | ||||||||||||||||||||||
| npm cache clean --force | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Copy built files from builder | ||||||||||||||||||||||
| COPY --from=builder /app/dist ./dist | ||||||||||||||||||||||
| COPY --from=builder /app/server ./server | ||||||||||||||||||||||
| COPY --from=builder /app/public ./public | ||||||||||||||||||||||
| COPY --from=builder /app/index.html ./index.html | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Create necessary directories with proper permissions | ||||||||||||||||||||||
| RUN mkdir -p /data /config && \ | ||||||||||||||||||||||
| chown -R node:node /app /data /config | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Switch to node user (uid/gid 1000) | ||||||||||||||||||||||
| USER node | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Environment variables | ||||||||||||||||||||||
| ENV NODE_ENV=production \ | ||||||||||||||||||||||
| PORT=3001 \ | ||||||||||||||||||||||
| DATABASE_PATH=/data/auth.db | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Expose port | ||||||||||||||||||||||
| EXPOSE 3001 | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Health check | ||||||||||||||||||||||
| HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ | ||||||||||||||||||||||
| CMD node -e "require('http').get('http://localhost:3001/api/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Start server | ||||||||||||||||||||||
| CMD ["node", "server/index.js"] | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| networks: | ||
| claudecodeui: | ||
| name: claudecodeui | ||
| public: | ||
| external: true | ||
|
|
||
| services: | ||
| claudecodeui: | ||
| container_name: claudecodeui | ||
| build: | ||
| context: . | ||
| dockerfile: Dockerfile | ||
| image: claudecodeui:latest | ||
| restart: unless-stopped | ||
| ports: | ||
| - "${EXTERNAL_PORT:-3002}:3001" | ||
| env_file: | ||
| - path: ./.env | ||
| required: true | ||
| environment: | ||
| - PORT=${PORT:-3001} | ||
| - DATABASE_PATH=${DATABASE_PATH:-/data/auth.db} | ||
| - CONTEXT_WINDOW=${CONTEXT_WINDOW:-160000} | ||
| - CLAUDE_CLI_PATH=${CLAUDE_CLI_PATH:-claude} | ||
| - NODE_ENV=production | ||
| volumes: | ||
| # Data persistence | ||
| - claudecodeui-data:/data | ||
| - claudecodeui-config:/config | ||
| # Mount user's .claude directory for project access (read-only) | ||
| - ${HOME}/.claude:/home/node/.claude:ro | ||
| # Mount user's home for project access (optional, configure as needed) | ||
| # Uncomment and adjust if you need access to specific project directories | ||
| # - ${HOME}/projects:/projects:rw | ||
| 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: | ||
| - "traefik.enable=true" | ||
| - "traefik.http.routers.claudecodeui.rule=Host(`claudecodeui.fhijazi.com`)" | ||
|
||
| - "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.entrypoints=web" | ||
| - "traefik.http.services.claudecodeui-ws.loadbalancer.server.port=3001" | ||
|
|
||
| volumes: | ||
| claudecodeui-data: | ||
| name: claudecodeui_data | ||
| claudecodeui-config: | ||
| name: claudecodeui_config | ||
Uh oh!
There was an error while loading. Please reload this page.