Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Docker Ops

BSecurity

Dockerfile best practices, multi-stage builds, docker-compose, container networking, volume management, and image optimization.

530 stars
0 votes
0 copies
0 views
Added 5/29/2026
ai-agentstypescriptpythongoshellbashsqlnodeexpressdockerdebugging

Works with

api

Security Analysis

B76/100
mediumUses curl or wget to download content
criticalExfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study
mediumInstalls packages at runtime which could introduce malicious dependencies
mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned 5/29/2026

$npx -y skills add vibeeval/vibecosystem --skill docker-ops --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Docker Ops?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Docker Ops
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/vibeeval-docker-ops/badge)](https://www.skillsdirectory.com/skills/vibeeval-docker-ops)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: docker-ops
description: Dockerfile best practices, multi-stage builds, docker-compose, container networking, volume management, and image optimization.
---

# Docker Operations

Practical patterns for building, running, and maintaining containers in production.

## Multi-Stage Builds

Minimize final image size by separating build-time dependencies from runtime.

```dockerfile
# Stage 1: Builder
FROM node:20-alpine AS builder
WORKDIR /app

# Copy dependency manifests first (layer cache)
COPY package*.json ./
RUN npm ci --only=production

COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build

# Stage 2: Runtime (no devDependencies, no source files)
FROM node:20-alpine AS runtime
WORKDIR /app

# Security: run as non-root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist

USER appuser

EXPOSE 3000
CMD ["node", "dist/index.js"]
```

```dockerfile
# Python multi-stage example
FROM python:3.12-slim AS builder
WORKDIR /app

RUN pip install --upgrade pip
COPY requirements.txt .
RUN pip install --prefix=/install -r requirements.txt

FROM python:3.12-slim AS runtime
WORKDIR /app

COPY --from=builder /install /usr/local
COPY src/ ./src/

RUN useradd -r -s /bin/false appuser
USER appuser

CMD ["python", "-m", "src.main"]
```

## Docker Compose for Multi-Service Environments

```yaml
# docker-compose.yml
version: '3.9'

services:
  api:
    build:
      context: .
      dockerfile: Dockerfile
      target: runtime
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://user:pass@postgres:5432/appdb
      - REDIS_URL=redis://redis:6379
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started
    restart: unless-stopped
    networks:
      - internal
    deploy:
      resources:
        limits:
          memory: 512m
          cpus: '0.5'

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: appdb
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d appdb"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - internal

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes
    networks:
      - internal

volumes:
  postgres_data:
  redis_data:

networks:
  internal:
    driver: bridge
```

## Container Networking

```bash
# Bridge network (default, same host)
docker network create --driver bridge my-network
docker run --network my-network --name service-a my-image

# Containers on same bridge network communicate by name
curl http://service-a:3000/health

# Host network (container shares host network stack, Linux only)
docker run --network host my-image

# Overlay network (multi-host, Docker Swarm or manual)
docker network create --driver overlay --attachable my-overlay
```

```yaml
# Compose network isolation example
services:
  frontend:
    networks:
      - public      # exposed to outside

  api:
    networks:
      - public      # receives traffic from frontend
      - internal    # talks to DB

  postgres:
    networks:
      - internal    # NOT reachable from frontend

networks:
  public:
  internal:
    internal: true  # blocks external traffic
```

## Volume Management

```yaml
# Named volumes (managed by Docker, persistent)
volumes:
  db_data:          # docker manages path
  uploads:
    driver: local

services:
  app:
    volumes:
      - uploads:/app/uploads         # named volume
      - ./config:/app/config:ro      # bind mount (read-only)
      - type: tmpfs                  # in-memory, discarded on stop
        target: /tmp
        tmpfs:
          size: 100m
```

```bash
# Volume lifecycle commands
docker volume ls
docker volume inspect my-volume
docker volume rm my-volume
docker volume prune           # remove all unused volumes (careful in prod)

# Backup a named volume
docker run --rm \
  -v my-volume:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/volume-backup.tar.gz -C /source .

# Restore
docker run --rm \
  -v my-volume:/target \
  -v $(pwd):/backup \
  alpine tar xzf /backup/volume-backup.tar.gz -C /target
```

## Health Checks

```dockerfile
# HEALTHCHECK in Dockerfile
HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1
```

```yaml
# Override in docker-compose
services:
  api:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      start_period: 20s
      retries: 3
```

```typescript
// Express health endpoint
app.get('/health', (req, res) => {
  res.json({
    status: 'ok',
    uptime: process.uptime(),
    timestamp: new Date().toISOString()
  })
})
```

## .dockerignore Best Practices

```
# .dockerignore
node_modules
.git
.gitignore
*.log
*.md
.env
.env.*
coverage/
dist/
.next/
__pycache__/
*.pyc
.pytest_cache/
.mypy_cache/
Dockerfile*
docker-compose*.yml
.dockerignore
```

## Image Layer Caching Optimization

```dockerfile
# BAD: invalidates cache on any source change
COPY . .
RUN npm install

# GOOD: dependency layer cached unless package.json changes
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
```

```dockerfile
# Python: cache pip install separately
COPY requirements.txt .
RUN pip install -r requirements.txt   # cached until requirements.txt changes

COPY . .
```

## Environment Variable Management

```yaml
# docker-compose: prefer env_file over inline secrets
services:
  api:
    env_file:
      - .env.production         # loaded from file, not committed
    environment:
      - NODE_ENV=production     # override specific vars inline
```

```dockerfile
# ARG (build-time only, not in final image)
ARG BUILD_VERSION=unknown
LABEL version=$BUILD_VERSION

# ENV (runtime, visible in container)
ENV PORT=3000
ENV LOG_LEVEL=info
```

## Docker Secrets vs Env Vars

```yaml
# Docker Swarm secrets (production approach)
secrets:
  db_password:
    external: true

services:
  api:
    secrets:
      - db_password
    # Secret mounted at /run/secrets/db_password (file)
```

```typescript
// Read secret from file (not env var)
import { readFileSync } from 'fs'

function getSecret(name: string): string {
  const secretPath = `/run/secrets/${name}`
  try {
    return readFileSync(secretPath, 'utf-8').trim()
  } catch {
    return process.env[name.toUpperCase()] ?? ''
  }
}

const dbPassword = getSecret('db_password')
```

## Container Resource Limits

```yaml
# docker-compose deploy limits
services:
  api:
    deploy:
      resources:
        limits:
          cpus: '0.5'          # max 50% of one CPU
          memory: 512m
        reservations:
          cpus: '0.25'
          memory: 256m
```

```bash
# docker run resource flags
docker run \
  --memory="512m" \
  --memory-swap="1g" \
  --cpus="0.5" \
  my-image
```

## Image Scanning for Vulnerabilities

```bash
# Trivy (recommended, free)
trivy image my-app:latest
trivy image --severity HIGH,CRITICAL my-app:latest
trivy image --exit-code 1 --severity CRITICAL my-app:latest  # fail on critical

# Snyk (SaaS, requires account)
snyk container test my-app:latest

# Docker Scout (built-in with Docker Desktop)
docker scout cves my-app:latest
docker scout recommendations my-app:latest
```

## Debugging Containers

```bash
# View logs
docker logs -f container-name
docker logs --tail 100 container-name
docker compose logs -f service-name

# Exec into running container
docker exec -it container-name sh
docker exec -it container-name bash

# Inspect container metadata
docker inspect container-name
docker inspect --format '{{.NetworkSettings.IPAddress}}' container-name

# Check resource usage
docker stats
docker stats --no-stream container-name

# Copy files to/from container
docker cp container-name:/app/logs/error.log ./error.log
docker cp ./config.json container-name:/app/config.json
```

## PID 1 Problem and Signal Handling (tini)

```dockerfile
# BAD: Node.js as PID 1 does not forward signals properly
CMD ["node", "dist/index.js"]

# GOOD: use tini as init process
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "dist/index.js"]
```

```yaml
# docker-compose init option (Docker 18.06+)
services:
  api:
    init: true      # uses tini automatically
```

```typescript
// Graceful shutdown in Node.js
process.on('SIGTERM', async () => {
  console.log('SIGTERM received, shutting down gracefully')
  await server.close()
  await db.disconnect()
  process.exit(0)
})
```

## Common Pitfalls

```dockerfile
# AVOID: running as root
# USER root  ← dangerous

# AVOID: latest tag in production
# FROM node:latest  ← use specific version

# AVOID: installing dev tools in production image
# RUN apt-get install -y vim curl wget

# AVOID: secrets in build args (visible in image history)
# ARG SECRET_KEY=abc123

# PREFER: specific digest for reproducible builds
FROM node:20.11.0-alpine@sha256:abc123...
```

**Key principle**: Keep images small, run as non-root, pin versions, use multi-stage builds, always define health checks.

Attribution

vibeevalvibeeval
View sourceSee grades on GitHubMore from vibeeval →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698461 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →