Master Dockerfile: Build Custom Docker Images Step‑by‑Step
This comprehensive guide explains how to create and customize Docker images using Dockerfile, covering base image selection, RUN, COPY, ADD, CMD, ENTRYPOINT, ENV, VOLUME, EXPOSE, and WORKDIR instructions, along with best practices for layer optimization and context handling.
Introduction
Hello everyone, this article provides a detailed explanation of Docker custom images, showing how to build your own Docker image and use Dockerfile instructions.
1. Using Dockerfile to Customize Images
1.1 Dockerfile Customization
Customizing an image means defining the configuration and files added in each layer. By writing all commands into a script—called a Dockerfile —you achieve repeatable builds, transparency, and smaller image size.
A Dockerfile is a text file containing a series of instructions, each creating a new layer.
Example using an nginx image:
mkdir mynginx
cd mynginx
touch DockerfileThe file content:
FROM nginx
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.htmlThis simple Dockerfile has two instructions: FROM and RUN.
1.2 FROM – Specify Base Image
Custom images start from a base image. The FROM instruction must be the first line in a Dockerfile and defines the base layer.
Docker Hub offers many official images such as nginx, redis, mongo, mysql, httpd, as well as OS images like ubuntu, debian, centos, fedora, alpine. You can also use the special virtual image scratch, which represents an empty image.
If you use scratch as the base, the first layer starts from an empty image.
1.3 RUN – Execute Commands
The RUN instruction executes shell commands during image build. It has two formats:
shell format: RUN <command> exec format:
RUN ["executable", "arg1", "arg2"]Example:
RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.htmlEach RUN creates a new layer. Using many separate RUN commands can lead to a large number of layers, increased build time, and larger images. It is better to combine related commands into a single RUN using && and line continuations.
FROM debian:jessie
RUN buildDeps='gcc libc6-dev make' \
&& apt-get update \
&& apt-get install -y $buildDeps \
&& 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/* \
&& rm redis.tar.gz \
&& rm -r /usr/src/redis \
&& apt-get purge -y --auto-remove $buildDepsThis single RUN builds Redis, cleans up build dependencies, and keeps the image lean.
1.4 Building the Image
After preparing the Dockerfile, build the image with: docker build -t nginx:v3 . The output shows each step, the creation of intermediate containers, and the final image ID.
1.5 Build Context
The final . in the build command specifies the build context—the directory whose contents are sent to the Docker daemon. Only files inside this context can be referenced by COPY or ADD. Using a .dockerignore file can exclude unnecessary files.
2. Dockerfile Instructions
2.1 COPY
Format:
COPY <src>... <dest> COPY ["<src1>", ... "<dest>"] COPYcopies files from the build context into the image, preserving metadata. COPY package.json /usr/src/app/ Wildcards are supported using Go's filepath.Match rules.
2.2 ADD
ADDworks like COPY but can also download files from URLs and automatically extract tar archives (gzip, bzip2, xz). Because of its extra behavior, Docker best practices recommend using COPY unless automatic extraction is needed.
2.3 CMD
CMDdefines the default command executed when a container starts. It supports shell and exec forms. The exec form is preferred because it avoids an extra shell layer.
CMD ["nginx", "-g", "daemon off;"]2.4 ENTRYPOINT
ENTRYPOINTalso defines the container’s startup command but works together with CMD: the CMD arguments are passed as parameters to the ENTRYPOINT. This allows the image to behave like a command where additional arguments can be appended at docker run time. ENTRYPOINT ["curl", "-s", "http://ip.cn"] Running docker run myimage -i adds -i as an argument to curl.
2.5 ENV
ENVsets environment variables that are available to subsequent instructions and at container runtime. ENV VERSION=1.0 DEBUG=on NAME="Happy Feet" Variables can be referenced in later instructions, e.g., $VERSION.
2.6 VOLUME
VOLUMEdeclares mount points for external storage. Declaring a volume ensures that data written to that path is stored outside the image’s layered filesystem.
VOLUME /data2.7 EXPOSE
EXPOSEdocuments which ports the container listens on. It does not publish the ports automatically but helps users and enables docker run -P to map them randomly.
EXPOSE 80 4432.8 WORKDIR
WORKDIRsets the working directory for subsequent instructions. If the directory does not exist, it is created. WORKDIR /app Using WORKDIR is necessary because each RUN instruction runs in a new container; a previous RUN cd /app does not affect later steps.
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.
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.
