Customizing Docker Images with Dockerfile: A Complete Guide
This article explains how to use Dockerfiles to customize Docker images, covering base image selection, RUN, COPY, ADD, CMD, ENTRYPOINT, ENV, VOLUME, EXPOSE, and WORKDIR instructions, along with best practices for layer optimization, build context handling, and efficient image construction.
1 Use Dockerfile to Customize Images
Dockerfile Customization
Customizing an image means defining each layer’s configuration, files, and commands in a script called a Dockerfile . Each line in the Dockerfile creates a new layer, making the build process transparent and repeatable.
Example: create an empty directory, add a Dockerfile , and write the following content.
$ mkdir mynginx
$ cd mynginx
$ touch DockerfileSimple Dockerfile content:
FROM nginx
RUN echo '
Hello, Docker!
' > /usr/share/nginx/html/index.htmlThis file uses two instructions: FROM (base image) and RUN (execute a command).
FROM – Specify Base Image
The base image is the starting point for customization. FROM must be the first instruction and defines which existing image (e.g., nginx , redis , ubuntu , etc.) the new image builds upon. The special scratch image represents an empty image.
RUN – Execute Commands
RUN executes shell commands during the build. It supports two formats:
shell format: RUN <command>
exec format: RUN ["executable", "arg1", "arg2"]
Each RUN creates a new layer. Over‑using separate RUN statements leads to many layers, larger images, and slower builds. Combining related commands with && into a single RUN reduces layers.
RUN apt-get update \
&& apt-get install -y gcc libc6-dev make \
&& wget -O redis.tar.gz "http://download.redis.io/releases/redis-3.2.5.tar.gz" \
&& mkdir -p /usr/src/redis \
&& tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
&& make -C /usr/src/redis \
&& make -C /usr/src/redis install \
&& rm -rf /var/lib/apt/lists/* redis.tar.gz /usr/src/redis \
&& apt-get purge -y --auto-remove gcc libc6-dev makeBuild Image
Run the build with:
$ docker build -t nginx:v3 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM nginx
---> e43d811ce2f4
Step 2 : RUN echo '
Hello, Docker!
' > /usr/share/nginx/html/index.html
---> Running in 9cdc27646c7b
---> 44aa4490ce2c
Removing intermediate container 9cdc27646c7b
Successfully built 44aa4490ce2cThe command shows each step, the temporary container used for RUN , and the final image ID.
Image Build Context
The path supplied to docker build (often . ) is the build context. Docker packs the entire directory (excluding files matched by .dockerignore ) and sends it to the daemon. Only files inside the context can be referenced by COPY or ADD .
2 Dockerfile Instructions
COPY
Format: COPY <src>... <dest> or JSON array syntax. Sources are relative to the build context; destinations can be absolute or relative to WORKDIR . Permissions and timestamps are preserved.
COPY package.json /usr/src/app/ADD
Similar to COPY but can fetch remote URLs and automatically extract tar archives (gzip, bzip2, xz). Because of its extra behavior, ADD should be used only when auto‑extraction is needed; otherwise prefer COPY .
CMD
Specifies the default command for the container. Two formats are supported:
Shell form: CMD <command>
Exec form: CMD ["executable", "arg1", "arg2"]
If the container is started with a different command, the provided command overrides CMD .
ENTRYPOINT
Defines the executable that will always run. When combined with CMD , the CMD arguments are passed as parameters to the ENTRYPOINT . This pattern lets an image behave like a command while still allowing extra arguments.
ENTRYPOINT ["curl", "-s", "http://ip.cn"]
# Running: docker run myip -i
# Executes: curl -s http://ip.cn -iENV
Sets environment variables that can be used in later instructions and at runtime.
ENV VERSION=1.0 DEBUG=on NAME="Happy Feet"VOLUME
Declares mount points that will be created as anonymous volumes unless the user supplies a named volume at docker run -v .
VOLUME /dataEXPOSE
Documents which ports the container intends to listen on. It does not publish the ports; -p or -P must be used at runtime.
EXPOSE 80 443WORKDIR
Sets the working directory for subsequent instructions. If the directory does not exist, it is created.
WORKDIR /appUsing WORKDIR is preferred over chaining cd commands in RUN because each RUN starts a new container layer.
Community Notice
Join our backend‑focused technical group for high‑quality discussions, job referrals, and industry insights. Please keep conversations civil and focused on technology.
Advertisement: add me as a friend to be invited to the group.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
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.