Agent Skill
2/7/2026

docker-best-practices

Docker and Docker Compose best practices for Node.js applications. This skill should be used when writing, reviewing, or modifying Dockerfiles, docker-compose files, or container orchestration configs. Triggers on tasks involving Docker, containers, deployment, or infrastructure.

T
tombensim
0GitHub Stars
2Views
npx skills add tombensim/tlvsunflowers

SKILL.md

Namedocker-best-practices
DescriptionDocker and Docker Compose best practices for Node.js applications. This skill should be used when writing, reviewing, or modifying Dockerfiles, docker-compose files, or container orchestration configs. Triggers on tasks involving Docker, containers, deployment, or infrastructure.

name: docker-best-practices description: Docker and Docker Compose best practices for Node.js applications. This skill should be used when writing, reviewing, or modifying Dockerfiles, docker-compose files, or container orchestration configs. Triggers on tasks involving Docker, containers, deployment, or infrastructure. license: MIT metadata: author: orient-derived version: '1.0.0'

Docker Best Practices for Node.js

Comprehensive Docker guidelines for Node.js/TypeScript monorepo applications with PostgreSQL and Redis.

When to Apply

Reference these guidelines when:

  • Writing or modifying Dockerfiles
  • Configuring docker-compose services
  • Setting up local development environments
  • Preparing production deployment configs
  • Debugging container networking or health issues

Rule Categories

CategoryImpactPrefix
Multi-Stage BuildsCRITICALbuild-
SecurityCRITICALsecurity-
Compose PatternsHIGHcompose-
Health ChecksHIGHhealth-
Logging & MonitoringMEDIUMlogging-
Development WorkflowMEDIUMdev-

Rules

Multi-Stage Builds (CRITICAL)

build-multi-stage

Use multi-stage builds to separate build dependencies from production image.

Incorrect: single stage with dev dependencies

FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["node", "dist/index.js"]

Correct: multi-stage build

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY tsconfig.json ./
COPY src ./src
RUN npm run build

FROM node:20-alpine AS production
WORKDIR /app
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
COPY --from=builder /app/dist ./dist
RUN chown -R nodejs:nodejs /app
USER nodejs
ENV NODE_ENV=production
CMD ["node", "dist/index.js"]

Production image contains only runtime dependencies, reducing size by 60-80%.

build-layer-caching

Order Dockerfile instructions from least to most frequently changed for optimal layer caching.

# 1. Base image (rarely changes)
FROM node:20-alpine

# 2. System packages (rarely changes)
RUN apk add --no-cache dumb-init

# 3. Package files (changes on dependency updates)
COPY package*.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile

# 4. Source code (changes frequently)
COPY . .
RUN pnpm build

Security (CRITICAL)

security-non-root

Always run containers as non-root user.

RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodejs -u 1001
RUN chown -R nodejs:nodejs /app
USER nodejs

security-env-secrets

Never bake secrets into images. Use environment variables or mounted secrets.

Incorrect:

ENV DATABASE_URL=postgres://user:password@host/db

Correct:

# docker-compose.yml
services:
  backend:
    env_file: .env
    # or
    environment:
      - DATABASE_URL

Compose Patterns (HIGH)

compose-variants

Use multiple compose files for different environments.

docker-compose.yml          # Base services
docker-compose.dev.yml      # Development overrides (volumes, ports, hot-reload)
docker-compose.prod.yml     # Production config (restart policies, resource limits)
docker-compose.infra.yml    # Infrastructure only (postgres, redis)

Run with: docker compose -f docker-compose.yml -f docker-compose.dev.yml up

compose-depends-on

Use depends_on with health check conditions for service ordering.

services:
  backend:
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

  postgres:
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -U postgres']
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
      interval: 10s
      timeout: 5s
      retries: 5

compose-networking

Use a dedicated bridge network for service isolation.

services:
  backend:
    networks:
      - app-network
  postgres:
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

Health Checks (HIGH)

health-check-all-services

Add health checks to every service.

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

Logging (MEDIUM)

logging-json-file

Use json-file logging driver with size limits to prevent disk exhaustion.

services:
  backend:
    logging:
      driver: 'json-file'
      options:
        max-size: '5m'
        max-file: '2'

Development Workflow (MEDIUM)

dev-volume-mounts

Mount source code as volumes for hot-reload in development.

# docker-compose.dev.yml
services:
  backend:
    volumes:
      - ./apps/backend/src:/app/apps/backend/src
      - /app/node_modules # Prevent overwriting container node_modules
    command: pnpm dev

  frontend:
    volumes:
      - ./apps/frontend/src:/app/apps/frontend/src
    command: pnpm dev
    environment:
      - VITE_HMR_HOST=localhost

dev-host-docker-internal

Use host.docker.internal to connect from containers to host services during development.

services:
  backend:
    extra_hosts:
      - 'host.docker.internal:host-gateway'
    environment:
      - DATABASE_URL=postgres://postgres:postgres@host.docker.internal:5432/tennis
Skills Info
Original Name:docker-best-practicesAuthor:tombensim