Claude Code Plugins

Community-maintained marketplace

Feedback
0
0

Build and deploy Docker containers for Node.js applications. Use when containerizing applications, optimizing Docker builds, or configuring container security.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name containerization
description Build and deploy Docker containers for Node.js applications. Use when containerizing applications, optimizing Docker builds, or configuring container security.
allowed-tools Read, Write, Edit, Bash, Glob, Grep

Containerization Skill

Build secure, optimized Docker containers for Node.js applications.

Core Principles

Principle Description
Minimal Images Use slim base images, multi-stage builds
Non-root User Never run as root in production
Layer Caching Order Dockerfile for optimal caching
Security First No secrets in images, scan for vulnerabilities
Reproducible Pin versions, use lock files

Project Structure

project/
├── Dockerfile              # Production image
├── Dockerfile.dev          # Development with hot reload
├── docker-compose.yml      # Multi-container orchestration
├── docker-compose.dev.yml  # Development overrides
├── .dockerignore           # Files to exclude from build
└── .env.example            # Environment variable template

Production Dockerfile

Node.js Application

# syntax=docker/dockerfile:1

# Stage 1: Dependencies
FROM node:20-slim AS deps
WORKDIR /app

# Install dependencies only (cached unless package files change)
COPY package.json package-lock.json ./
RUN npm ci --only=production

# Stage 2: Build
FROM node:20-slim AS build
WORKDIR /app

# Install all dependencies including devDependencies
COPY package.json package-lock.json ./
RUN npm ci

# Copy source and build
COPY . .
RUN npm run build

# Stage 3: Production
FROM node:20-slim AS production
WORKDIR /app

# Create non-root user
RUN groupadd --gid 1001 nodejs && \
    useradd --uid 1001 --gid nodejs --shell /bin/bash --create-home nodejs

# Copy production dependencies from deps stage
COPY --from=deps --chown=nodejs:nodejs /app/node_modules ./node_modules

# Copy built application from build stage
COPY --from=build --chown=nodejs:nodejs /app/dist ./dist
COPY --from=build --chown=nodejs:nodejs /app/package.json ./

# Set environment
ENV NODE_ENV=production
ENV PORT=3000

# Switch to non-root user
USER nodejs

# Expose port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"

# Start application
CMD ["node", "dist/server.js"]

Static Site (Nginx)

# syntax=docker/dockerfile:1

# Stage 1: Build
FROM node:20-slim AS build
WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

COPY . .
RUN npm run build

# Stage 2: Serve
FROM nginx:alpine AS production

# Copy custom nginx config
COPY nginx.conf /etc/nginx/nginx.conf

# Copy built static files
COPY --from=build /app/dist /usr/share/nginx/html

# Create non-root user for nginx
RUN chown -R nginx:nginx /usr/share/nginx/html && \
    chown -R nginx:nginx /var/cache/nginx && \
    chown -R nginx:nginx /var/log/nginx && \
    touch /var/run/nginx.pid && \
    chown -R nginx:nginx /var/run/nginx.pid

USER nginx

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s \
  CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1

CMD ["nginx", "-g", "daemon off;"]

Development Dockerfile

# Dockerfile.dev
FROM node:20-slim

WORKDIR /app

# Install dependencies (will be mounted over in dev)
COPY package.json package-lock.json ./
RUN npm install

# Copy source (will be mounted over in dev)
COPY . .

ENV NODE_ENV=development

EXPOSE 3000

# Use nodemon for hot reload
CMD ["npx", "nodemon", "--watch", "src", "src/server.js"]

Docker Compose

Production

# docker-compose.yml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=${DATABASE_URL}
    env_file:
      - .env.production
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health')"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 128M

  postgres:
    image: postgres:16-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=${DB_NAME}
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  postgres_data:

Development

# docker-compose.dev.yml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    volumes:
      # Mount source for hot reload
      - ./src:/app/src:delegated
      - ./package.json:/app/package.json
      # Exclude node_modules from mount
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DEBUG=app:*
    env_file:
      - .env.development

  postgres:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=devuser
      - POSTGRES_PASSWORD=devpass
      - POSTGRES_DB=devdb
    volumes:
      - postgres_dev_data:/var/lib/postgresql/data

volumes:
  postgres_dev_data:

.dockerignore

# Git
.git
.gitignore

# Node
node_modules
npm-debug.log

# Build output (will be created in container)
dist
build

# Development
.env
.env.local
.env.*.local
*.log

# IDE
.vscode
.idea
*.swp
*.swo

# Documentation
*.md
docs/

# Tests
test/
tests/
__tests__/
*.test.js
*.spec.js
coverage/

# CI/CD
.github/
.gitlab-ci.yml
Jenkinsfile

# Docker (prevent recursive copying)
Dockerfile*
docker-compose*
.dockerignore

Security Best Practices

Non-root User

# Create user with specific UID/GID
RUN groupadd --gid 1001 appgroup && \
    useradd --uid 1001 --gid appgroup --shell /bin/false --no-create-home appuser

# Set ownership
COPY --chown=appuser:appgroup . .

# Switch to non-root
USER appuser

Secret Management

# DON'T: Embed secrets in image
ENV API_KEY=secret123  # Bad!

# DO: Pass at runtime
# docker run -e API_KEY=secret123 myapp

# DO: Use Docker secrets (Swarm/Compose)
# docker secret create api_key ./api_key.txt

# DO: Use BuildKit secrets for build-time secrets
RUN --mount=type=secret,id=npm_token \
    NPM_TOKEN=$(cat /run/secrets/npm_token) npm ci

Vulnerability Scanning

# Scan image for vulnerabilities
docker scout cves myapp:latest

# Or use Trivy
trivy image myapp:latest

# Scan during CI
docker scout cves --exit-code --only-severity critical,high myapp:latest

Read-only Filesystem

# docker-compose.yml
services:
  app:
    read_only: true
    tmpfs:
      - /tmp
      - /var/run

Layer Optimization

Order for Best Caching

# 1. Base image and system deps (rarely changes)
FROM node:20-slim
RUN apt-get update && apt-get install -y --no-install-recommends dumb-init

# 2. Package files (changes when dependencies change)
COPY package.json package-lock.json ./

# 3. Install dependencies (cached unless package files change)
RUN npm ci --only=production

# 4. Application code (changes frequently)
COPY . .

# 5. Build step (runs when code changes)
RUN npm run build

Multi-stage Build Benefits

Stage Purpose Final Image
deps Install production dependencies Copied
build Install all deps, compile TypeScript Build artifacts only
production Runtime only Final image

Health Checks

HTTP Health Check

HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
  CMD node -e "require('http').get('http://localhost:3000/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"

Application Health Endpoint

// src/api/health.js
export function healthHandler(req, res) {
  const health = {
    status: 'healthy',
    timestamp: new Date().toISOString(),
    uptime: process.uptime(),
    memory: process.memoryUsage(),
    checks: {
      database: await checkDatabase(),
      redis: await checkRedis()
    }
  };

  const isHealthy = Object.values(health.checks).every(c => c === true);

  res.status(isHealthy ? 200 : 503).json(health);
}

Common Commands

# Build image
docker build -t myapp:latest .

# Build with BuildKit (recommended)
DOCKER_BUILDKIT=1 docker build -t myapp:latest .

# Build specific stage
docker build --target build -t myapp:build .

# Run container
docker run -p 3000:3000 --env-file .env myapp:latest

# Development with compose
docker compose -f docker-compose.yml -f docker-compose.dev.yml up

# Production
docker compose up -d

# View logs
docker compose logs -f app

# Shell into container
docker compose exec app sh

# Rebuild single service
docker compose up -d --build app

# Prune unused images
docker image prune -a

DigitalOcean Deployment

App Platform (app.yaml)

name: my-app
services:
  - name: web
    dockerfile_path: Dockerfile
    source_dir: /
    github:
      repo: username/repo
      branch: main
    http_port: 3000
    instance_size_slug: basic-xxs
    instance_count: 1
    health_check:
      http_path: /health

Droplet Deployment

# Build and push to registry
docker build -t registry.digitalocean.com/myregistry/myapp:latest .
docker push registry.digitalocean.com/myregistry/myapp:latest

# On droplet
docker pull registry.digitalocean.com/myregistry/myapp:latest
docker compose up -d

Checklist

When containerizing:

  • Multi-stage build used for smaller images
  • Running as non-root user
  • No secrets in Dockerfile or image
  • .dockerignore excludes unnecessary files
  • Health check configured
  • Layer order optimized for caching
  • Vulnerability scan passes
  • Resource limits set in compose

Related Skills

  • deployment - Deploy containers to infrastructure
  • ci-cd - Build images in CI pipeline
  • security - Container security practices
  • nodejs-backend - Node.js application patterns