AgentSkillsCN

docker

Docker模式、Dockerfile、多阶段构建、Compose、开发环境/生产环境。触发条件:在编写Dockerfile、docker-compose或容器配置时。

SKILL.md
--- frontmatter
name: docker
description: >
  Docker patterns, Dockerfile, multi-stage builds, Compose, dev/prod.
  Trigger: When writing Dockerfiles, docker-compose, or container configuration.
license: Apache-2.0
metadata:
  author: gentleman-programming
  version: "1.0"

When to Use

  • Writing or modifying Dockerfiles
  • Configuring docker-compose services
  • Setting up dev vs production containers
  • Multi-stage builds for Node.js/NestJS/Nuxt
  • Database containers (MySQL, Redis)
  • CI/CD pipeline container configs

Critical Patterns

Multi-Stage Build (NestJS)

dockerfile
# Stage 1: Dependencies
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile

# Stage 2: Build
FROM node:22-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN corepack enable && pnpm build
RUN pnpm prune --prod

# Stage 3: Production
FROM node:22-alpine AS production
WORKDIR /app
RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -s /bin/sh -D appuser

COPY --from=build --chown=appuser:appgroup /app/dist ./dist
COPY --from=build --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=build --chown=appuser:appgroup /app/package.json ./

USER appuser
EXPOSE 3000
CMD ["node", "dist/main.js"]

Multi-Stage Build (Nuxt)

dockerfile
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile

FROM node:22-alpine AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN corepack enable && pnpm build

FROM node:22-alpine AS production
WORKDIR /app
RUN addgroup -g 1001 appgroup && adduser -u 1001 -G appgroup -s /bin/sh -D appuser

COPY --from=build --chown=appuser:appgroup /app/.output ./.output

USER appuser
EXPOSE 3000
CMD ["node", ".output/server/index.mjs"]

Docker Compose (Full Stack)

yaml
# docker-compose.yml
services:
  mysql:
    image: mysql:8.4
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
      target: production
    restart: unless-stopped
    ports:
      - "3001:3000"
    environment:
      DATABASE_URL: mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@mysql:3306/${MYSQL_DATABASE}
      JWT_SECRET: ${JWT_SECRET}
      NODE_ENV: production
    depends_on:
      mysql:
        condition: service_healthy

  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile
      target: production
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      NUXT_PUBLIC_API_BASE: http://backend:3000
    depends_on:
      - backend

volumes:
  mysql_data:

Dev Compose Override

yaml
# docker-compose.dev.yml
services:
  mysql:
    ports:
      - "3306:3306"

  backend:
    build:
      target: deps
    command: pnpm start:dev
    volumes:
      - ./backend:/app
      - /app/node_modules
    environment:
      NODE_ENV: development

  frontend:
    build:
      target: deps
    command: pnpm dev
    volumes:
      - ./frontend:/app
      - /app/node_modules
    environment:
      NODE_ENV: development
bash
# Dev
docker compose -f docker-compose.yml -f docker-compose.dev.yml up

# Prod
docker compose up -d

Dockerfile Rules

RuleWhy
Use specific image tags (node:22-alpine)Reproducible builds
Multi-stage buildsSmaller production images
COPY package.json before COPY .Cache dependencies layer
--frozen-lockfileDeterministic installs
Non-root user (USER appuser)Security
.dockerignore everything unnecessarySmaller context, faster builds
EXPOSE only needed portsDocumentation + security
healthcheck on servicesOrchestration reliability

.dockerignore

code
node_modules
.git
.env*
*.md
.nuxt
.output
dist
coverage
.vscode
.idea

Decision Tree

code
Dev environment with hot reload?  → Compose with volumes + target: deps
Production single service?        → Multi-stage Dockerfile
Full stack (DB + API + Frontend)? → docker-compose.yml
Need DB only for local dev?       → Compose with just mysql service
CI/CD pipeline?                   → Multi-stage + --target production

Commands

bash
# Build
docker build -t myapp .                          # Build image
docker build --target production -t myapp .       # Build specific stage

# Compose
docker compose up -d                              # Start detached
docker compose down                               # Stop and remove
docker compose down -v                            # Stop + remove volumes
docker compose logs -f backend                    # Follow logs
docker compose exec backend sh                    # Shell into container
docker compose build --no-cache                   # Rebuild without cache

# Debugging
docker ps                                         # Running containers
docker logs <container> -f                        # Follow logs
docker exec -it <container> sh                    # Shell access
docker stats                                      # Resource usage

# Cleanup
docker system prune -a                            # Remove unused images/containers
docker volume prune                               # Remove unused volumes

MySQL Container Tips

  • Always use healthcheck — prevents apps from connecting before MySQL is ready
  • Use named volumes (mysql_data) — anonymous volumes get lost on down
  • Set MYSQL_DATABASE env var — auto-creates database on first run
  • For Prisma migrations in Docker: run npx prisma migrate deploy as entrypoint script