Dockerfile•1.93 kB
# Multi-stage build for optimization
FROM node:18-alpine AS builder
# Build arguments
ARG BUILDTIME
ARG VERSION
ARG REVISION
# Create app directory
WORKDIR /usr/src/app
# Copy package files and tsconfig
COPY package*.json tsconfig.json ./
# Install all dependencies (including dev dependencies for build)
RUN npm ci && npm cache clean --force
# Copy source code
COPY src/ ./src/
# Build TypeScript
RUN npm run build
# Production stage
FROM node:18-alpine AS production
# Build arguments
ARG BUILDTIME
ARG VERSION
ARG REVISION
# Add build info as labels
LABEL org.opencontainers.image.created=${BUILDTIME}
LABEL org.opencontainers.image.version=${VERSION}
LABEL org.opencontainers.image.revision=${REVISION}
LABEL org.opencontainers.image.title="Cisco Support MCP Server"
LABEL org.opencontainers.image.description="MCP server for Cisco Support APIs including Bug Search and future tools"
LABEL org.opencontainers.image.vendor="Cisco Support MCP Server"
LABEL org.opencontainers.image.licenses="MIT"
# Create non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodeuser -u 1001
# Create app directory
WORKDIR /usr/src/app
# Copy package files
COPY package*.json ./
# Install only production dependencies
RUN npm ci --only=production && npm cache clean --force
# Copy built application from builder stage
COPY --from=builder /usr/src/app/dist ./dist
# Copy .env.example for reference
COPY --chown=nodeuser:nodejs .env.example ./
# Create logs directory
RUN mkdir -p logs && chown -R nodeuser:nodejs logs
# Expose port
EXPOSE 3000
# Switch to non-root user
USER nodeuser
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', (res) => { \
process.exit(res.statusCode === 200 ? 0 : 1); \
}).on('error', () => process.exit(1));"
# Start the application
CMD ["node", "dist/index.js", "--http"]