소스 정보
- 저장소
- leroyguillaume/claude
- 최근 소스 활동
- 2026년 8월 10일 13:18
- 감지된 SKILL.md 언어
- 영어
- 스타
- 4
- 포크
- 2
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
SOC 직업 분류 기준
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/leroyguillaume/claude --skill docker-conventions명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
| name | docker-conventions |
| description | Dockerfile conventions (minimal CVE-free base images — |
Always:
.dockerignore file to exclude unnecessary files from the build
context (.git/, node_modules/, *.log, README.md, etc.).scratch — statically linked binaries (Rust with musl, Go with
CGO_ENABLED=0). Zero packages, zero CVEs, nothing to patch.gcr.io/distroless/static, .../base, .../cc) — when
you need libc, TLS roots, or /etc/passwd but no shell or package
manager. Prefer the :nonroot variants.alpine — when you genuinely need a shell or a couple of apk packages.*-slim (debian:*-slim, python:*-slim) — when glibc or a distro
runtime is unavoidable.
Full distro images (debian, ubuntu, python:3.13, node:22) are a
builder-stage-only thing; they never appear in the last FROM.scratch have no groupadd/useradd. Two options, both
fine, and both land on the same UID 65532 as the rule below:
:nonroot tag and USER nonroot:nonroot;/etc/passwd and
/etc/group over.
Either way the final stage still ends with an explicit non-root USER.trivy image / grype) and fail the build
on HIGH/CRITICAL. A skinny base is what makes that gate cheap enough to
keep enabled.Dockerfile itself with trivy config, and fix every finding.
These are the DS-xxxx checks (DS-0002 running as root, DS-0026 missing
HEALTHCHECK, DS-0001 :latest tag, DS-0009 relative WORKDIR, …).
Standing rule, same as everywhere else: treat them as errors, fix at the
source, no self-authorised ignores. Run it locally with
trivy config --exit-code 1 Dockerfile; in .pre-commit-config.yaml use a
repo: local, language: system hook (never a Docker-backed one — see
pre-commit-conventions).trivy does not replace hadolint. Run both. They overlap on the
obvious stuff (absolute WORKDIR, cd in RUN, --no-install-recommends),
but each catches things the other is blind to:
hadolint: apk package version pinning (DL3018) — the pinning
rule below has no Trivy equivalent, which by itself settles the
question; apt list cleanup (DL3009); JSON notation for
ENTRYPOINT/CMD (DL3025); and ShellCheck on every RUN line
(SC2086 unquoted expansion, etc.), which Trivy does not do at all.trivy: missing HEALTHCHECK (DS-0026), plus severity levels
and the same report format as image/IaC scanning.--no-install-recommends
for apt, --no-cache for apk, no curl/wget/bash "just for debugging",
and health checks that use the app itself rather than an extra binary.<appname> the project name:
/usr/local/src/<appname> (the builder stage WORKDIR)./usr/local/bin/ (on PATH)./etc/<appname>/./var/lib/<appname>/.chown the app-owned paths,
and end the Dockerfile with a USER directive.
Why 65532 and not 1000: UID/GID must be > 10000 (Trivy KSV-0020 /
KSV-0021). Without user namespaces, a container UID is a host UID, and
1000 is the first human account on virtually every Linux box — so a
container escape, a hostPath mount, or a shared NFS export lands with
that user's identity. 65532 is the specific high UID upstream already
agreed on (distroless:nonroot, Chainguard), which keeps the number
identical whether you inherit the user or create it. Avoid 65534 — that's
nobody/nogroup, shared by every unmapped process and squashed-to by NFS.
Example (app myapp):
# builder stage
WORKDIR /usr/local/src/myapp
# ... build, producing /usr/local/src/myapp/target/release/myapp ...
# runtime stage
RUN groupadd --system --gid 65532 myapp \
&& useradd --system --uid 65532 --gid myapp \
--home /etc/myapp --shell /usr/sbin/nologin myapp
COPY --from=builder --chown=myapp:myapp \
/usr/local/src/myapp/target/release/myapp /usr/local/bin/myapp
USER myapp
ENTRYPOINT ["/usr/local/bin/myapp"]
Dockerfile with hadolint and add the hadolint/hadolint
pre-commit hook.hadolint warning at the source. A green run is the only
acceptable end state.apk package versions (apk add pkg=1.2.3-r4) — this is DL3018, and
the answer is to pin, not to silence. Keeping the pins current is Renovate's
job, not a reason to skip them. Annotate each one so Renovate can see it:
# renovate: datasource=repology depName=alpine_3_24/bash versioning=loose
RUN apk add --no-cache bash=5.3.9-r1
Notes that save an hour of debugging:
depName is <repology-repo>/<package>, and the repo carries the
distro release (alpine_3_24, debian_13). It does not follow a
base-image bump on its own — when the base moves to a new release, the
annotations must move with it or Renovate silently keeps resolving
against the old one.cat /etc/alpine-release) and annotate per stage.apk list <pkg> / apt-cache policy <pkg>), not from Repology's
version field — Repology normalises (5.3.p9), and only its
origversion (5.3.9-r1) is the string apk will accept.LOG_LEVEL=debug npx --package renovate -- renovate --platform=local --dry-run=extract.apt package versions on Debian/Ubuntu — leave DL3008
ignored. This is a deliberate exception to the rule above, not an
oversight, and # hadolint ignore=DL3008 is pre-authorised here (the
"never silence a rule on your own initiative" rule below does not apply to
this one code). Two reasons:
deb.debian.org serves exactly one
version of each package per suite: the current one. The moment a security
update or point release lands, curl=8.14.1-2+deb13u4 stops existing and
every build breaks — including builds of tags that used to work. apk does
not get this exemption for free either, but Alpine users typically pair it
with Renovate; on Debian the deb datasource is far more fiddly, and most
repos have no bot wired up at all. Check before assuming one exists.apt-get install on a rebuild picks up precisely
the patches you want — while a pin freezes the vulnerability until a human
notices. That is backwards for an image you are also scanning with Trivy.
Reproducibility is recovered at the layer where it actually works: pin the
base image by digest and rebuild on a schedule. Not with apt pins.
What still gets pinned, because those pools keep old versions:
third-party apt repos (download.docker.com, PostgreSQL, NodeSource), PyPI,
npm, and GitHub release assets. Hoist third-party apt versions into ARGs at
the top of the Dockerfile so every version knob lives in one place.Never:
Dockerfile without an explicit non-root USER.root in the final image, even "temporarily".docker debug, ephemeral containers,
and a separate -debug tag are for.:latest, :3, :bookworm) in a FROM. Pin
the specific version, and pin by digest where the registry supports it
(image:1.2.3@sha256:…) — Renovate keeps both current. A floating tag means
the image you scanned is not the image you shipped..trivyignore, --severity downgrade)
on your own initiative. Same rule as hadolint ignore: bump the base image,
bump the package, or drop the dependency. If none of those work, say so and
let the user decide.# hadolint ignore=DLxxxx on your own initiative — not
with a justification comment, not "just this once", not because pinning
looks brittle. Add one only when the user has expressly asked for that
specific ignore. If a rule looks genuinely wrong for the situation, say so
and let the user decide; do not pre-empt the decision by silencing it.
The single standing exception is DL3008 (apt version pinning), which is
pre-authorised — see the apt rule above. Everything else, including
DL3018, still needs an explicit ask.