Docker Deployment
Time to read: 15 minutes
Deploy your MCP server using Docker for consistent, reproducible deployments across any environment.
What You'll Learn
- Creating a Dockerfile
 - Building images
 - Running containers
 - Docker Compose
 - Production optimization
 
Basic Dockerfile
# Dockerfile
FROM node:20-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy built server
COPY dist ./dist
# Expose inspector port (optional for stdio mode)
EXPOSE 3000
# Run server
CMD ["node", "dist/index.js"]
Build & Run
Build Image
npm run build
docker build -t my-mcp-server .
Run Container
docker run -d \
  --name mcp-server \
  -p 3000:3000 \
  my-mcp-server
Multi-Stage Build
Optimize image size:
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/index.js"]
Environment Variables
Using .env
# Load environment variables
ENV NODE_ENV=production
ENV LOG_LEVEL=info
# Or use --env-file
docker run -d \
  --env-file .env.production \
  -p 3000:3000 \
  my-mcp-server
Docker Compose
docker-compose.yml
version: '3.8'
services:
  mcp-server:
    build: .
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      LOG_LEVEL: info
    volumes:
      - ./logs:/app/logs
    restart: unless-stopped
    
  # Optional: Add database
  database:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - db-data:/var/lib/postgresql/data
    
volumes:
  db-data:
Start Services
docker-compose up -d
Production Optimizations
Health Checks
HEALTHCHECK --interval=30s --timeout=3s \
  CMD node -e "require('http').get('http://localhost:3000/health', (r) => r.statusCode === 200 ? process.exit(0) : process.exit(1))"
Non-Root User
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs
Security
# Install security updates
RUN apk add --no-cache --upgrade bash
# Don't run as root
USER nodejs
Persistent Storage
Volumes
docker run -d \
  -v $(pwd)/logs:/app/logs \
  -v $(pwd)/data:/app/data \
  my-mcp-server
Networking
Connect Services
services:
  mcp-server:
    networks:
      - app-network
  
  redis:
    image: redis:alpine
    networks:
      - app-network
networks:
  app-network:
    driver: bridge
Best Practices
- Use multi-stage builds - Smaller images
 - Don't run as root - Security
 - Use .dockerignore - Exclude unnecessary files
 - Cache layers - Copy package.json first
 - Health checks - Monitor container health
 - Limit resources - Set memory/CPU limits
 - Use specific tags - node:20-alpine not node:latest
 
Example .dockerignore
node_modules
npm-debug.log
.git
.env
.env.local
dist
logs
*.log
Troubleshooting
Container Crashes
# View logs
docker logs mcp-server
# Check status
docker ps -a
Port Already in Use
# Change port mapping
docker run -d -p 3001:3000 my-mcp-server
Permission Issues
# Fix volume permissions
docker run -d \
  -v $(pwd)/logs:/app/logs \
  --user $(id -u):$(id -g) \
  my-mcp-server
Next Steps
Learn deployment strategies:
- Cloud Platforms - Deploy to AWS, GCP, Azure
 - Production Checklist - Pre-deployment guide
 - Logging - Container logging