Skill: kklouzal/docker-encyclopedia (version 1.0.0)

--- name: docker-encyclopedia description: >- Docker documentation-first workflow for Docker-specific questions, troubleshooting, command planning, image/build work, container/runtime operations, Compose behavior, networking, volumes, registries, and diagnostics. Use when the request is clearly about Docker itself: the `docker` CLI, Docker Engine, Dockerfiles, BuildKit/buildx, Docker Compose, images, containers, registries, volumes, networks, contexts, rootless Docker, or Docker Desktop/Engine behavior where Docker-specific semantics matter. Do not use for generic Linux administration, generic OCI/container theory, generic shell work, or Kubernetes/orchestration questions unless the Docker layer is specifically what is being discussed or debugged. metadata: {"openclaw":{"emoji":"🐳","homepage":"https://docs.docker.com/"}} --- # Docker Encyclopedia ## Overview Use a docs-first workflow for Docker work. Prefer the official Docker documentation at `https://docs.docker.com/`, consult cached local copies under `.Docker-Encyclopedia/` before re-fetching, and record useful official-doc excerpts plus environment-specific operational learnings so future work gets faster and safer. This skill is for the **Docker product/runtime layer**. It should trigger for real Docker behavior, configuration, build/runtime, and operational questions — not for generic Linux admin work, generic container theory, or generic orchestration talk where Docker-specific semantics are not the real issue. ## Workflow 1. **Classify the task** - Decide whether the task is a Docker question, troubleshooting task, command-planning task, image/build task, Compose review, runtime review, or live operational task. - Use this skill when the request is specifically about Docker product behavior, Docker CLI semantics, Docker build/runtime behavior, Docker Compose behavior, image/container lifecycle, or Docker-specific networking/storage/registry details. - Do not use this skill for generic shell work, generic Linux admin, generic OCI/container theory, or Kubernetes questions unless the Docker layer is specifically in play. 2. **Check local cache first** - Use `.Docker-Encyclopedia/` as the local knowledge/cache root. - Check these locations first when relevant: - `.Docker-Encyclopedia/docs/docs.docker.com/...` - `.Docker-Encyclopedia/notes/components/...` - `.Docker-Encyclopedia/notes/patterns/...` - `.Docker-Encyclopedia/inventory/...` - If a cached page or note already answers the question well enough, use it. 3. **Consult official Docker docs before answering or touching the system** - Before answering direct or indirect Docker questions that depend on command syntax, feature boundaries, configuration semantics, builder/runtime behavior, storage/network semantics, or version-sensitive details, consult the official docs unless the answer is already well-supported by the local cache. - Before performing direct Docker CLI or configuration work, consult the relevant docs first when: - the exact command path matters - build/runtime semantics are easy to misremember - the action could affect running containers, images, volumes, networks, registries, credentials, or host reachability - Do not improvise high-impact Docker commands or config changes from memory when the docs are easy to check. 4. **Cache consulted docs locally** - When you consult a Docker docs page, save a normalized markdown/text cache copy under `.Docker-Encyclopedia/docs/docs.docker.com/...`. - Mirror the official docs path structure as much as practical. - Cache only pages actually consulted; do not try to mirror the whole docs site eagerly. - Use `scripts/cache_doc.py` when appropriate. 5. **Separate official documentation from local observations** - Store official-doc-derived material under `.Docker-Encyclopedia/docs/...`. - Store environment-specific operational knowledge under: - `.Docker-Encyclopedia/notes/components/` - `.Docker-Encyclopedia/notes/patterns/` - `.Docker-Encyclopedia/inventory/` - Distinguish clearly between: - official documented behavior - observed local configuration/state - inferred best-practice guidance 6. **Record useful local learnings** - After useful live work, save durable notes such as: - host-specific Docker layout and runtime conventions - recurring build/runtime/debugging patterns - image/registry/credential-helper gotchas - Compose/deployment conventions - safe/unsafe operational boundaries for the environment - Prefer concise durable notes over re-learning the same Docker details later. ## Live Work Rules - Treat official Docker docs lookup as the default preflight for non-trivial Docker work. - Prefer read/inspect first when entering a Docker area you have not recently reviewed. - Treat image pruning, volume/network changes, Compose deployments, builder/registry config, daemon config, and credential-handling paths as high-sensitivity areas. - When uncertainty remains after checking cache + docs, say so and avoid bluffing. - When answering a question, mention when useful whether the answer comes from cached official docs, a fresh official docs lookup, or live observed environment state. ## Data Root Use this workspace-local root for cache and notes: - `.Docker-Encyclopedia/` Expected structure: - `.Docker-Encyclopedia/docs/docs.docker.com/...` - `.Docker-Encyclopedia/notes/components/...` - `.Docker-Encyclopedia/notes/patterns/...` - `.Docker-Encyclopedia/inventory/...` Use `scripts/init_workspace.py` to create or repair the expected directory structure. ## Note Destinations - Component-specific observations → `.Docker-Encyclopedia/notes/components/<component-name>.md` - Reusable Docker patterns/gotchas → `.Docker-Encyclopedia/notes/patterns/<topic>.md` - Environment-wide deployment/access info → `.Docker-Encyclopedia/inventory/*.md` - Cached official docs → `.Docker-Encyclopedia/docs/docs.docker.com/...` ## Secrets / Sensitive Data - Do not store plaintext credentials, API keys, session tokens, private URLs, recovery codes, or other secrets in the encyclopedia notes/inventory tree. - If a note needs to mention access details, keep it high-level and redact or omit secret material. - Treat these workspace notes as operational memory, not as a secrets vault. ## Resources - `scripts/init_workspace.py` — create or repair the `.Docker-Encyclopedia/` directory tree. - `scripts/cache_doc.py` — fetch and cache a consulted official Docker docs page under `.Docker-Encyclopedia/docs/...`. - `references/workflow.md` — detailed operating workflow and evidence-handling rules. - `references/cache-layout.md` — canonical `.Docker-Encyclopedia/` directory structure. - `references/topic-map.md` — useful Docker topic groupings for faster doc lookup. ## Good Outcomes - Answer a Docker question using cached or freshly checked official docs instead of guesswork. - Inspect a live Docker environment after checking the relevant docs and record any new local operational knowledge. - Build a growing local Docker knowledge cache that makes later work faster, safer, and more grounded. - Turn one-off Docker discoveries into durable notes so future work does not rediscover them from scratch. ## Avoid - Answering Docker-specific questions purely from memory when docs are easy to consult. - Treating local observed behavior as if it were guaranteed official documented behavior. - Dumping large amounts of low-value docs into the workspace without a reason. - Writing component-specific observations into the official-doc cache tree. - Making high-impact live changes before checking the relevant docs when exact behavior matters.

path: references/cache-layout.md
content: # `.Docker-Encyclopedia/` Cache Layout

Use this directory as the workspace-local data root for the skill.

## Directory tree

```text
.Docker-Encyclopedia/
  docs/
    docs.docker.com/
      ... cached official docs pages ...
  notes/
    components/
      ... per-component notes ...
    patterns/
      ... reusable Docker notes ...
  inventory/
    access.md
    topology.md
    doc-index.md
```

## Placement rules

### `docs/`
Store cached copies of official Docker docs here.

Mirror the official docs path as much as practical.
Example:

```text
https://docs.docker.com/engine/reference/commandline/run/
->
.Docker-Encyclopedia/docs/docs.docker.com/engine/reference/commandline/run/index.md
```

### `notes/components/`
Store environment-specific component notes here.

Suggested filenames:
- `engine.md`
- `compose.md`
- `registry.md`
- `buildkit.md`
- `networking.md`

### `notes/patterns/`
Store reusable operational notes here.

Examples:
- `compose-deployments.md`
- `image-build-cache-gotchas.md`
- `volume-backup-restore.md`
- `rootless-docker-notes.md`

### `inventory/`
Store environment-wide inventories here.

Suggested files:
- `access.md`
- `topology.md`
- `doc-index.md`

## Cache philosophy

Do not mirror the whole docs site eagerly.
Cache only the pages you actually consulted and expect to be useful later.


path: references/topic-map.md
content: # Docker Topic Map

Use this as a quick orientation aid when deciding what docs to look up.

## Core areas

- Docker Engine / daemon / runtime behavior
- CLI commands and operational workflows
- Dockerfiles / image builds / BuildKit / buildx
- Containers / images / layers / lifecycle
- Volumes / bind mounts / storage behavior
- Networks / ports / name resolution
- Compose / multi-container application definitions
- Registries / authentication / image distribution
- Rootless Docker / contexts / remote engines

## Typical lookup prompts

When the task is about...

### Engine / CLI
Look for docs covering:
- docker CLI commands
- daemon behavior
- contexts
- rootless mode
- engine configuration

### Builds / Dockerfiles
Look for docs covering:
- Dockerfile reference
- build context semantics
- BuildKit/buildx
- caching behavior
- multi-stage builds

### Compose
Look for docs covering:
- compose file reference
- service/network/volume semantics
- environment/config handling
- lifecycle commands

### Storage / networking
Look for docs covering:
- volumes
- bind mounts
- overlay/network drivers
- publishing ports
- DNS/name resolution

### Registries / auth
Look for docs covering:
- registries
- image push/pull
- auth/login
- credential stores/helpers

### Security / operations
Look for docs covering:
- rootless mode
- daemon socket exposure
- capabilities/seccomp when relevant
- cleanup/pruning behavior


path: references/workflow.md
content: # Docker Encyclopedia Workflow

## Core stance

Use official Docker docs plus local observed state together.

Default order:
1. check `.Docker-Encyclopedia/` cache/notes
2. check official docs when needed
3. inspect live environment state
4. answer or act
5. record durable learnings

## When docs lookup is mandatory

Do a docs lookup before answering or acting when any of these are true:
- the user asks about Docker command syntax, feature semantics, or configuration behavior
- the task involves Dockerfiles, BuildKit/buildx, Compose, registries, networks, volumes, daemon/rootless config, or credential handling
- the task involves a version-sensitive feature or a behavior you are not highly confident about
- the task involves live CLI/config work and the command path or safety boundaries matter

## Cache-first rule

Before fetching docs, check whether the needed material already exists under:
- `.Docker-Encyclopedia/docs/docs.docker.com/...`
- `.Docker-Encyclopedia/notes/components/...`
- `.Docker-Encyclopedia/notes/patterns/...`
- `.Docker-Encyclopedia/inventory/...`

If the local cache is good enough, use it.
If not, fetch/check the official docs and then cache what you used.

## How to cache docs

Use `scripts/cache_doc.py`.

Typical usage:

```bash
python3 scripts/cache_doc.py \
  --url 'https://docs.docker.com/engine/reference/commandline/run/' \
  --root '<workspace>/.Docker-Encyclopedia'
```

The script will:
- fetch the page
- convert it into a normalized markdown-ish cache file
- place it under `.Docker-Encyclopedia/docs/docs.docker.com/...`
- add metadata such as source URL and fetch timestamp

## How to store local knowledge

### Component notes

Use `.Docker-Encyclopedia/notes/components/<component-name>.md` for:
- component purpose
- access path
- role in deployment
- sensitive boundaries
- discovered quirks

### Pattern notes

Use `.Docker-Encyclopedia/notes/patterns/<topic>.md` for:
- recurring build/runtime patterns
- repeated gotchas
- safe operational sequences
- environment-specific design conventions

### Inventory files

Use `.Docker-Encyclopedia/inventory/` for:
- deployment/access inventory
- topology/runtime layout
- documentation index

## Distinguish evidence types

When writing notes, label information mentally as one of:
- **Official docs** — from Docker documentation
- **Observed local state** — from live environment inspection
- **Inference/recommendation** — your judgment based on docs + local state

Do not blur these together.

## Recommended answer style

When it helps, mention whether your answer is based on:
- cached official docs
- freshly checked official docs
- live environment inspection
- best-practice inference

## High-sensitivity areas

Treat these as high-sensitivity even when you have live access:
- daemon config and auth/credential changes
- image/volume/network pruning or destructive cleanup
- Compose deployment changes
- registry/login/push behavior
- rootless/socket/permission changes
- changes that could break running containers, storage, or host reachability

For these, prefer docs lookup even if you think you remember the command or config path.


path: scripts/cache_doc.py
content: #!/usr/bin/env python3
from __future__ import annotations

import argparse
import html
import ipaddress
import re
import urllib.parse
import urllib.request
from datetime import datetime, timezone
from html.parser import HTMLParser
from pathlib import Path, PurePosixPath

ALLOWED_NETLOCS = {'docs.docker.com'}
ALLOWED_SCHEMES = {'https'}
OUTPUT_NETLOC = 'docs.docker.com'
USER_AGENT = 'Docker-Encyclopedia/1.1'
TITLE_FALLBACK = 'Docker Doc'
PATH_HELP = 'docs.docker.com URL to cache'
ROOT_HELP = 'Docker Encyclopedia data root (default: <cwd>/.Docker-Encyclopedia)'
DESCRIPTION = 'Fetch and cache a Docker docs page into .Docker-Encyclopedia.'
PATH_PREFIX = None
BLOCK_QUERY = True


class TextExtractor(HTMLParser):
    def __init__(self) -> None:
        super().__init__()
        self.in_script = False
        self.in_style = False
        self.title = ''
        self._in_title = False
        self.parts: list[str] = []

    def handle_starttag(self, tag: str, attrs):
        tag = tag.lower()
        if tag == 'script':
            self.in_script = True
        elif tag == 'style':
            self.in_style = True
        elif tag == 'title':
            self._in_title = True
        elif tag in {'li', 'br', 'h4', 'h3', 'div', 'h2', 'article', 'tr', 'p', 'section', 'h1', 'h6', 'h5'}:
            self.parts.append('\n')

    def handle_endtag(self, tag: str):
        tag = tag.lower()
        if tag == 'script':
            self.in_script = False
        elif tag == 'style':
            self.in_style = False
        elif tag == 'title':
            self._in_title = False
        elif tag in {'li', 'br', 'h4', 'h3', 'div', 'h2', 'article', 'tr', 'p', 'section', 'h1', 'h6', 'h5'}:
            self.parts.append('\n')

    def handle_data(self, data: str):
        if self.in_script or self.in_style:
            return
        text = html.unescape(data)
        if self._in_title:
            self.title += text
        self.parts.append(text)

    def text(self) -> str:
        text = ''.join(self.parts)
        text = re.sub(r'\r', '', text)
        text = re.sub(r'\n{3,}', '\n\n', text)
        text = re.sub(r'[ \t]+', ' ', text)
        lines = [line.strip() for line in text.splitlines()]
        return '\n'.join(line for line in lines if line).strip()


def default_root() -> Path:
    return Path.cwd() / '.Docker-Encyclopedia'


def normalized_relative_path(parsed: urllib.parse.ParseResult) -> PurePosixPath:
    raw_path = urllib.parse.unquote(parsed.path or '/')
    if '\x00' in raw_path:
        raise ValueError('NUL bytes are not supported in URL paths')
    if PATH_PREFIX and not (raw_path == PATH_PREFIX or raw_path.startswith(PATH_PREFIX + '/')):
        raise ValueError(f'Only {PATH_PREFIX} URLs are supported')
    pure = PurePosixPath(raw_path)
    parts = [part for part in pure.parts if part not in ('/', '')]
    if any(part in {'.', '..'} for part in parts):
        raise ValueError('Dot path segments are not supported')
    rel = PurePosixPath(*parts) if parts else PurePosixPath('index')
    if raw_path.endswith('/'):
        rel = rel / 'index'
    return rel.with_suffix('.md')


def validate_url(url: str) -> urllib.parse.ParseResult:
    parsed = urllib.parse.urlparse(url)
    if parsed.scheme not in ALLOWED_SCHEMES:
        raise ValueError(f'Only {sorted(ALLOWED_SCHEMES)} URLs are supported')
    if parsed.username or parsed.password:
        raise ValueError('Userinfo in URLs is not supported')
    if parsed.hostname is None:
        raise ValueError('URL must include a hostname')
    try:
        ipaddress.ip_address(parsed.hostname)
    except ValueError:
        pass
    else:
        raise ValueError('Direct IP URLs are not supported')
    if parsed.hostname not in ALLOWED_NETLOCS:
        raise ValueError(f'Only {sorted(ALLOWED_NETLOCS)} URLs are supported')
    if parsed.port is not None:
        raise ValueError('Explicit ports are not supported')
    if BLOCK_QUERY and (parsed.params or parsed.query or parsed.fragment):
        raise ValueError('Query strings, params, and fragments are not supported')
    normalized_relative_path(parsed)
    return parsed


def ensure_within(base: Path, candidate: Path) -> Path:
    resolved_base = base.resolve(strict=False)
    resolved_candidate = candidate.resolve(strict=False)
    try:
        resolved_candidate.relative_to(resolved_base)
    except ValueError as exc:
        raise ValueError('Refusing to write outside the cache root') from exc
    return resolved_candidate


def build_output_path(root: Path, parsed: urllib.parse.ParseResult) -> Path:
    rel = normalized_relative_path(parsed)
    base = root / 'docs' / OUTPUT_NETLOC
    out = base.joinpath(*rel.parts)
    return ensure_within(base, out)


def fetch_html(url: str) -> str:
    req = urllib.request.Request(url, headers={'User-Agent': USER_AGENT})
    with urllib.request.urlopen(req, timeout=20) as resp:
        charset = resp.headers.get_content_charset() or 'utf-8'
        return resp.read().decode(charset, errors='replace')


def main() -> int:
    parser = argparse.ArgumentParser(description=DESCRIPTION)
    parser.add_argument('--url', required=True, help=PATH_HELP)
    parser.add_argument('--root', default=str(default_root()), help=ROOT_HELP)
    args = parser.parse_args()

    parsed = validate_url(args.url)
    root = Path(args.root).expanduser().resolve()
    html_body = fetch_html(args.url)
    extractor = TextExtractor()
    extractor.feed(html_body)
    title = extractor.title.strip() or Path(parsed.path).name or TITLE_FALLBACK
    body = extractor.text()
    out = build_output_path(root, parsed)
    out.parent.mkdir(parents=True, exist_ok=True)
    content = (
        f'# {title}\n\n'
        f'- Source: {args.url}\n'
        f'- Cached at: {datetime.now(timezone.utc).isoformat()}\n\n'
        '## Cached text\n\n'
        f'{body}\n'
    )
    out.write_text(content, encoding='utf-8')
    print(out)
    return 0


if __name__ == '__main__':
    raise SystemExit(main())


path: scripts/init_workspace.py
content: #!/usr/bin/env python3
from __future__ import annotations

import argparse
from pathlib import Path

SEED_FILES = {
    'inventory/access.md': '# Docker Access Inventory\n\nStore Docker environment and access notes here.\n',
    'inventory/topology.md': '# Docker Topology\n\nStore environment-specific Docker topology and component-role notes here.\n',
    'inventory/doc-index.md': '# Docker Cached Doc Index\n\nTrack especially useful cached official-doc pages here when helpful.\n',
    'notes/components/.gitkeep': '',
    'notes/patterns/.gitkeep': '',
    'docs/docs.docker.com/.gitkeep': '',
}


def default_root() -> Path:
    return Path.cwd() / '.Docker-Encyclopedia'


def main() -> int:
    parser = argparse.ArgumentParser(description='Create/repair the .Docker-Encyclopedia workspace layout.')
    parser.add_argument('--root', default=str(default_root()), help='Data root to initialize (default: <cwd>/.Docker-Encyclopedia)')
    args = parser.parse_args()

    root = Path(args.root).expanduser().resolve()
    for rel, content in SEED_FILES.items():
        path = root / rel
        path.parent.mkdir(parents=True, exist_ok=True)
        if not path.exists():
            path.write_text(content, encoding='utf-8')
    print(root)
    return 0


if __name__ == '__main__':
    raise SystemExit(main())


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)