Writing Dockerfiles that build in seconds, not minutes

Most slow Docker builds come down to layer ordering. A few structural habits make rebuilds dramatically faster.

A multi-stage Dockerfile that copies the lockfile before the application code

Docker builds an image as a stack of layers, and it reuses a cached layer only if that step and every step before it is unchanged. Slow builds almost always come from invalidating the cache too early.

Copy dependency manifests first

The single biggest win: install dependencies before copying your source code.

FROM ruby:3.4-slim AS build
WORKDIR /app

# Changes rarely → cached most of the time
COPY Gemfile Gemfile.lock ./
RUN bundle install

# Changes constantly → only this layer and below rebuild
COPY . .
RUN bin/rails assets:precompile

If you COPY . . first, editing a single view file reinstalls every gem.

Use multi-stage builds

Compilers, headers and build tools are needed to build your app, not to run it. Build in one stage and copy only the results into a slim final stage:

FROM ruby:3.4-slim
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /app /app

Smaller images push and pull faster, and ship fewer packages that could carry vulnerabilities.

Keep the build context small

Everything in the build directory is sent to the builder. A .dockerignore that excludes .git, node_modules, logs and local databases can shave seconds off every build.

.git
log/*
tmp/*
node_modules
storage/*

Cache mounts for package managers

BuildKit can persist package-manager caches across builds without baking them into the image:

RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt

In CI

CI runners usually start with an empty cache. Export and import the build cache (to a registry or the CI cache store) so pipelines get the same speed-up your laptop does.

None of this is exotic. Order layers from least to most frequently changed, ship only what you run, and the build cache does the rest.

Written by

— Senior Editor

Covers infrastructure, deployment and the business of developer tools. Previously a platform engineer.

Weekly digest

Releases, deep dives and the stories developers are talking about. No spam, unsubscribe any time.