How I Cut Docker Image Build Time from 16 Minutes to 1 Minute – 10× Faster Builds
This article walks through a step‑by‑step analysis of a slow Docker image build for a Python app, identifies the costly layers, and applies multi‑stage builds, cache‑busting techniques, and Dockerfile best‑practice rules to shrink the build time from about 16 minutes to one minute and reduce the image size by roughly half.
Overview
The author describes a Python application whose Docker image originally required about 16 minutes to build and produced an ~8 GB image. By analysing the Dockerfile and applying a series of optimisations, the build time was reduced to roughly 1 minute and the image size to ~5 GB, achieving about a ten‑fold efficiency gain.
Initial Build Situation
The original Dockerfile (excerpt) and results are shown below:
FROM reg.docker.alibaba-inc.com/aci-images/python-service:3.8.0-63928922
# init folder
RUN mkdir -p /home/admin/logs && mkdir -p /home/admin/bin && mkdir -p /home/admin/conf && mkdir -p /home/admin/nginx && mkdir -p /home/admin/.maxhub/env_helper_util/zeta-local-env
# install zeta
RUN pushd /home/admin/.maxhub/env_helper_util/zeta-local-env && \
wget https://artifacts.antgroup-inc.cn/artifact/repositories/softwares-common/antcode/zeta/0.7.9/zeta-linux-amd64-0.7.9.sh -O zeta-release.sh && \
chmod +x zeta-release.sh && \
./zeta-release.sh --prefix=/usr/local && \
popd
COPY --chown=admin:admin aml_core /home/admin/release/aml_core
COPY --chown=admin:admin backend /home/admin/release/backend
COPY --chown=admin:admin requirements.txt /home/admin/release/
RUN python3.10 -m venv /home/admin/run && \
. /home/admin/run/bin/activate && \
python3.10 -m pip install -i https://pypi.antfin-inc.com/simple-remote --upgrade pip && \
python3.10 -m pip install -i https://pypi.antfin-inc.com/simple -r /home/admin/release/requirements.txtBuild time: ~16 minutes; Image size: ~8 GB.
Post‑Optimization Build
The optimised Dockerfile adopts a multi‑stage approach, moves rarely‑changed layers to the top, adds --no-cache-dir to pip install, removes unnecessary RUN chown commands, merges several RUN statements, and copies only the required artefacts from the builder stage.
# Stage 1: download dependencies
FROM reg.docker.alibaba-inc.com/antfin-sqa/amlregservermodel-dev:20241016125401_b0296dab as builder
COPY --chown=admin:admin requirements.txt /home/admin/release/
RUN python3.10 -m venv /home/admin/run && \
. /home/admin/run/bin/activate && \
python3.10 -m pip install -i https://pypi.antfin-inc.com/simple-remote --upgrade pip && \
python3.10 -m pip install -i https://pypi.antfin-inc.com/simple -r /home/admin/release/requirements.txt --no-cache-dir
# Stage 2: final image
FROM reg.docker.alibaba-inc.com/aci-images/python-service:3.8.0-63928922
RUN mkdir -p /home/admin/logs /home/admin/bin /home/admin/conf /home/admin/nginx /home/admin/.maxhub/env_helper_util/zeta-local-env
COPY --chown=admin:admin conf/docker/build.yaml /root/
COPY --chown=admin:admin conf/docker/scripts/admin /home/admin
COPY --chown=admin:admin conf/nginx /home/admin/nginx
COPY --chown=admin:admin aml_core /home/admin/release/aml_core
COPY --chown=admin:admin backend /home/admin/release/backend
RUN chmod a+xw /home/admin/bin/fetch_ollama.sh /tmpResult after optimisation: build time ~1 minute, image size ~5 GB.
Analysis Process
The longest‑running step was the
COPY --chown=admin:admin conf/docker/scripts/admin /home/admininstruction, whose preceding step (downloading dependencies) consumed about 10 minutes. The base image itself was large (2.33 GB) and the pip cache added roughly 3.1 GB (2.6 GB dependencies + 729 MB cache). docker history was used to pinpoint the heavy layers.
Cache Invalidation Rules
Docker checks each instruction against cached layers; any change invalidates that layer and all subsequent layers.
ADD and COPY compute a checksum of file metadata; changes in file content invalidate the cache.
RUN instructions are cached based solely on the command string, not on the state of the container.
To force cache busting, you can modify a build‑arg, use docker builder prune, or build with --no-cache / --no-cache-filter.
Optimization Steps
Apply the static‑dynamic separation principle: place rarely‑changed commands (base image, dependency installation) early to maximise cache reuse.
Use multi‑stage builds to keep only the final artefacts in the runtime image.
Add --no-cache-dir to pip install to avoid large pip caches.
Remove or consolidate RUN chown commands, as each creates a new layer.
Merge consecutive RUN commands to reduce the total number of layers.
Select a smaller base image when possible (e.g., Alpine or a minimal Alibaba image).
Final Summary
Through systematic analysis and the above optimisations, the Docker image build time dropped from 16 minutes to about 1 minute and the image size was halved. The article also provides a checklist of Dockerfile best‑practice rules (limit to 20 instructions, avoid more than three consecutive RUN commands, place CMD/ENTRYPOINT after COPY/RUN, etc.) and a collection of additional tips such as using a .dockerignore file, running a single application per container, avoiding the latest tag, and adding health checks.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
dbaplus Community
Enterprise-level professional community for Database, BigData, and AIOps. Daily original articles, weekly online tech talks, monthly offline salons, and quarterly XCOPS&DAMS conferences—delivered by industry experts.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
