# Pathrule Pattern: Docker & Containers (1.0.0)
# ::pathrule:package:docker-containers

### [RULE] Use multi-stage builds with a minimal non-root runtime  (path: /)
<!-- scope: file_type | priority: high | strict -->

Split build and runtime into separate stages so build tools never reach the final image.

- Build in a full stage (for example `node:22` or `golang:1.24`), then `COPY --from=build` only the artifacts into a minimal final stage like `-slim`, `alpine`, or a `distroless` `:nonroot` image.
- Create and switch to a non-root user with an explicit UID and add a `USER` directive before `CMD`; copy artifacts with `COPY --chown` so they are owned correctly.
- Pin base images by major version or digest; never ship `latest` to production.

---

### [RULE] Keep build context small and cache-ordered  (path: /)
<!-- scope: file_type | priority: high | advisory -->

Order Dockerfile instructions so rarely changing layers come first and the build context stays tiny.

- Commit a `.dockerignore` that excludes `node_modules`, `.git`, build output, secrets, and local env files so they are never sent to the builder.
- Copy the dependency manifest (`package.json`, `go.mod`, `requirements.txt`) and install before `COPY . .`, so a code change does not invalidate the dependency layer.
- Use BuildKit cache mounts for package managers, for example `RUN --mount=type=cache,target=/root/.npm npm ci`, with `sharing=locked` for apt.

---

### [MEMORY] Healthchecks must use exec form and match the runtime  (path: /)

Add a `HEALTHCHECK` so the orchestrator knows when the container is ready, but match it to the runtime you shipped.

- Use the JSON exec form, for example `HEALTHCHECK CMD ["node", "healthcheck.js"]`; the shell form fails on `distroless` images that have no shell.
- `curl` and `wget` are absent from `distroless` and minimal images, so ship a tiny in-language probe instead of shelling out.
- Tune `--interval`, `--timeout`, `--start-period`, and `--retries` to the service: fast checks for latency-critical APIs, slower checks for background workers.

---

### [MEMORY] BuildKit and CI cache strategy for fast rebuilds  (path: /deploy)

BuildKit is the default builder; layer order plus cache mounts plus a remote cache backend is what cuts CI times by 70 to 85 percent.

- Layer cache is all-or-nothing per instruction; cache mounts (`--mount=type=cache`) persist a package store across builds so only new deps download when a manifest changes.
- In CI, push and pull a registry cache with `--cache-to type=registry` and `--cache-from` so ephemeral runners reuse prior layers.
- The dependency-first layout and a tight `.dockerignore` are the two highest-leverage changes; add multi-stage and cache backends on top.

---

### [SKILL] docker-containers-review  (path: /)

---
name: docker-containers-review
description: Review checklist for production Dockerfiles covering multi-stage builds, non-root runtime, layer caching, .dockerignore, and healthchecks. Run before merging any Dockerfile change.
---

# Docker & Containers review

- [ ] Dockerfile uses multi-stage builds; the final stage contains only runtime artifacts, no build tools or dev dependencies.
- [ ] Base images are pinned by major version or digest, not `latest`.
- [ ] A non-root user is created with an explicit UID and a `USER` directive precedes `CMD`/`ENTRYPOINT`.
- [ ] Artifacts are copied with `COPY --chown` so the non-root user owns them.
- [ ] Dependency manifests are copied and installed before `COPY . .` to preserve the dependency cache layer.
- [ ] A `.dockerignore` excludes `node_modules`, `.git`, build output, secrets, and local env files.
- [ ] BuildKit cache mounts are used for package managers (with `sharing=locked` for apt).
- [ ] A `HEALTHCHECK` is defined in JSON exec form and uses a probe the final image can actually run.
- [ ] No secrets are baked into layers via `ARG`/`ENV`; build secrets use `--mount=type=secret`.
- [ ] CI build pushes/pulls a registry cache (`--cache-to` / `--cache-from`) for fast rebuilds.
