diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 12434a0c9f..18b6f35bd8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -74,7 +74,7 @@ jobs: - name: Validate Docker production build run: | echo "🐳 Testing Docker production target..." - docker build --target runtime . --no-cache --progress=plain + docker build --target bolt-ai-production . --no-cache --progress=plain echo "✅ Production target builds successfully" - name: Validate Docker development build diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 0fa38eec8a..32ea67ed52 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -57,7 +57,7 @@ jobs: with: context: . platforms: linux/amd64,linux/arm64 - target: runtime + target: bolt-ai-production push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile index 44960e2926..1ad0c1d162 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,10 @@ ENV CI=true # Use pnpm RUN corepack enable && corepack prepare pnpm@9.15.9 --activate +# Ensure git is available for build and runtime scripts +RUN apt-get update && apt-get install -y --no-install-recommends git \ + && rm -rf /var/lib/apt/lists/* + # Accept (optional) build-time public URL for Remix/Vite (Coolify can pass it) ARG VITE_PUBLIC_APP_URL ENV VITE_PUBLIC_APP_URL=${VITE_PUBLIC_APP_URL} @@ -25,68 +29,75 @@ RUN pnpm install --offline --frozen-lockfile # Build the Remix app (SSR + client) RUN NODE_OPTIONS=--max-old-space-size=4096 pnpm run build +# ---- production dependencies stage ---- +FROM build AS prod-deps + # Keep only production deps for runtime RUN pnpm prune --prod --ignore-scripts -# ---- runtime stage ---- -FROM node:22-bookworm-slim AS runtime +# ---- production stage ---- +FROM prod-deps AS bolt-ai-production WORKDIR /app ENV NODE_ENV=production -ENV PORT=3000 +ENV PORT=5173 ENV HOST=0.0.0.0 -# Install curl so Coolify’s healthcheck works inside the image +# Non-sensitive build arguments +ARG VITE_LOG_LEVEL=debug +ARG DEFAULT_NUM_CTX + +# Set non-sensitive environment variables +ENV WRANGLER_SEND_METRICS=false \ + VITE_LOG_LEVEL=${VITE_LOG_LEVEL} \ + DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX} \ + RUNNING_IN_DOCKER=true + +# Note: API keys should be provided at runtime via docker run -e or docker-compose +# Example: docker run -e OPENAI_API_KEY=your_key_here ... + +# Install curl for healthchecks and copy bindings script RUN apt-get update && apt-get install -y --no-install-recommends curl \ && rm -rf /var/lib/apt/lists/* -# Copy only what we need to run -COPY --from=build /app/build /app/build -COPY --from=build /app/node_modules /app/node_modules -COPY --from=build /app/package.json /app/package.json +# Copy built files and scripts +COPY --from=prod-deps /app/build /app/build +COPY --from=prod-deps /app/node_modules /app/node_modules +COPY --from=prod-deps /app/package.json /app/package.json +COPY --from=prod-deps /app/bindings.sh /app/bindings.sh + +# Pre-configure wrangler to disable metrics +RUN mkdir -p /root/.config/.wrangler && \ + echo '{"enabled":false}' > /root/.config/.wrangler/metrics.json -EXPOSE 3000 +# Make bindings script executable +RUN chmod +x /app/bindings.sh -# Healthcheck for Coolify +EXPOSE 5173 + +# Healthcheck for deployment platforms HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=5 \ - CMD curl -fsS http://localhost:3000/ || exit 1 + CMD curl -fsS http://localhost:5173/ || exit 1 -# Start the Remix server -CMD ["node", "build/server/index.js"] +# Start using dockerstart script with Wrangler +CMD ["pnpm", "run", "dockerstart"] # ---- development stage ---- FROM build AS development -# Define environment variables for development -ARG GROQ_API_KEY -ARG HuggingFace_API_KEY -ARG OPENAI_API_KEY -ARG ANTHROPIC_API_KEY -ARG OPEN_ROUTER_API_KEY -ARG GOOGLE_GENERATIVE_AI_API_KEY -ARG OLLAMA_API_BASE_URL -ARG XAI_API_KEY -ARG TOGETHER_API_KEY -ARG TOGETHER_API_BASE_URL +# Non-sensitive development arguments ARG VITE_LOG_LEVEL=debug ARG DEFAULT_NUM_CTX -ENV GROQ_API_KEY=${GROQ_API_KEY} \ - HuggingFace_API_KEY=${HuggingFace_API_KEY} \ - OPENAI_API_KEY=${OPENAI_API_KEY} \ - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} \ - OPEN_ROUTER_API_KEY=${OPEN_ROUTER_API_KEY} \ - GOOGLE_GENERATIVE_AI_API_KEY=${GOOGLE_GENERATIVE_AI_API_KEY} \ - OLLAMA_API_BASE_URL=${OLLAMA_API_BASE_URL} \ - XAI_API_KEY=${XAI_API_KEY} \ - TOGETHER_API_KEY=${TOGETHER_API_KEY} \ - TOGETHER_API_BASE_URL=${TOGETHER_API_BASE_URL} \ - AWS_BEDROCK_CONFIG=${AWS_BEDROCK_CONFIG} \ - VITE_LOG_LEVEL=${VITE_LOG_LEVEL} \ +# Set non-sensitive environment variables for development +ENV VITE_LOG_LEVEL=${VITE_LOG_LEVEL} \ DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX} \ RUNNING_IN_DOCKER=true +# Note: API keys should be provided at runtime via docker run -e or docker-compose +# Example: docker run -e OPENAI_API_KEY=your_key_here ... + RUN mkdir -p /app/run CMD ["pnpm", "run", "dev", "--host"] diff --git a/docker-compose.yaml b/docker-compose.yaml index 2aa38ae0bf..aff491123a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -38,7 +38,9 @@ services: app-dev: image: bolt-ai:development build: - target: bolt-ai-development + context: . + dockerfile: Dockerfile + target: development env_file: - '.env' - '.env.local' diff --git a/package.json b/package.json index 9352faeef9..1547920ce1 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "dockerstart": "bindings=$(./bindings.sh) && wrangler pages dev ./build/client $bindings --ip 0.0.0.0 --port 5173 --no-show-interactive-dev-session", "dockerrun": "docker run -it -d --name bolt-ai-live -p 5173:5173 --env-file .env.local bolt-ai", "dockerbuild:prod": "docker build -t bolt-ai:production -t bolt-ai:latest --target bolt-ai-production .", - "dockerbuild": "docker build -t bolt-ai:development -t bolt-ai:latest --target bolt-ai-development .", + "dockerbuild": "docker build -t bolt-ai:development -t bolt-ai:latest --target development .", "typecheck": "tsc", "typegen": "wrangler types", "preview": "pnpm run build && pnpm run start",