Claude-skill-registry docker-web
Containerizes web applications with Docker for consistent deployments across environments. Use when creating Dockerfiles, building container images, or setting up Docker Compose for development.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/docker-web" ~/.claude/skills/majiayu000-claude-skill-registry-docker-web && rm -rf "$T"
manifest:
skills/data/docker-web/SKILL.mdsource content
Docker for Web Applications
Containerize web applications for consistent development and deployment across environments.
Quick Start
# Create Dockerfile touch Dockerfile # Build image docker build -t my-app . # Run container docker run -p 3000:3000 my-app # Docker Compose docker compose up
Node.js Dockerfile
Basic
FROM node:20-alpine WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build EXPOSE 3000 CMD ["node", "dist/index.js"]
Production Optimized
# Build stage FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Prune dev dependencies RUN npm prune --production # Production stage FROM node:20-alpine AS production WORKDIR /app # Create non-root user RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 nodeuser # Copy built app COPY --from=builder --chown=nodeuser:nodejs /app/dist ./dist COPY --from=builder --chown=nodeuser:nodejs /app/node_modules ./node_modules COPY --from=builder --chown=nodeuser:nodejs /app/package.json ./ USER nodeuser ENV NODE_ENV=production EXPOSE 3000 CMD ["node", "dist/index.js"]
Next.js Dockerfile
Standalone Output
FROM node:20-alpine AS deps WORKDIR /app COPY package*.json ./ RUN npm ci FROM node:20-alpine AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . RUN npm run build FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 nextjs COPY --from=builder /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0" CMD ["node", "server.js"]
next.config.js
/** @type {import('next').NextConfig} */ module.exports = { output: 'standalone', };
React (Vite) Dockerfile
# Build stage FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Production stage with nginx FROM nginx:alpine AS production COPY --from=builder /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
nginx.conf
server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; # Gzip gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml; # SPA routing location / { try_files $uri $uri/ /index.html; } # Cache static assets location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } }
Docker Compose
Development
# docker-compose.yml version: '3.8' services: app: build: context: . dockerfile: Dockerfile.dev ports: - "3000:3000" volumes: - .:/app - /app/node_modules environment: - NODE_ENV=development depends_on: - db - redis db: image: postgres:16-alpine ports: - "5432:5432" environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: myapp volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7-alpine ports: - "6379:6379" volumes: postgres_data:
Production
# docker-compose.prod.yml version: '3.8' services: app: build: context: . dockerfile: Dockerfile target: production ports: - "3000:3000" environment: - NODE_ENV=production - DATABASE_URL=postgres://user:password@db:5432/myapp depends_on: db: condition: service_healthy restart: unless-stopped db: image: postgres:16-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: myapp volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U user -d myapp"] interval: 5s timeout: 5s retries: 5 restart: unless-stopped volumes: postgres_data:
.dockerignore
# Dependencies node_modules npm-debug.log # Build output dist build .next # Git .git .gitignore # IDE .idea .vscode # Environment .env* !.env.example # Tests coverage *.test.js *.test.ts __tests__ # Docker Dockerfile* docker-compose* .dockerignore # Misc README.md *.md
Multi-Stage Best Practices
Separate Stages
# Base - shared configuration FROM node:20-alpine AS base WORKDIR /app ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable # Dependencies FROM base AS deps COPY package.json pnpm-lock.yaml ./ RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile # Build FROM base AS builder COPY --from=deps /app/node_modules ./node_modules COPY . . RUN pnpm build # Production deps only FROM base AS prod-deps COPY package.json pnpm-lock.yaml ./ RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile # Runner FROM base AS runner ENV NODE_ENV=production COPY --from=prod-deps /app/node_modules ./node_modules COPY --from=builder /app/dist ./dist CMD ["node", "dist/index.js"]
Build Arguments
ARG NODE_VERSION=20 FROM node:${NODE_VERSION}-alpine AS base ARG API_URL ENV NEXT_PUBLIC_API_URL=${API_URL}
docker build --build-arg NODE_VERSION=20 --build-arg API_URL=https://api.example.com .
Health Checks
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
# docker-compose.yml services: app: healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s
Security Best Practices
Non-Root User
RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 appuser USER appuser
Read-Only Filesystem
services: app: read_only: true tmpfs: - /tmp volumes: - app_data:/app/data
Security Scanning
# Scan image for vulnerabilities docker scout cves my-app # Trivy trivy image my-app
Common Commands
# Build docker build -t my-app . docker build -t my-app:v1.0 --target production . # Run docker run -p 3000:3000 my-app docker run -d --name my-app -p 3000:3000 my-app docker run --env-file .env my-app # Compose docker compose up docker compose up -d docker compose up --build docker compose down docker compose logs -f # Inspect docker ps docker logs my-app docker exec -it my-app sh # Clean up docker system prune docker image prune docker volume prune
See references/patterns.md for framework-specific patterns.