Master Dockerfile Optimization: Reduce Image Size and Boost Build Efficiency
This guide explains how to format and optimize Dockerfile instructions, choose minimal base images, avoid root users, manage processes, clean caches, and apply best‑practice tips such as proper ENTRYPOINT scripts and labeling to create smaller, more secure container images.
1. Instruction Formatting
LABEL
LABEL vendor=ACME\ Incorporated \
com.example.is-beta= \
com.example.is-production="" \
com.example.version="0.0.1-beta" \
com.example.release-date="2015-02-12"ENV
In a Dockerfile, each ENV creates a temporary layer, similar to RUN.
ENV JAVA_HOME=/opt/jdk1.8.0_241 \
CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
ENV PATH=$PATH:$JAVA_HOME/binRUN
RUN apt-get update && \
apt-get install -y --no-install-recommends \
apt-transport-https \
ca-certificates && \
rm -rf /var/lib/apt/lists/*2. Instruction Optimization
1. Reduce RUN statements by chaining commands
RUN useradd -s /sbin/nologin -m -u 1001 curiouser && \
mkdir -p /home/curiouser/{data,logs} && \
rm -rf /etc/yum.repos.d/C* && \
yum install -q -y git && \
yum clean all && \
curl -s http://192.168.1.7/repository/tools/jdk-8u241-linux-x64.tar.gz | tar -xC /opt/2. Use COPY instead of ADD for remote tarballs
Replace remote ADD with a RUN curl … | tar pattern.
RUN curl -s http://192.168.1.7/repository/tools/jdk-8u241-linux-x64.tar.gz | tar -xC /opt/3. Minimize Base Image to Reduce Image Size
1. Prefer Alpine as the base image
Alpine images are only a few megabytes.
Use apk to install only the required packages.
FROM alpine:3.11.5
RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories \
&& apk add --no-cache git4. Avoid Running as Root
Create a non‑root user and limit permissions for runtime containers.
gosu
FROM alpine:3.11.5
RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories \
&& apk add --no-cache gosu5. Use a Process‑Management Tool to Handle Signals
Prevent zombie processes inside containers.
dumb‑init
GitHub: https://github.com/Yelp/dumb-init
FROM alpine:3.11.5
RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories \
&& apk add --no-cache dumb-init
# Runs "/usr/bin/dumb-init -- /my/script --with --args"
ENTRYPOINT ["dumb-init", "--"]
CMD ["/my/script", "--with", "--args"]6. Remove All Caches and Unnecessary Files
Delete extracted source archives.
Clean package‑manager caches.
For Alpine: use apk add --no-cache ….
For Ubuntu/Debian: run rm -rf /var/lib/apt/lists/* after apt installs.
7. Use a Reasonable ENTRYPOINT Script
Example script:
#!/bin/bash
set -e
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
fi
exec gosu postgres "$@"
fi
exec "$@"8. Additional Recommendations
1. Set Timezone
FROM alpine:3.11.5
ENV TZ=Asia/Shanghai
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
&& apk add --no-cache tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone2. Set System Language
FROM alpine:3.11.5
ENV LANG=en_US.UTF-8 \
LANGUAGE=en_US.UTF-8
RUN apk --no-cache add ca-certificates \
&& wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub \
&& wget -q https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.29-r0/glibc-2.29-r0.apk \
&& wget -q https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.29-r0/glibc-bin-2.29-r0.apk \
&& wget -q https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.29-r0/glibc-i18n-2.29-r0.apk \
&& apk add glibc-2.29-r0.apk glibc-bin-2.29-r0.apk glibc-i18n-2.29-r0.apk \
&& rm -rf /usr/lib/jvm glibc-2.29-r0.apk glibc-bin-2.29-r0.apk glibc-i18n-2.29-r0.apk \
&& /usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true \
&& echo "export LANG=$LANG" > /etc/profile.d/locale.sh \
&& apk del glibc-i18n3. Use LABEL to Add Metadata
FROM alpine:3.11.5
LABEL Author=Curiouser \
Mail=****@163.com \
PHP=7.3 \
Tools="git, vim, curl" \
Update="添加用户组"4. Define Working Directory
WORKDIR /var/wwww5. Show Optimized RUN Syntax
RUN set -eux ; \
ls -al9. Image Build Practices
1. Naming Convention
Use a three‑part naming scheme: registry/type/image:tag.
registry/runtime/Java:8.1.2
registry/runtime/php-fpm-nginx:7.3-1.14
registry/cicd/kubectl-helm:1.17-3.0
registry/cicd/git-compose-docker:v1
registry/applications/demo:git_commit_id
2. Use a Makefile
IMAGE_BASE = registry/runtime
IMAGE_NAME = php-fpm
IMAGE_VERSION = 7.3
all: build push
build:
docker build --rm -f Dockerfile -t ${IMAGE_BASE}/${IMAGE_NAME}:${IMAGE_VERSION} .
push:
docker push ${IMAGE_BASE}/${IMAGE_NAME}:${IMAGE_VERSION}
# Build and push
make
# Only build
make build
# Only push
make pushReferences
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
https://www.artindustrial-it.com/2017/09/20/10-best-practices-for-creating-good-docker-images/
https://gist.github.com/StevenACoffman/41fee08e8782b411a4a26b9700ad7af5
https://snyk.io/blog/10-docker-image-security-best-practices/
Original source: https://gitbook.curiouser.top/origin/dockerfile-optimization.html#
Open Source Linux
Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.
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.
