Safeguard
Developer Tools•

How should you run apt-get in a Dockerfile?

Run apt-get update and install in one RUN step, skip recommended extras, and clear package lists. Here is why each choice matters for size and security.

Safeguard Security Team
4 min read

Run apt-get update and apt-get install in the same RUN instruction, install only the packages you name, and remove the package lists in that same step. This keeps the layer small, avoids stale package indexes from the build cache, and leaves fewer tools in the image for an attacker to use.

The one rule Docker spells out

Docker's best practices page says to always combine the update command with the install command in the same RUN statement. The reason is the build cache. If update sits in its own layer, Docker may reuse that cached layer weeks later, and the next install step then works from an old package index. You get older versions than you expect, sometimes with known flaws.

FROM debian:bookworm-slim
RUN apt-get update \
 && apt-get install -y curl ca-certificates \
 && rm -rf /var/lib/apt/lists/*

Why remove the package lists

The same page notes that removing the apt lists directory reduces image size, because the cache is not stored in a layer. It also says the official Debian and Ubuntu images already run a clean step, so the explicit removal matters less there. Keep it anyway if you build on other bases. It costs one line and makes the intent obvious to reviewers.

The cleanup must happen in the same RUN step as the install. If you delete the lists in a later instruction, the files still exist in the earlier layer and the image does not shrink.

Skip the recommended extras

Apt installs recommended packages by default. The no-install-recommends option tells it to install only what you asked for and the hard dependencies. Docker's own examples use it. Fewer packages means less to patch and fewer binaries a scanner will flag. Test your image after adding it, because some programs quietly relied on a recommended package.

Should you pin package versions?

Docker describes version pinning as a way to bust the cache and force a specific version. The tradeoff is upkeep. A pinned version that leaves the archive makes the build fail, and a pin you never update freezes known flaws in place. Many teams pin the base image and rebuild often instead of pinning each apt package. Pick one approach and write down who updates it.

ChoiceBenefitCost
Combine update and installNo stale indexNone
Remove apt lists in same stepSmaller layerOne extra line
Skip recommended packagesFewer packages to patchOccasional missing library
Pin each package versionRepeatable buildsFrequent pin updates

Check the result

After the build, list what you shipped. A scan of the built image shows the operating system packages and their known flaws, and a rebuild with a fresh base shows how many disappear. See scanning a local image before you push it and rebuilding images regularly.

Try it yourself

Click through it at your own pace, or open it full screen.

Quick check

Does cleaning apt lists in a later RUN shrink the image?

No. Layers are additive, so the files remain in the earlier layer. Clean up in the same RUN step that created them.

Is apt-get update on its own line a security problem?

It can be. A cached update layer leaves later installs using an old index, so you may ship older packages than you intended.

Safeguard

Safeguard does SBOM and dependency scanning, and its policies and gates can run in CI so a bad image does not reach production. You can try a free scan before deciding anything.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.