Cloud Native 28 min read

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.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Customizing Docker Images with Dockerfile: A Complete Guide

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 Dockerfile

Simple Dockerfile content:

FROM nginx
RUN echo '
Hello, Docker!
' > /usr/share/nginx/html/index.html

This 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 make

Build 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 44aa4490ce2c

The 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 -i

ENV

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 /data

EXPOSE

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 443

WORKDIR

Sets the working directory for subsequent instructions. If the directory does not exist, it is created.

WORKDIR /app

Using 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.

Dockerbest practicesContainerDockerfilebuildImage
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.