---
applyTo: "**/Dockerfile*,**/*.dockerfile,**/compose*.yaml,**/docker-compose*.yml"
description: Container build conventions
---

# Dockerfiles and Compose

- Multi-stage: `build` stage installs dev deps and compiles; final stage copies only artifacts onto a slim/distroless base.
- Pin base images to an exact version (`python:3.13.8-slim`), optionally by digest. Never `latest`.
- Cache-friendly order: copy lockfile -> install -> copy source. Use `RUN --mount=type=cache,target=...` for package managers.
- Combine `apt-get update && apt-get install -y --no-install-recommends ... && rm -rf /var/lib/apt/lists/*` in one layer.
- Create and switch to a non-root `USER`; don't `chmod 777`.
- Exec-form `ENTRYPOINT`/`CMD` (`["./server"]`) so signals reach the process.
- Secrets via `--mount=type=secret`, never `ARG`/`ENV`/`COPY`.
- Keep `.dockerignore` current (`.git`, `node_modules`, `.env*`, build output).
- `HEALTHCHECK` in the image or `healthcheck:` in compose.
- Compose: `compose.yaml` without a `version:` key, `depends_on` with `condition: service_healthy`, named volumes for data.

## Check
`hadolint Dockerfile` and `docker build .` succeed; mention the final image size.
