From 0a21c11a3587588e1cdc5d95a5af190acbf9ecaf Mon Sep 17 00:00:00 2001 From: Kacper Date: Sun, 28 Dec 2025 20:53:35 +0100 Subject: [PATCH] chore: update Dockerfile to use Node.js 22 and improve health check - Upgraded base and server images in Dockerfile from Node.js 20 to 22-alpine for better performance and security. - Replaced wget with curl in the health check command for improved reliability. - Enhanced README with detailed Docker deployment instructions, including configuration for API key and Claude CLI authentication, and examples for working with projects and GitHub CLI authentication. This update ensures a more secure and efficient Docker setup for the application. --- Dockerfile | 8 +- README.md | 101 +++++++++++++++++- .../src/routes/setup/routes/gh-status.ts | 9 +- 3 files changed, 111 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index a5f7a806..e7a0237a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ # ============================================================================= # BASE STAGE - Common setup for all builds (DRY: defined once, used by all) # ============================================================================= -FROM node:20-alpine AS base +FROM node:22-alpine AS base # Install build dependencies for native modules (node-pty) RUN apk add --no-cache python3 make g++ @@ -51,7 +51,7 @@ RUN npm run build:packages && npm run build --workspace=apps/server # ============================================================================= # SERVER PRODUCTION STAGE # ============================================================================= -FROM node:20-alpine AS server +FROM node:22-alpine AS server # Install git, curl, bash (for terminal), and GitHub CLI (pinned version, multi-arch) RUN apk add --no-cache git curl bash && \ @@ -109,9 +109,9 @@ ENV DATA_DIR=/data # Expose port EXPOSE 3008 -# Health check +# Health check (using curl since it's already installed, more reliable than busybox wget) HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:3008/api/health || exit 1 + CMD curl -f http://localhost:3008/api/health || exit 1 # Start server CMD ["node", "apps/server/dist/index.js"] diff --git a/README.md b/README.md index f9cabfd0..cd575d1b 100644 --- a/README.md +++ b/README.md @@ -223,14 +223,111 @@ npm run build:electron:linux # Linux (AppImage + DEB, x64) #### Docker Deployment +Docker provides the most secure way to run Automaker by isolating it from your host filesystem. + ```bash -# Build and run with Docker Compose (recommended for security) +# Build and run with Docker Compose docker-compose up -d -# Access at http://localhost:3007 +# Access UI at http://localhost:3007 # API at http://localhost:3008 + +# View logs +docker-compose logs -f + +# Stop containers +docker-compose down ``` +##### Configuration + +Create a `.env` file in the project root if using API key authentication: + +```bash +# Optional: Anthropic API key (not needed if using Claude CLI authentication) +ANTHROPIC_API_KEY=sk-ant-... +``` + +**Note:** Most users authenticate via Claude CLI instead of API keys. See [Claude CLI Authentication](#claude-cli-authentication-optional) below. + +##### Working with Projects (Host Directory Access) + +By default, the container is isolated from your host filesystem. To work on projects from your host machine, create a `docker-compose.override.yml` file (gitignored): + +```yaml +services: + server: + volumes: + # Mount your project directories + - /path/to/your/project:/projects/your-project +``` + +##### Claude CLI Authentication (Optional) + +To use Claude Code CLI authentication instead of an API key, mount your Claude CLI config directory: + +```yaml +services: + server: + volumes: + # Linux/macOS + - ~/.claude:/home/automaker/.claude + # Windows + - C:/Users/YourName/.claude:/home/automaker/.claude +``` + +**Note:** The Claude CLI config must be writable (do not use `:ro` flag) as the CLI writes debug files. + +##### GitHub CLI Authentication (For Git Push/PR Operations) + +To enable git push and GitHub CLI operations inside the container: + +```yaml +services: + server: + volumes: + # Mount GitHub CLI config + # Linux/macOS + - ~/.config/gh:/home/automaker/.config/gh + # Windows + - 'C:/Users/YourName/AppData/Roaming/GitHub CLI:/home/automaker/.config/gh' + + # Mount git config for user identity (name, email) + - ~/.gitconfig:/home/automaker/.gitconfig:ro + environment: + # GitHub token (required on Windows where tokens are in Credential Manager) + # Get your token with: gh auth token + - GH_TOKEN=${GH_TOKEN} +``` + +Then add `GH_TOKEN` to your `.env` file: + +```bash +GH_TOKEN=gho_your_github_token_here +``` + +##### Complete docker-compose.override.yml Example + +```yaml +services: + server: + volumes: + # Your projects + - /path/to/project1:/projects/project1 + - /path/to/project2:/projects/project2 + + # Authentication configs + - ~/.claude:/home/automaker/.claude + - ~/.config/gh:/home/automaker/.config/gh + - ~/.gitconfig:/home/automaker/.gitconfig:ro + environment: + - GH_TOKEN=${GH_TOKEN} +``` + +##### Architecture Support + +The Docker image supports both AMD64 and ARM64 architectures. The GitHub CLI and Claude CLI are automatically downloaded for the correct architecture during build. + ### Testing #### End-to-End Tests (Playwright) diff --git a/apps/server/src/routes/setup/routes/gh-status.ts b/apps/server/src/routes/setup/routes/gh-status.ts index 1d1312fe..e48b5c25 100644 --- a/apps/server/src/routes/setup/routes/gh-status.ts +++ b/apps/server/src/routes/setup/routes/gh-status.ts @@ -96,15 +96,22 @@ async function getGhStatus(): Promise { // Check authentication status by actually making an API call // gh auth status can return non-zero even when GH_TOKEN is valid + let apiCallSucceeded = false; try { const { stdout } = await execAsync('gh api user --jq ".login"', { env: execEnv }); const user = stdout.trim(); if (user) { status.authenticated = true; status.user = user; + apiCallSucceeded = true; } + // If stdout is empty, fall through to gh auth status fallback } catch { - // API call failed - try gh auth status as fallback + // API call failed - fall through to gh auth status fallback + } + + // Fallback: try gh auth status if API call didn't succeed + if (!apiCallSucceeded) { try { const { stdout } = await execAsync('gh auth status', { env: execEnv }); status.authenticated = true;