Multiple RUN vs. single chained RUN in Dockerfile, which is better?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
There is no universal winner between many RUN instructions and one long chained RUN in a Dockerfile. The right choice depends on what you are optimizing for: cache reuse, image cleanliness, readability, or package-manager behavior. The useful rule is to group commands that belong to one atomic step and separate commands that change independently.
Each RUN Creates a Layer
A RUN instruction creates a new filesystem layer. That matters because Docker caching works instruction by instruction.
Separate RUN example:
Chained RUN example:
Both are valid. The difference is how caching and cleanup behave.
Chain Package Install and Cleanup Together
Package-manager workflows are the clearest case where a chained RUN is usually better.
If apt-get update happens in one layer and cleanup happens in another, the cleanup does not shrink the earlier layer that already stored the package metadata. That is why update, install, and cleanup usually belong in the same RUN.
Split Unrelated Steps When It Improves Clarity or Cache Reuse
Not every instruction should be forced into one giant shell chain. If steps are logically separate and likely to change independently, separate RUN instructions can be easier to maintain.
This separation makes the file easier to review and lets Docker reuse cached results for unaffected instructions.
The broader rule is simple: separate by change frequency and conceptual responsibility, not by superstition about layer count.
BuildKit Changed the Old “Fewer Layers Always Wins” Advice
Older Docker advice focused heavily on minimizing layer count. Modern BuildKit makes the conversation more nuanced, because cache mounts and smarter build behavior often matter more than raw layer count.
This is readable, efficient, and not built around the outdated idea that every separate RUN is automatically bad.
Instruction Order Usually Matters More Than Style Arguments
The biggest cache win often comes from ordering instructions by change frequency, not from arguing about one RUN versus many.
Here the important optimization is that dependency installation is isolated from source-code changes. That cache behavior usually matters more than whether a few unrelated commands were chained together.
Readability Still Matters
A 200-character shell chain with multiple &&, cleanup commands, and conditional logic can become harder to maintain than a few well-separated steps. If the line becomes difficult to audit, the theoretical layer benefit is often not worth it.
Good Dockerfiles optimize for both machine behavior and human understanding. A build file is part of the codebase, not only a compression exercise.
Use Multi-Stage Builds for Bigger Wins
If size and security matter, multi-stage builds usually matter more than micro-optimizing RUN style.
This often produces a much larger practical improvement than debating whether one build stage should have three RUN lines or one chained line.
Common Pitfalls
- Splitting package update, install, and cleanup across separate layers.
- Chaining unrelated commands into unreadable one-liners.
- Optimizing for layer count while ignoring instruction order and cache behavior.
- Treating old Docker folklore as a substitute for measuring real build and image outcomes.
- Focusing on
RUNstyle while missing larger gains from multi-stage builds.
Summary
- There is no universal rule that one chained
RUNis always better than multipleRUNlines. - Chain tightly related package-manager steps, especially when cleanup belongs with install.
- Split unrelated steps when it improves readability or cache reuse.
- Modern BuildKit reduces the value of simplistic “minimize layer count” advice.
- Measure actual build time and image size instead of following Dockerfile dogma.

