원클릭으로
docker-deployment
Production-ready Docker configurations, multi-stage builds, and deployment best practices
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Production-ready Docker configurations, multi-stage builds, and deployment best practices
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Structured divergence engine. Generates a wide, deliberately non-anchored set of approaches to a consequential, open-ended problem by spawning isolated parallel sub-agents under different cognitive frames, then a separate critic pass scores, declusters, and deepens the best. The divergent complement to /deep-analysis. Use for high-stakes architecture, strategy, design-space, and "what are our options" decisions. Auto-activates on diverge, brainstorm options, explore alternatives, what are our options, de-anchor, divergent thinking, option space, consider alternatives, multiple approaches.
Orchestrated task execution engine. Decomposes any goal into small atomic tasks, plans dependencies, selects the right agent/tool/MCP server for each, executes in optimally parallel batches, and tracks everything. Use when given a complex, multi-step goal that benefits from structured decomposition and full tool utilization.
Advanced multi-agent patterns using Claude Code's built-in orchestration. Teams, background agents, coordinator pattern, worker restrictions, SendMessage protocol, fork subagents. Auto-activates on multi-agent, orchestrate, team, coordinator, parallel agents, worker agents, background agent, agent swarm.
Structured multi-step reasoning for complex problems using the sequential-thinking MCP server. Use when facing architectural decisions, performance bottlenecks, complex debugging, design trade-offs, technology selection, or any problem requiring rigorous step-by-step analysis with hypothesis testing.
Deep root cause analysis engine. Systematically investigates bugs, crashes, unexpected behavior, and performance issues through an 8-phase diagnostic protocol. Uses structured reasoning (sequential-thinking MCP), multi-pass codebase analysis, git forensics, evidence-based hypothesis testing, and the 5 Whys method. Never jumps to a fix — always proves the root cause first.
Comprehensive codebase reading engine. Systematically reads actual source code line by line through a 6-phase protocol — scoping, structural mapping, execution tracing, deep reading, pattern synthesis, and structured reporting. Source code is the source of truth. Use when needing to truly understand how code works, not just what documentation claims.
| name | docker-deployment |
| description | Production-ready Docker configurations, multi-stage builds, and deployment best practices |
Provides production-ready Docker configurations, multi-stage builds, and deployment best practices.
This skill provides:
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies (including dev dependencies for build)
RUN npm ci
# Copy source code
COPY . .
# Build the application
RUN npm run build
# Prune dev dependencies
RUN npm prune --production
# Production stage
FROM node:20-alpine AS production
# Add non-root user for security
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
WORKDIR /app
# Copy built artifacts and production dependencies
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=nodejs:nodejs /app/package*.json ./
# Use 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/index.js"]
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 . .
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
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
CMD ["node", "server.js"]
FROM python:3.11-slim AS builder
WORKDIR /app
# Install build dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc && \
rm -rf /var/lib/apt/lists/*
# Copy requirements
COPY requirements.txt .
# Install Python dependencies
RUN pip install --user --no-cache-dir -r requirements.txt
# Production stage
FROM python:3.11-slim
WORKDIR /app
# Copy Python dependencies from builder
COPY --from=builder /root/.local /root/.local
# Copy application code
COPY . .
# Add local bin to PATH
ENV PATH=/root/.local/bin:$PATH
# Create non-root user
RUN useradd -m -u 1001 appuser && \
chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health').read()"
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
version: '3.9'
services:
# Frontend (Next.js)
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://api:4000
depends_on:
api:
condition: service_healthy
networks:
- app-network
restart: unless-stopped
# Backend API (Node.js)
api:
build:
context: ./api
dockerfile: Dockerfile
ports:
- "4000:4000"
environment:
- DATABASE_URL=postgresql://postgres:password@postgres:5432/myapp
- REDIS_URL=redis://redis:6379
- NODE_ENV=production
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:4000/health')"]
interval: 10s
timeout: 3s
retries: 3
start_period: 30s
networks:
- app-network
restart: unless-stopped
volumes:
- ./api/uploads:/app/uploads
# PostgreSQL Database
postgres:
image: postgres:16-alpine
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=myapp
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init-db.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5
networks:
- app-network
restart: unless-stopped
# Redis Cache
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
networks:
- app-network
restart: unless-stopped
# Nginx Reverse Proxy
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- frontend
- api
networks:
- app-network
restart: unless-stopped
networks:
app-network:
driver: bridge
volumes:
postgres-data:
redis-data:
# Use distroless for minimal attack surface
FROM gcr.io/distroless/nodejs20-debian12
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["dist/index.js"]
FROM node:20-alpine
# Security: Run as non-root
RUN addgroup -g 1001 app && \
adduser -D -u 1001 -G app app
WORKDIR /app
# Security: Use specific versions
COPY package*.json ./
RUN npm ci --only=production && \
npm cache clean --force
# Security: Set file permissions
COPY --chown=app:app . .
# Security: Drop capabilities
USER app
# Security: Read-only filesystem
# (mount volumes for writable areas)
VOLUME ["/app/data"]
EXPOSE 3000
CMD ["node", "index.js"]
# Dependencies
node_modules
npm-debug.log
# Testing
coverage
.jest
*.test.js
# Environment
.env
.env.local
.env.*.local
# Git
.git
.gitignore
# CI/CD
.github
.gitlab-ci.yml
# Documentation
README.md
docs/
# Build artifacts
dist
build
*.log
# IDE
.vscode
.idea
*.swp
# .github/workflows/docker-publish.yml
name: Docker Build & Push
on:
push:
branches: [ main ]
tags: [ 'v*' ]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
// health.ts
export function setupHealthCheck(app: Express) {
app.get('/health', async (req, res) => {
const checks = {
uptime: process.uptime(),
timestamp: Date.now(),
database: await checkDatabase(),
redis: await checkRedis(),
memory: process.memoryUsage(),
}
const isHealthy = checks.database && checks.redis
res.status(isHealthy ? 200 : 503).json(checks)
})
}
async function checkDatabase(): Promise<boolean> {
try {
await db.raw('SELECT 1')
return true
} catch {
return false
}
}
async function checkRedis(): Promise<boolean> {
try {
await redis.ping()
return true
} catch {
return false
}
}
services:
app:
image: myapp:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels:
- "prometheus.scrape=true"
- "prometheus.port=9090"
// metrics.ts
import promClient from 'prom-client'
const register = new promClient.Registry()
promClient.collectDefaultMetrics({ register })
const httpRequestDuration = new promClient.Histogram({
name: 'http_request_duration_ms',
help: 'Duration of HTTP requests in ms',
labelNames: ['method', 'route', 'status_code'],
buckets: [10, 50, 100, 500, 1000, 5000],
})
register.registerMetric(httpRequestDuration)
export function setupMetrics(app: Express) {
app.get('/metrics', async (req, res) => {
res.set('Content-Type', register.contentType)
res.end(await register.metrics())
})
}
latest).dockerignore to exclude unnecessary filesWorks best with: