# Dockerfile for Canvas Server (Optional) # Provides the web interface, REST API, and SQLite persistence # Stage 1: Build frontend FROM node:20-slim AS frontend-builder WORKDIR /app COPY package*.json ./ RUN --mount=type=cache,target=/root/.npm npm ci --ignore-scripts COPY frontend ./frontend COPY vite.config.js ./ RUN npm run build:frontend # Stage 2: Build backend (TypeScript compilation + native modules) FROM node:20-slim AS backend-builder RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY package*.json ./ RUN --mount=type=cache,target=/root/.npm npm ci COPY src ./src COPY tsconfig.json ./ RUN npm run build:server # Stage 3: Production Canvas Server FROM node:20-slim AS production RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/* RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 --gid 1001 nodejs WORKDIR /app COPY package*.json ./ RUN --mount=type=cache,target=/root/.npm npm ci --omit=dev # Remove build tools after native modules are compiled RUN apt-get purge -y python3 make g++ && apt-get autoremove -y COPY --from=backend-builder /app/dist ./dist COPY --from=frontend-builder /app/dist/frontend ./dist/frontend RUN mkdir -p /app/data && chown -R nodejs:nodejs /app USER nodejs ENV NODE_ENV=production ENV PORT=3000 # HOST=0.0.0.0 is correct inside Docker: the container binds all interfaces, # but external access is gated by the published port mapping in docker-compose.yml. # For local dev without Docker, the server defaults to localhost (127.0.0.1). ENV HOST=0.0.0.0 ENV EXCALIDRAW_DB_PATH=/app/data/excalidraw.db EXPOSE 3000 CMD ["node", "dist/server.js"] LABEL org.opencontainers.image.source="https://github.com/sanjibdevnathlabs/mcp-excalidraw-local" LABEL org.opencontainers.image.description="MCP Excalidraw Canvas Server - Web UI and REST API (with SQLite persistence & multi-tenancy)" LABEL org.opencontainers.image.licenses="MIT"