From cb36631b7a0b75a82703b03c186268fe84615d61 Mon Sep 17 00:00:00 2001 From: Arseniy Ivanov Date: Sun, 3 Aug 2025 17:45:42 -0400 Subject: [PATCH] Fix Docker implementation with working SQLite and healthcheck MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Enable CGO in Go build stage for SQLite support (add gcc, musl-dev, sqlite-dev) - Replace PM2 with direct process management for simpler container operation - Fix network binding to 0.0.0.0 for external access from host - Simplify healthcheck command to avoid spider mode issues - Remove PM2 dependency and use background processes with proper signal handling - Both proxy (3001) and web (5173) services now start and respond correctly 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- Dockerfile | 18 +++++--- docker-entrypoint.sh | 105 ++++++++++--------------------------------- 2 files changed, 34 insertions(+), 89 deletions(-) diff --git a/Dockerfile b/Dockerfile index 87234a4..6891ded 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,8 +6,8 @@ FROM golang:1.21-alpine AS go-builder WORKDIR /app -# Install build dependencies -RUN apk add --no-cache git +# Install build dependencies including gcc for CGO +RUN apk add --no-cache git gcc musl-dev sqlite-dev # Copy Go modules COPY proxy/go.mod proxy/go.sum ./proxy/ @@ -16,7 +16,8 @@ RUN go mod download # Copy Go source code COPY proxy/ ./ -RUN go build -o /app/bin/proxy cmd/proxy/main.go +# Build with CGO enabled for SQLite support +RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o /app/bin/proxy cmd/proxy/main.go # Stage 2: Build Node.js Frontend FROM node:20-alpine AS node-builder @@ -26,19 +27,22 @@ WORKDIR /app # Copy package files COPY web/package*.json ./web/ WORKDIR /app/web -RUN npm ci --only=production +RUN npm ci # Copy web source code and build COPY web/ ./ RUN npm run build +# Clean up dev dependencies after build +RUN npm ci --only=production && npm cache clean --force + # Stage 3: Production Runtime FROM node:20-alpine WORKDIR /app -# Install process manager for running multiple services -RUN npm install -g pm2 +# Install runtime dependencies +RUN apk add --no-cache sqlite wget # Create app user for security RUN addgroup -g 1001 -S appgroup && \ @@ -79,7 +83,7 @@ USER appuser # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT}/health || exit 1 + CMD wget -qO- http://localhost:3001/health > /dev/null || exit 1 # Start both services CMD ["./docker-entrypoint.sh"] \ No newline at end of file diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index bbf82f8..1ea9e68 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -12,101 +12,42 @@ echo "=========================================" cleanup() { echo "" echo "🛑 Shutting down services..." - pm2 delete all 2>/dev/null || true + kill $PROXY_PID $WEB_PID 2>/dev/null || true exit 0 } # Trap signals for graceful shutdown trap cleanup SIGTERM SIGINT -# Create PM2 ecosystem file -cat > /tmp/ecosystem.config.js << EOF -module.exports = { - apps: [ - { - name: 'proxy-server', - script: './bin/proxy', - cwd: '/app', - env: { - PORT: '${PORT}', - READ_TIMEOUT: '${READ_TIMEOUT}s', - WRITE_TIMEOUT: '${WRITE_TIMEOUT}s', - IDLE_TIMEOUT: '${IDLE_TIMEOUT}s', - ANTHROPIC_FORWARD_URL: '${ANTHROPIC_FORWARD_URL}', - ANTHROPIC_VERSION: '${ANTHROPIC_VERSION}', - ANTHROPIC_MAX_RETRIES: '${ANTHROPIC_MAX_RETRIES}', - DB_PATH: '${DB_PATH}' - }, - error_file: '/dev/stderr', - out_file: '/dev/stdout', - log_file: '/dev/stdout', - time: true - }, - { - name: 'web-server', - script: 'npm', - args: 'start', - cwd: '/app/web', - env: { - PORT: '${WEB_PORT}', - NODE_ENV: 'production' - }, - error_file: '/dev/stderr', - out_file: '/dev/stdout', - log_file: '/dev/stdout', - time: true - } - ] -}; -EOF - echo "📊 Configuration:" -echo " - Proxy Server: http://localhost:${PORT}" -echo " - Web Dashboard: http://localhost:${WEB_PORT}" +echo " - Proxy Server: http://0.0.0.0:${PORT}" +echo " - Web Dashboard: http://0.0.0.0:${WEB_PORT}" echo " - Database: ${DB_PATH}" echo " - Anthropic API: ${ANTHROPIC_FORWARD_URL}" echo "=========================================" -# Start services with PM2 +# Start proxy server echo "🔄 Starting proxy server..." -pm2 start /tmp/ecosystem.config.js --only proxy-server --no-daemon & +PORT=${PORT} \ +READ_TIMEOUT=${READ_TIMEOUT}s \ +WRITE_TIMEOUT=${WRITE_TIMEOUT}s \ +IDLE_TIMEOUT=${IDLE_TIMEOUT}s \ +ANTHROPIC_FORWARD_URL=${ANTHROPIC_FORWARD_URL} \ +ANTHROPIC_VERSION=${ANTHROPIC_VERSION} \ +ANTHROPIC_MAX_RETRIES=${ANTHROPIC_MAX_RETRIES} \ +DB_PATH=${DB_PATH} \ +./bin/proxy & +PROXY_PID=$! -# Wait for proxy to be ready -echo "⏳ Waiting for proxy server to start..." -timeout=30 -while [ $timeout -gt 0 ]; do - if wget --quiet --spider "http://localhost:${PORT}/health" 2>/dev/null; then - echo "✅ Proxy server is ready" - break - fi - sleep 1 - timeout=$((timeout - 1)) -done - -if [ $timeout -eq 0 ]; then - echo "❌ Proxy server failed to start within 30 seconds" - exit 1 -fi +# Wait for proxy to start +sleep 3 +# Start web server echo "🔄 Starting web server..." -pm2 start /tmp/ecosystem.config.js --only web-server --no-daemon & - -# Wait for web server to be ready -echo "⏳ Waiting for web server to start..." -timeout=30 -while [ $timeout -gt 0 ]; do - if wget --quiet --spider "http://localhost:${WEB_PORT}" 2>/dev/null; then - echo "✅ Web server is ready" - break - fi - sleep 1 - timeout=$((timeout - 1)) -done - -if [ $timeout -eq 0 ]; then - echo "❌ Web server failed to start within 30 seconds" - exit 1 -fi +cd web +PORT=${WEB_PORT} HOST=0.0.0.0 NODE_ENV=production npx remix-serve build/server/index.js & +WEB_PID=$! +cd .. echo "" echo "✨ All services started successfully!" @@ -118,5 +59,5 @@ echo "=========================================" echo "💡 To use with Claude Code, set: ANTHROPIC_BASE_URL=http://localhost:${PORT}" echo "" -# Keep container running and show logs -pm2 logs --raw \ No newline at end of file +# Wait for processes to finish +wait \ No newline at end of file