docker
Installation
SKILL.md
Docker Skill
Container best practices for development, building, and deployment.
When to Use This Skill
- Writing Dockerfiles
- Configuring docker-compose
- Optimizing container images
- Container security
- Multi-stage builds
📦 Dockerfile Best Practices
Multi-Stage Build (Go)
# Build stage
FROM golang:1.22-alpine AS builder
WORKDIR /app
# Cache dependencies
COPY go.mod go.sum ./
RUN go mod download
# Build
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /app/server ./cmd/main.go
# Runtime stage
FROM alpine:3.19
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /app
# Copy binary from builder
COPY /app/server .
COPY /app/config.yaml .
# Non-root user
RUN adduser -D -g '' appuser
USER appuser
EXPOSE 8080
ENTRYPOINT ["./server"]
Multi-Stage Build (Node.js)
# Dependencies stage
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY /app/node_modules ./node_modules
COPY . .
RUN yarn build
# Runtime stage
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY /app/public ./public
COPY /app/.next/standalone ./
COPY /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
CMD ["node", "server.js"]
🔧 Layer Optimization
Order Matters
# ✅ Good: Least changing files first
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o app
# ❌ Bad: COPY all invalidates cache
COPY . .
RUN go mod download
RUN go build -o app
Reduce Layers
# ❌ Bad: Multiple RUN commands
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y git
RUN rm -rf /var/lib/apt/lists/*
# ✅ Good: Single RUN command
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
git && \
rm -rf /var/lib/apt/lists/*
Use .dockerignore
# Git
.git
.gitignore
# Dependencies
node_modules
vendor
# Build artifacts
dist
build
*.exe
# Development files
*.md
*.log
.env.local
.vscode
.idea
# Tests
*_test.go
__tests__
coverage
🐳 Docker Compose
Development Setup
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "8080:8080"
volumes:
- .:/app
- /app/node_modules # Exclude node_modules
environment:
- DATABASE_URL=postgres://user:pass@db:5432/app
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: app
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d app"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
Production Setup
version: '3.8'
services:
app:
image: ${REGISTRY}/app:${VERSION}
deploy:
replicas: 3
resources:
limits:
cpus: '1'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
environment:
- DATABASE_URL=${DATABASE_URL}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- app
🔒 Security
Run as Non-Root
# Create non-root user
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup
# Change ownership
COPY . .
# Switch to non-root user
USER appuser
Scan for Vulnerabilities
# Using Docker Scout
docker scout cves myimage:latest
# Using Trivy
trivy image myimage:latest
# Using Snyk
snyk container test myimage:latest
Read-Only Filesystem
services:
app:
read_only: true
tmpfs:
- /tmp
- /var/run
📊 Health Checks
HEALTHCHECK \
CMD curl -f http://localhost:8080/health || exit 1
// Health endpoint
func (h *Handler) Health(w http.ResponseWriter, r *http.Request) {
checks := map[string]string{
"database": h.checkDB(),
"redis": h.checkRedis(),
}
healthy := true
for _, status := range checks {
if status != "ok" {
healthy = false
break
}
}
if healthy {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(http.StatusServiceUnavailable)
}
json.NewEncoder(w).Encode(checks)
}
🛠️ Useful Commands
# Build
docker build -t myapp:latest .
docker build --no-cache -t myapp:latest . # Fresh build
# Run
docker run -d -p 8080:8080 --name myapp myapp:latest
docker run --rm -it myapp:latest /bin/sh # Interactive
# Logs
docker logs -f myapp
docker logs --tail 100 myapp
# Exec into container
docker exec -it myapp /bin/sh
# Cleanup
docker system prune -a # Remove all unused
docker volume prune # Remove unused volumes
docker image prune # Remove dangling images
# Inspect
docker stats # Resource usage
docker inspect myapp # Container details
docker history myapp # Image layers
📚 References
Weekly Installs
1
Repository
aiyuekuang/llmproxyGitHub Stars
11
First Seen
Mar 3, 2026
Security Audits
Installed on
mcpjam1
claude-code1
replit1
junie1
windsurf1
zencoder1