Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
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
  • 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

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Docker Containerization Skill

CSecurity

Create and optimize Dockerfiles — multi-stage builds, compose patterns, layer caching, .dockerignore, health checks, hadolint/docker scout scanning.

6 stars
0 votes
0 copies
0 views
Added 9/20/2026
devopsjavascriptpythongojavashellbashsqlnextjsnodenodejs

Works with

vscodeapi

Security Analysis

C72/100
criticalAccesses sensitive system or user directories
highPerforms destructive filesystem operations
mediumInstalls packages at runtime which could introduce malicious dependencies
mediumInstalls packages at runtime which could introduce malicious dependencies

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add darellchua2/opencode-config-template --skill docker-containerization-skill --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Docker Containerization Skill?

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

Security grade badge for Docker Containerization Skill
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/darellchua2-docker-containerization-skill/badge)](https://www.skillsdirectory.com/skills/darellchua2-docker-containerization-skill)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: docker-containerization-skill
description: >-
  Create and optimize Dockerfiles — multi-stage builds, compose patterns, layer
  caching, .dockerignore, health checks, hadolint/docker scout scanning.
license: Apache-2.0
compatibility: opencode
category: DevOps
---

## What I do

I help you create, optimize, and secure Docker containers:

1. **Dockerfile Authoring**: Write production-grade Dockerfiles with multi-stage builds
2. **Image Optimization**: Reduce image size with distroless, Alpine, and layer strategies
3. **Docker Compose**: Design development and production compose configurations
4. **Layer Caching**: Structure builds for maximum cache efficiency
5. **Health Checks**: Implement proper health check endpoints and probes
6. **Security Scanning**: Scan images with hadolint (linting) and docker scout (vulnerabilities)

## When to use me

Use this skill when:
- Writing or optimizing a Dockerfile for a new or existing project
- Setting up docker-compose for local development or production deployment
- Reducing Docker image size
- Debugging container build failures or slow builds
- Implementing health checks and graceful shutdown
- Setting up multi-container architectures
- Scanning containers for security issues
- Creating .dockerignore files

## Related Skills

- **opentofu-provisioning-workflow-skill**: Handles infrastructure provisioning. This skill handles container image building and composition.
- **security-audit-skill**: Handles application-level security auditing. This skill handles container-specific security (image scanning, hadolint).

---

## Step 1: Dockerfile Templates

### Node.js (Next.js)

```dockerfile
FROM node:20-alpine AS base
RUN apk add --no-cache libc6-compat
WORKDIR /app

FROM base AS deps
COPY package.json pnpm-lock.yaml ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile

FROM base AS builder
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN corepack enable pnpm && pnpm build

FROM base AS runner
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nextjs

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 HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
```

### Python (FastAPI)

```dockerfile
FROM python:3.12-slim AS base
RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential && rm -rf /var/lib/apt/lists/*
WORKDIR /app

FROM base AS deps
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

FROM base AS runner
COPY --from=deps /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=deps /usr/local/bin /usr/local/bin
COPY . .

RUN groupadd -r appuser && useradd -r -g appuser appuser
USER appuser

EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
    CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
```

### Go

```dockerfile
FROM golang:1.22-alpine AS builder
RUN apk add --no-cache git
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /app/server ./cmd/server

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/server /server
EXPOSE 8080
USER nonroot:nonroot
ENTRYPOINT ["/server"]
```

## Step 2: Image Size Optimization

### Strategy Matrix

| Technique | Size Reduction | Best For |
|-----------|---------------|----------|
| Multi-stage build | 50-80% | All compiled languages |
| Alpine base | 30-50% | Python, Node.js, Go |
| Distroless | 40-60% | Go, static binaries |
| `.dockerignore` | 10-30% | All projects |
| Layer squashing | 10-20% | Complex builds |
| `--no-cache-dir` (pip) | 5-15% | Python |
| `--frozen-lockfile` | Prevents bloat | Node.js |

### .dockerignore Template

```
.git
.github
.gitignore
node_modules
__pycache__
*.pyc
.pytest_cache
.venv
.env
.env.*
*.md
LICENSE
docker-compose*.yml
Dockerfile*
.dockerignore
.vscode
.idea
coverage
.nyc_output
dist
build
.next
*.log
```

## Step 3: Docker Compose Patterns

### Development

```yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: deps
    volumes:
      - .:/app
      - /app/node_modules
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - DATABASE_URL=postgresql://postgres:postgres@db:5432/app_dev
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: app_dev
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  pgdata:
```

### Production

```yaml
services:
  app:
    image: ghcr.io/org/app:${VERSION:-latest}
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=${DATABASE_URL}
    healthcheck:
      test: ["CMD", "node", "-e", "fetch('http://localhost:3000/api/health').then(r=>r.ok?process.exit(0):process.exit(1))"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "0.5"
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
```

## Step 4: Layer Caching Optimization

### Rules

1. **Copy dependency files first** — `package.json`, `requirements.txt`, `go.mod`
2. **Install dependencies** — changes when deps change
3. **Copy source code last** — changes most frequently
4. **Order from least to most frequently changing**

### Cache Check

```bash
docker build --no-cache -t app:latest .
docker history app:latest --human --no-trunc
docker images app --format "{{.Repository}}:{{.Tag}} {{.Size}}"
```

### BuildKit Cache Mounts

```dockerfile
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

RUN --mount=type=cache,target=/app/.npm \
    npm ci
```

## Step 5: Health Checks

### Application Health Endpoint

```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
async def health():
    return {"status": "healthy", "version": "1.0.0"}

@app.get("/health/ready")
async def readiness():
    return {"status": "ready", "checks": {"database": "connected"}}
```

### Container Health Check Config

| Parameter | Default | Recommended |
|-----------|---------|-------------|
| interval | 30s | 30s |
| timeout | 30s | 5-10s |
| start-period | 0s | 10-30s |
| retries | 3 | 3 |

## Step 6: Security Scanning

### Hadolint (Dockerfile Linting)

```bash
hadolint Dockerfile
```

### Docker Scout (Vulnerability Scanning)

```bash
docker scout cves app:latest
docker scout recommendations app:latest
```

### Trivy

```bash
trivy image app:latest
trivy image --severity HIGH,CRITICAL app:latest
```

### Common Hadolint Fixes

| Rule | Issue | Fix |
|------|-------|-----|
| DL3008 | Pin apt versions | `RUN apt-get install -y --no-install-recommends package=1.0.*` |
| DL3013 | Pin pip versions | `RUN pip install --no-cache-dir package==1.0.0` |
| DL3016 | Pin npm versions | `RUN npm ci` (uses lockfile) |
| DL3007 | Use latest tag | Pin specific version: `FROM node:20.11-alpine` |
| DL4006 | Pipe fail | `SHELL ["/bin/bash", "-o", "pipefail", "-c"]` |
| DL3059 | Multiple consecutive RUN | Combine into single RUN with `&&` |

## Step 7: Graceful Shutdown

```javascript
const server = app.listen(PORT)

function gracefulShutdown(signal) {
  console.log(`Received ${signal}, shutting down gracefully...`)
  server.close(() => {
    console.log('HTTP server closed')
    process.exit(0)
  })
  setTimeout(() => {
    console.error('Forced shutdown after timeout')
    process.exit(1)
  }, 10000)
}

process.on('SIGTERM', () => gracefulShutdown('SIGTERM'))
process.on('SIGINT', () => gracefulShutdown('SIGINT'))
```

```yaml
compose:
  stop_grace_period: 10s
```

---

## Deployment Rollback Strategy

### `no-rollback-on-deploy`

A deployment that overwrites the running image and then runs a smoke test has no way back when the smoke test fails — production is already on the broken image. Capture the previous image URI BEFORE the update, then add an explicit rollback step that restores it on smoke-test failure. This is especially critical with dual deployment targets (e.g. EC2 service + Lambda function) where one target may update successfully and the other fail, leaving the system in a split-brain state where rollback is the only safe action.

```bash
# VULNERABLE — overwrite in place, no previous image captured, no rollback
aws ecs update-service --cluster prod --service api \
  --task-definition api:42         # previous task def api:41 is now orphaned
./smoke_test.sh                    # FAILS — prod is now on api:42 with no way back

# SECURE — capture previous, rollback on smoke test failure
set -euo pipefail
PREV_TASK_DEF=$(aws ecs describe-services --cluster prod --services api \
  --query 'services[0].taskDefinition' --output text)
aws ecs update-service --cluster prod --service api \
  --task-definition api:42
aws ecs wait services-stable --cluster prod --service api

if ! ./smoke_test.sh; then
  echo "Smoke test failed — rolling back to ${PREV_TASK_DEF}" >&2
  aws ecs update-service --cluster prod --service api \
    --task-definition "${PREV_TASK_DEF}"
  aws ecs wait services-stable --cluster prod --service api
  exit 1
fi
```

```yaml
# CI/CD step (GitHub Actions) — capture + rollback for dual EC2 + Lambda targets
- name: Deploy
  env:
    PREV_ECS: ${{ steps.prev.outputs.task_def }}
    PREV_LAMBDA: ${{ steps.prev.outputs.lambda_arn }}
  run: |
    ./deploy_ecs.sh "${{ steps.build.outputs.image }}"
    ./deploy_lambda.sh "${{ steps.build.outputs.image }}"
    if ! ./smoke_test.sh; then
      ./rollback_ecs.sh "${PREV_ECS}"
      ./rollback_lambda.sh "${PREV_LAMBDA}"
      exit 1
    fi
```

**Detection:**

```bash
rg 'update-service|deploy|aws lambda update-function-code' .github/workflows/ -A 5 | rg -v 'rollback|prev|previous'
```

**Rule:** Every deployment MUST (1) capture the previous image/task-def/ARN before updating, and (2) include an explicit rollback step that restores it on smoke-test failure. Dual-target deployments (EC2 + Lambda) must rollback BOTH targets atomically on any failure.

---

## Build ARG Centralization

### `hardcoded-sed-version-swap`

SDK or library versions hardcoded as `sed` substitutions across Dockerfiles, CI workflows, and shell scripts are a DRY violation that drifts within a single repo. Bump the version once and three files still ship the old value because nobody grepped for every occurrence. Use a single `ARG` (Dockerfile) or a single variable sourced by all build steps (CI workflow matrix) so there is exactly one place to bump the version.

```dockerfile
# WRONG — version appears in 3+ places via sed, drifts on bump
RUN sed -i 's/VERSION=1.2.3/VERSION=1.3.0/g' config.toml
# .github/workflows/release.yml
#   run: sed -i 's/sdk-version=1.2.3/sdk-version=1.3.0/' package.json
# scripts/install.sh
#   sed -i 's/SERVICE_VERSION=1.2.3/SERVICE_VERSION=1.3.0/' .env

# CORRECT — one ARG, referenced everywhere; bump in a single line
ARG SERVICE_VERSION=1.3.0
ENV SERVICE_VERSION=${SERVICE_VERSION}
RUN echo "{\"version\": \"${SERVICE_VERSION}\"}" > /app/version.json
```

```yaml
# .github/workflows/release.yml — single variable, consumed by all steps
env:
  SERVICE_VERSION: 1.3.0
jobs:
  build:
    steps:
      - run: docker build --build-arg SERVICE_VERSION=${{ env.SERVICE_VERSION }} .
      - run: ./scripts/install.sh "${{ env.SERVICE_VERSION }}"
```

**Detection:**

```bash
rg "sed.*version|sed.*VERSION" Dockerfile* .github/ scripts/ -n
```

**Rule:** Pin SDK/library versions in exactly one place — a Dockerfile `ARG`, a CI workflow-level `env`, or a single `.env` — and have every build step consume that single source. Never `sed` the same version string into multiple files.

Attribution

darellchua2darellchua2
View sourceMore from darellchua2 →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

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

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Terraform Module Library

Build reusable Terraform modules for AWS, Azure, and GCP infrastructure following infrastructure-as-code best practices. Use when creating infrastructure modules, standardizing cloud provisioning, or implementing reusable IaC components.

393431 votes

sematext-otel

Wire a service's OpenTelemetry output to Sematext Cloud. Walks through region, App-type, instrumentation flow (managed OTLP endpoint vs Sematext Agent), and signal selection (traces/metrics/logs), then produces the exact env-var block and points at a runnable reference example in this repo. Invoke when instrumenting a new app for Sematext.

01 votes

Deployment Patterns

Deployment workflows, CI/CD pipeline patterns, Docker containerization, health checks, rollback strategies, and production readiness checklists for web applications. Use when setting up deployment infrastructure or planning releases.

2459130 votes

Babysit

Watch a pull request or review cycle until it is ready to merge. Use when asked to babysit, monitor, or keep checking PR comments, reviews, and CI until all actionable issues are resolved.

942310 votes

V7 Roster

Interact with the Paperclip control plane API for task coordination and governance. Use when checking assignments, updating issue status, posting comments, delegating work, managing routines, or calling Paperclip API endpoints.

805540 votes
View all in devops →