Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .dockerignore
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
75 changes: 75 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
name: Docker Build and Push

on:
push:
branches:
- main
- master
tags:
- 'v*.*.*'
pull_request:
branches:
- main
- master
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64

- name: Generate artifact attestation
if: github.event_name != 'pull_request'
uses: actions/attest-build-provenance@v1
with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
subject-digest: ${{ steps.build-and-push.outputs.digest }}
push-to-registry: true
91 changes: 91 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
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 including bash and curl for CLI installations
RUN apk add --no-cache \
python3 \
make \
g++ \
git \
ca-certificates \
tzdata \
bash \
curl

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

# Install all supported CLIs globally
# 1. Claude Code CLI - Anthropic's official CLI
RUN npm install -g @anthropic-ai/claude-code && \
npm cache clean --force

# 2. Cursor CLI - Install via official method
RUN curl -fsSL https://cursor.com/install | bash

# 3. Codex CLI - OpenAI's Codex CLI
RUN npm install -g @openai/codex && \
npm cache clean --force

# 4. Taskmaster CLI - AI task orchestration
RUN npm install -g taskmaster-cli && \
npm cache clean --force

# Create necessary directories with proper permissions for all CLIs
RUN mkdir -p /data /config /init-scripts /home/node/.claude /home/node/.cursor /home/node/.openai /home/node/.taskmaster && \
chown -R node:node /app /data /config /init-scripts /home/node/.claude /home/node/.cursor /home/node/.openai /home/node/.taskmaster

# Copy entrypoint script
COPY --chown=node:node docker-entrypoint.sh /app/docker-entrypoint.sh
RUN chmod +x /app/docker-entrypoint.sh

# Switch to node user (uid/gid 1000)
USER node

# Environment variables
ENV NODE_ENV=production \
PORT=3001 \
DATABASE_PATH=/data/auth.db \
CLAUDE_CLI_PATH=claude

# Expose port
EXPOSE 3001

# Start server using entrypoint script
CMD ["/app/docker-entrypoint.sh"]
Loading