FROM node:20-alpine AS builder WORKDIR /app # Install build dependencies RUN apk add --no-cache git bun # Clone the Claude Code Agents UI repository RUN git clone --depth 1 https://github.com/Ngxba/claude-code-agents-ui.git . || true # Install dependencies using bun or npm RUN if [ -f bun.lockb ]; then \ bun install --frozen-lockfile; \ else \ npm install; \ fi # Build the Nuxt application RUN npm run build || bun run build # Production stage FROM node:20-alpine WORKDIR /app # Install runtime dependencies including Claude Code and utilities RUN apk add --no-cache \ python3 py3-pip \ git git-lfs \ curl wget \ bash zsh \ vim nano \ build-base \ openssh-client \ ca-certificates \ tini # Install Claude Code CLI RUN npm install -g @anthropic-ai/claude-code # Install Python tools for agent execution RUN pip3 install --no-cache-dir \ requests \ python-dotenv \ pydantic \ fastapi \ uvicorn # Copy built application from builder COPY --from=builder /app/.output /app/.output COPY --from=builder /app/package.json /app/package.json COPY --from=builder /app/node_modules /app/node_modules # Create non-root user for security RUN addgroup -g 1000 claude && \ adduser -D -u 1000 -G claude claude # Create necessary directories RUN mkdir -p /workspace /root/.claude && \ chown -R claude:claude /workspace /root/.claude # Set permissions RUN chown -R claude:claude /app # Create entrypoint script that starts both services RUN cat > /entrypoint.sh << 'EOF' #!/bin/sh set -e # Start Claude Code in the background if specified if [ "$RUN_CLAUDE_CODE" = "true" ]; then echo "Starting Claude Code daemon..." claude serve & CLAUDE_PID=$! fi # Start the Nuxt application echo "Starting Claude Code Agents UI..." exec node /app/.output/server/index.mjs EOF RUN chmod +x /entrypoint.sh # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ CMD curl -f http://localhost:3000/api/health || exit 1 EXPOSE 3000 # Use tini to handle signals properly ENTRYPOINT ["/sbin/tini", "--"] CMD ["/entrypoint.sh"]