mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-29 22:02:02 +00:00
chore: update Docker configuration and entrypoint script
- Enhanced .dockerignore to exclude additional build outputs and dependencies. - Modified dev.mjs and start.mjs to change Docker container startup behavior, removing the --build flag to preserve volumes. - Updated docker-compose.yml to add a new volume for persisting Claude CLI OAuth session keys. - Introduced docker-entrypoint.sh to fix permissions on the Claude CLI config directory. - Adjusted Dockerfile to include the entrypoint script and ensure proper user permissions. These changes improve the Docker setup and streamline the development workflow.
This commit is contained in:
@@ -1 +1,19 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
**/node_modules/
|
||||
|
||||
# Build outputs
|
||||
dist/
|
||||
**/dist/
|
||||
dist-electron/
|
||||
**/dist-electron/
|
||||
build/
|
||||
**/build/
|
||||
.next/
|
||||
**/.next/
|
||||
.nuxt/
|
||||
**/.nuxt/
|
||||
out/
|
||||
**/out/
|
||||
.cache/
|
||||
**/.cache/
|
||||
22
Dockerfile
22
Dockerfile
@@ -53,8 +53,8 @@ RUN npm run build:packages && npm run build --workspace=apps/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 && \
|
||||
# Install git, curl, bash (for terminal), su-exec (for user switching), and GitHub CLI (pinned version, multi-arch)
|
||||
RUN apk add --no-cache git curl bash su-exec && \
|
||||
GH_VERSION="2.63.2" && \
|
||||
ARCH=$(uname -m) && \
|
||||
case "$ARCH" in \
|
||||
@@ -72,9 +72,11 @@ RUN npm install -g @anthropic-ai/claude-code
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Create non-root user
|
||||
# Create non-root user with home directory
|
||||
RUN addgroup -g 1001 -S automaker && \
|
||||
adduser -S automaker -u 1001
|
||||
adduser -S automaker -u 1001 -h /home/automaker && \
|
||||
mkdir -p /home/automaker && \
|
||||
chown automaker:automaker /home/automaker
|
||||
|
||||
# Copy root package.json (needed for workspace resolution)
|
||||
COPY --from=server-builder /app/package*.json ./
|
||||
@@ -98,12 +100,17 @@ RUN git config --system --add safe.directory '*' && \
|
||||
# Use gh as credential helper (works with GH_TOKEN env var)
|
||||
git config --system credential.helper '!gh auth git-credential'
|
||||
|
||||
# Switch to non-root user
|
||||
USER automaker
|
||||
# Copy entrypoint script for fixing permissions on mounted volumes
|
||||
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||
|
||||
# Note: We stay as root here so entrypoint can fix permissions
|
||||
# The entrypoint script will switch to automaker user before running the command
|
||||
|
||||
# Environment variables
|
||||
ENV PORT=3008
|
||||
ENV DATA_DIR=/data
|
||||
ENV HOME=/home/automaker
|
||||
|
||||
# Expose port
|
||||
EXPOSE 3008
|
||||
@@ -112,6 +119,9 @@ EXPOSE 3008
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD curl -f http://localhost:3008/api/health || exit 1
|
||||
|
||||
# Use entrypoint to fix permissions before starting
|
||||
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
|
||||
|
||||
# Start server
|
||||
CMD ["node", "apps/server/dist/index.js"]
|
||||
|
||||
|
||||
@@ -7,12 +7,28 @@ import { createLogger } from '@automaker/utils/logger';
|
||||
import { getHttpApiClient } from './http-api-client';
|
||||
import { getElectronAPI } from './electron';
|
||||
import { getItem, setItem } from './storage';
|
||||
import path from 'path';
|
||||
|
||||
const logger = createLogger('WorkspaceConfig');
|
||||
|
||||
const LAST_PROJECT_DIR_KEY = 'automaker:lastProjectDir';
|
||||
|
||||
/**
|
||||
* Browser-compatible path join utility
|
||||
* Works in both Node.js and browser environments
|
||||
*/
|
||||
function joinPath(...parts: string[]): string {
|
||||
// Remove empty parts and normalize separators
|
||||
const normalized = parts
|
||||
.filter((p) => p)
|
||||
.map((p) => p.replace(/\\/g, '/'))
|
||||
.join('/')
|
||||
.replace(/\/+/g, '/'); // Remove duplicate slashes
|
||||
|
||||
// Preserve leading slash if first part had it
|
||||
const hasLeadingSlash = parts[0]?.startsWith('/');
|
||||
return hasLeadingSlash ? '/' + normalized.replace(/^\//, '') : normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default Documents/Automaker directory path
|
||||
* @returns Promise resolving to Documents/Automaker path, or null if unavailable
|
||||
@@ -21,7 +37,7 @@ async function getDefaultDocumentsPath(): Promise<string | null> {
|
||||
try {
|
||||
const api = getElectronAPI();
|
||||
const documentsPath = await api.getPath('documents');
|
||||
return path.join(documentsPath, 'Automaker');
|
||||
return joinPath(documentsPath, 'Automaker');
|
||||
} catch (error) {
|
||||
logger.error('Failed to get documents path:', error);
|
||||
return null;
|
||||
|
||||
9
dev.mjs
9
dev.mjs
@@ -172,7 +172,9 @@ async function main() {
|
||||
} else if (choice === '3') {
|
||||
console.log('');
|
||||
log('Launching Docker Container (Isolated Mode)...', 'blue');
|
||||
log('Building and starting Docker containers...', 'yellow');
|
||||
log('Starting Docker containers...', 'yellow');
|
||||
log('Note: Containers will only rebuild if images are missing.', 'yellow');
|
||||
log('To force a rebuild, run: docker compose up --build', 'yellow');
|
||||
console.log('');
|
||||
|
||||
// Check if ANTHROPIC_API_KEY is set
|
||||
@@ -183,8 +185,9 @@ async function main() {
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Build and start containers with docker-compose
|
||||
processes.docker = crossSpawn('docker', ['compose', 'up', '--build'], {
|
||||
// Start containers with docker-compose (without --build to preserve volumes)
|
||||
// Images will only be built if they don't exist
|
||||
processes.docker = crossSpawn('docker', ['compose', 'up'], {
|
||||
stdio: 'inherit',
|
||||
cwd: __dirname,
|
||||
env: {
|
||||
|
||||
@@ -59,6 +59,10 @@ services:
|
||||
# This volume persists data between restarts but is container-managed
|
||||
- automaker-data:/data
|
||||
|
||||
# Persist Claude CLI OAuth session keys across container restarts
|
||||
# This allows 'claude login' authentication to persist between restarts
|
||||
- automaker-claude-config:/home/automaker/.claude
|
||||
|
||||
# NO host directory mounts - container cannot access your laptop files
|
||||
# If you need to work on a project, create it INSIDE the container
|
||||
# or use a separate docker-compose override file
|
||||
@@ -72,3 +76,8 @@ volumes:
|
||||
automaker-data:
|
||||
name: automaker-data
|
||||
# Named volume - completely isolated from host filesystem
|
||||
|
||||
automaker-claude-config:
|
||||
name: automaker-claude-config
|
||||
# Named volume for Claude CLI OAuth session keys and configuration
|
||||
# Persists authentication across container restarts
|
||||
|
||||
19
docker-entrypoint.sh
Executable file
19
docker-entrypoint.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Fix permissions on Claude CLI config directory if it exists
|
||||
# This handles the case where a volume is mounted and owned by root
|
||||
if [ -d "/home/automaker/.claude" ]; then
|
||||
chown -R automaker:automaker /home/automaker/.claude
|
||||
chmod -R 755 /home/automaker/.claude
|
||||
fi
|
||||
|
||||
# Ensure the directory exists with correct permissions if volume is empty
|
||||
if [ ! -d "/home/automaker/.claude" ]; then
|
||||
mkdir -p /home/automaker/.claude
|
||||
chown automaker:automaker /home/automaker/.claude
|
||||
chmod 755 /home/automaker/.claude
|
||||
fi
|
||||
|
||||
# Switch to automaker user and execute the command
|
||||
exec su-exec automaker "$@"
|
||||
@@ -26,7 +26,7 @@
|
||||
"dev:electron:wsl": "npm run build:packages && npm run _dev:electron:wsl",
|
||||
"dev:electron:wsl:gpu": "npm run build:packages && npm run _dev:electron:wsl:gpu",
|
||||
"dev:server": "npm run build:packages && npm run _dev:server",
|
||||
"dev:docker": "docker compose up --build",
|
||||
"dev:docker": "docker compose up",
|
||||
"dev:full": "npm run build:packages && concurrently \"npm run _dev:server\" \"npm run _dev:web\"",
|
||||
"build": "npm run build:packages && npm run build --workspace=apps/ui",
|
||||
"build:packages": "npm run build -w @automaker/types && npm run build -w @automaker/platform && npm run build -w @automaker/utils && npm run build -w @automaker/prompts -w @automaker/model-resolver -w @automaker/dependency-resolver && npm run build -w @automaker/git-utils",
|
||||
|
||||
@@ -231,7 +231,9 @@ async function main() {
|
||||
} else if (choice === '3') {
|
||||
console.log('');
|
||||
log('Launching Docker Container (Isolated Mode)...', 'blue');
|
||||
log('Building and starting Docker containers...', 'yellow');
|
||||
log('Starting Docker containers...', 'yellow');
|
||||
log('Note: Containers will only rebuild if images are missing.', 'yellow');
|
||||
log('To force a rebuild, run: docker compose up --build', 'yellow');
|
||||
console.log('');
|
||||
|
||||
// Check if ANTHROPIC_API_KEY is set
|
||||
@@ -242,8 +244,9 @@ async function main() {
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Build and start containers with docker-compose
|
||||
processes.docker = crossSpawn('docker', ['compose', 'up', '--build'], {
|
||||
// Start containers with docker-compose (without --build to preserve volumes)
|
||||
// Images will only be built if they don't exist
|
||||
processes.docker = crossSpawn('docker', ['compose', 'up'], {
|
||||
stdio: 'inherit',
|
||||
cwd: __dirname,
|
||||
env: {
|
||||
|
||||
Reference in New Issue
Block a user