Skip to content

Commit 6012e83

Browse files
Shironexclaude
andcommitted
refactor: consolidate Dockerfiles into single multi-stage build
- Create unified Dockerfile with multi-stage builds (base, server, ui targets) - Centralize lib package.json COPYs in shared base stage (DRY) - Add Claude CLI installation for Docker authentication support - Remove duplicate apps/server/Dockerfile and apps/ui/Dockerfile - Update docker-compose.yml to use target: parameter - Add docker-compose.override.yml to .gitignore Build commands: docker build --target server -t automaker-server . docker build --target ui -t automaker-ui . docker-compose build && docker-compose up -d 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8f458e5 commit 6012e83

5 files changed

Lines changed: 148 additions & 129 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,4 @@ blob-report/
8080
*.pem
8181

8282
docker-compose.override.yml
83-
.claude/
83+
.claude/docker-compose.override.yml

Dockerfile

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Automaker Multi-Stage Dockerfile
2+
# Single Dockerfile for both server and UI builds
3+
# Usage:
4+
# docker build --target server -t automaker-server .
5+
# docker build --target ui -t automaker-ui .
6+
# Or use docker-compose which selects targets automatically
7+
8+
# =============================================================================
9+
# BASE STAGE - Common setup for all builds (DRY: defined once, used by all)
10+
# =============================================================================
11+
FROM node:20-alpine AS base
12+
13+
# Install build dependencies for native modules (node-pty)
14+
RUN apk add --no-cache python3 make g++
15+
16+
WORKDIR /app
17+
18+
# Copy root package files
19+
COPY package*.json ./
20+
21+
# Copy all libs package.json files (centralized - add new libs here)
22+
COPY libs/types/package*.json ./libs/types/
23+
COPY libs/utils/package*.json ./libs/utils/
24+
COPY libs/prompts/package*.json ./libs/prompts/
25+
COPY libs/platform/package*.json ./libs/platform/
26+
COPY libs/model-resolver/package*.json ./libs/model-resolver/
27+
COPY libs/dependency-resolver/package*.json ./libs/dependency-resolver/
28+
COPY libs/git-utils/package*.json ./libs/git-utils/
29+
30+
# Copy scripts (needed by npm workspace)
31+
COPY scripts ./scripts
32+
33+
# =============================================================================
34+
# SERVER BUILD STAGE
35+
# =============================================================================
36+
FROM base AS server-builder
37+
38+
# Copy server-specific package.json
39+
COPY apps/server/package*.json ./apps/server/
40+
41+
# Install dependencies (--ignore-scripts to skip husky/prepare, then rebuild native modules)
42+
RUN npm ci --ignore-scripts && npm rebuild node-pty
43+
44+
# Copy all source files
45+
COPY libs ./libs
46+
COPY apps/server ./apps/server
47+
48+
# Build packages in dependency order, then build server
49+
RUN npm run build:packages && npm run build --workspace=apps/server
50+
51+
# =============================================================================
52+
# SERVER PRODUCTION STAGE
53+
# =============================================================================
54+
FROM node:20-alpine AS server
55+
56+
# Install git, curl, and GitHub CLI (pinned version for reproducible builds)
57+
RUN apk add --no-cache git curl && \
58+
GH_VERSION="2.63.2" && \
59+
curl -L "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_amd64.tar.gz" -o gh.tar.gz && \
60+
tar -xzf gh.tar.gz && \
61+
mv "gh_${GH_VERSION}_linux_amd64/bin/gh" /usr/local/bin/gh && \
62+
rm -rf gh.tar.gz "gh_${GH_VERSION}_linux_amd64"
63+
64+
# Install Claude CLI globally
65+
RUN npm install -g @anthropic-ai/claude-code
66+
67+
WORKDIR /app
68+
69+
# Create non-root user
70+
RUN addgroup -g 1001 -S automaker && \
71+
adduser -S automaker -u 1001
72+
73+
# Copy root package.json (needed for workspace resolution)
74+
COPY --from=server-builder /app/package*.json ./
75+
76+
# Copy built libs (workspace packages are symlinked in node_modules)
77+
COPY --from=server-builder /app/libs ./libs
78+
79+
# Copy built server
80+
COPY --from=server-builder /app/apps/server/dist ./apps/server/dist
81+
COPY --from=server-builder /app/apps/server/package*.json ./apps/server/
82+
83+
# Copy node_modules (includes symlinks to libs)
84+
COPY --from=server-builder /app/node_modules ./node_modules
85+
86+
# Create data and projects directories
87+
RUN mkdir -p /data /projects && chown automaker:automaker /data /projects
88+
89+
# Switch to non-root user
90+
USER automaker
91+
92+
# Environment variables
93+
ENV NODE_ENV=production
94+
ENV PORT=3008
95+
ENV DATA_DIR=/data
96+
97+
# Expose port
98+
EXPOSE 3008
99+
100+
# Health check
101+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
102+
CMD wget --no-verbose --tries=1 --spider http://localhost:3008/api/health || exit 1
103+
104+
# Start server
105+
CMD ["node", "apps/server/dist/index.js"]
106+
107+
# =============================================================================
108+
# UI BUILD STAGE
109+
# =============================================================================
110+
FROM base AS ui-builder
111+
112+
# Copy UI-specific package.json
113+
COPY apps/ui/package*.json ./apps/ui/
114+
115+
# Install dependencies (--ignore-scripts to skip husky and build:packages in prepare script)
116+
RUN npm ci --ignore-scripts
117+
118+
# Copy all source files
119+
COPY libs ./libs
120+
COPY apps/ui ./apps/ui
121+
122+
# Build packages in dependency order, then build UI
123+
# VITE_SERVER_URL tells the UI where to find the API server
124+
# Use ARG to allow overriding at build time: --build-arg VITE_SERVER_URL=http://api.example.com
125+
ARG VITE_SERVER_URL=http://localhost:3008
126+
ENV VITE_SKIP_ELECTRON=true
127+
ENV VITE_SERVER_URL=${VITE_SERVER_URL}
128+
RUN npm run build:packages && npm run build --workspace=apps/ui
129+
130+
# =============================================================================
131+
# UI PRODUCTION STAGE
132+
# =============================================================================
133+
FROM nginx:alpine AS ui
134+
135+
# Copy built files
136+
COPY --from=ui-builder /app/apps/ui/dist /usr/share/nginx/html
137+
138+
# Copy nginx config for SPA routing
139+
COPY apps/ui/nginx.conf /etc/nginx/conf.d/default.conf
140+
141+
EXPOSE 80
142+
143+
CMD ["nginx", "-g", "daemon off;"]

apps/server/Dockerfile

Lines changed: 0 additions & 75 deletions
This file was deleted.

apps/ui/Dockerfile

Lines changed: 0 additions & 51 deletions
This file was deleted.

docker-compose.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ services:
1313
ui:
1414
build:
1515
context: .
16-
dockerfile: apps/ui/Dockerfile
16+
dockerfile: Dockerfile
17+
target: ui
1718
container_name: automaker-ui
1819
restart: unless-stopped
1920
ports:
@@ -25,7 +26,8 @@ services:
2526
server:
2627
build:
2728
context: .
28-
dockerfile: apps/server/Dockerfile
29+
dockerfile: Dockerfile
30+
target: server
2931
container_name: automaker-server
3032
restart: unless-stopped
3133
ports:

0 commit comments

Comments
 (0)