## TL;DR

Pin each apt package to an explicit version, like `apt-get install -y [package]=[version]`, and add `--no-install-recommends`. DL3008 exists because an unpinned `apt-get install` pulls whatever is newest at build time, so two builds of the same Dockerfile can produce different images. Pinning makes the build reproducible and the review pass.

## The error

```text
Dockerfile:7 DL3008 warning: Pin versions in `apt-get install`. Instead of `apt-get install [package]` use `apt-get install [package]=[version]`
```

(The real output shows your actual package name where `[package]` appears above.)

## Fix it

1. Reproduce locally. Run `hadolint Dockerfile`.
   Expected: the DL3008 line with the file name and line number of each unpinned install.
2. Find the version to pin. On a machine running the same distro as your base image, run `apt-cache policy [package]`.
   Expected: an installed/candidate version string such as `1.2.3-4` you can pin to.
3. Pin it in the Dockerfile:
   ```dockerfile
   RUN apt-get update && apt-get install -y --no-install-recommends [package]=[version] \
       && rm -rf /var/lib/apt/lists/*
   ```
   Expected: re-running hadolint reports no DL3008 for that line. (The `\` at line end is the Dockerfile line continuation.)
4. Keep `apt-get update` and the install in the same RUN layer, and clean the lists in the same layer.
   Expected: no stale package index baked into the layer, smaller image, and DL3009 stays quiet too.

## Use this when

- hadolint reports DL3008 in CI and blocks the PR
- A reviewer asks for pinned versions in `apt-get install`
- You need reproducible image builds for audit or security review

## Not for this skill when

- The blocker is a different hadolint rule (DL3006 unpinned image tag, DL3018 for apk) - each rule has its own fix
- The build fails because the pinned version no longer exists in the distro repo - refresh the pin or bump the base image
- You install with apk, yum, or dnf instead of apt - those have their own pinning rules

## Variant phrasings

- hadolint pin versions in apt-get install
- DL3008 how to fix
- apt-get install pin version dockerfile
- hadolint warning unpinned package

## Why it happens

Debian and Ubuntu repos keep moving: an unpinned install resolves to the newest version available at build time. That breaks reproducibility (the same Dockerfile builds different images on different days) and makes security review impossible, because nobody can say which version actually shipped. DL3008 forces the version into the Dockerfile.

## Edge cases

- A wildcard pin like `[package]=1.2.*` satisfies hadolint and still tolerates patch releases
- Pins rot: when the distro removes the old version from the repo the build breaks - refresh pins when you bump the base image
- Pinning every package by hand is tedious on big images; generate the list from a built image and paste the versions in
- DL3008 only covers apt - if you mix in pip or npm installs, pin those in their own manifests too

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_h5zvj9C48_lgGu_7BR3ECQ
