Master Dockerfile: Essential Commands and Best Practices for Building Efficient Images
This article explains how Docker images are created, introduces Dockerfile syntax and key instructions such as FROM, COPY, RUN, CMD, and ENTRYPOINT, and provides practical guidelines and real‑world examples for building clean, lightweight containers.
Image Generation Methods
About Dockerfile
Dockerfile is the source code for building Docker images; it is a plain‑text file.
When building an image from a Dockerfile, the file must reside in a specific directory. The filename must start with a capital "D". To exclude files from the build context, a .dockerignore file can be defined. Finally, docker build creates the image.
Dockerfile Instructions
FROM
FROM is the first non‑comment line in a Dockerfile and specifies the base image for the build.
The base image can be any available image; if it does not exist locally, Docker pulls it from Docker Hub.
If the image cannot be found, docker build returns an error.
Syntax: FROM [image[:tag]] or
FROM image@digestMAINTAINER (deprecated)
Provides author information; placement is not restricted but is usually placed after FROM.
Syntax:
MAINTAINER "Name <[email protected]>"LABEL
Syntax:
LABEL key=value key=value ...COPY
Copies files from the build context into the image.
Syntax: COPY src dest or COPY ["src", "dest"] If the destination path contains spaces, the JSON form should be used.
Files must be inside the build context; directories are copied recursively but the directory itself is not created unless it already exists.
ADD
Similar to COPY but also supports extracting TAR archives and downloading from URLs.
Syntax: ADD src dest or
ADD ["src", "dest"]WORKDIR
Sets the working directory for subsequent RUN, CMD, ENTRYPOINT, COPY and ADD instructions.
Syntax:
WORKDIR /pathVOLUME
Creates a mount point inside the image.
Syntax: VOLUME /path or
VOLUME ["/path"]EXPOSE
Documents which ports the container listens on.
Syntax:
EXPOSE 80/tcp 443/tcpENV
Defines environment variables for later instructions.
Syntax: ENV VAR=value or
ENV VAR1=value1 VAR2=value2RUN
Executes commands during image build.
Two forms: shell form RUN command and exec form
RUN ["executable","param1","param2"]CMD
Specifies the default command to run when a container starts.
Only the last CMD in the Dockerfile takes effect.
Syntax similar to RUN.
ENTRYPOINT
Defines a container's main executable; arguments from docker run are appended.
Unlike CMD, ENTRYPOINT cannot be overridden unless --entrypoint is used.
Only the last ENTRYPOINT is effective.
USER
Specifies the user (or UID) under which subsequent instructions run.
Default user is root.
HEALTHCHECK
Defines a command to test container health.
Options include --interval, --timeout, --retries, and --start-period.
Only the last HEALTHCHECK is used.
ONBUILD
Registers a trigger instruction that runs when the image is used as a base for another build.
Cannot be nested and does not trigger FROM or MAINTAINER.
Basic Dockerfile Guidelines
Containers should be short‑lived (ephemeral).
Use .dockerignore to exclude unnecessary files (syntax same as .gitignore).
Prefer multi‑stage builds to reduce final image size.
Avoid installing unnecessary packages.
Each container should do one thing; separate services into separate containers.
Only RUN, COPY, and ADD create image layers; minimize layer count.
Order instructions to maximize cache reuse; use --no-cache to force rebuild.
Dockerfile Examples
Build an sshd image
# Dockerfile
FROM centos:centos7
LABEL maintainer="hukey<[email protected]>"
RUN yum install -y openssh* net-tools iproute NetworkManager && \
echo "UseDNS no" >> /etc/ssh/sshd_config && \
sed -i '/pam_loginuid.so/d' /etc/pam.d/sshd && \
echo '123123' | passwd --stdin root && \
ssh-keygen -A && yum clean all
EXPOSE 22
CMD ["/usr/sbin/sshd","-D"]Build a systemd image (based on the sshd image)
# Dockerfile
FROM sshd:v0.1-2
LABEL maintainer="hukey<[email protected]>"
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done) && \
rm -f /lib/systemd/system/multi-user.target.wants/* && \
rm -f /etc/systemd/system/*.wants/* && \
rm -f /lib/systemd/system/local-fs.target.wants/* && \
rm -f /lib/systemd/system/sockets.target.wants/*udev* && \
rm -f /lib/systemd/system/sockets.target.wants/*initctl* && \
rm -f /lib/systemd/system/basic.target.wants/* && \
rm -f /lib/systemd/system/anaconda.target.wants/*
VOLUME ["/sys/fs/cgroup"]
CMD ["/usr/sbin/init"]Build an nginx image
# Dockerfile
FROM centos:centos7
LABEL maintainer="hukey<[email protected]>"
ENV NGX_PACKAGE="nginx-1.18.0"
ADD http://192.168.118.45/${NGX_PACKAGE}.tar.gz /usr/local/src/
WORKDIR /usr/local/src/${NGX_PACKAGE}
RUN tar xf /usr/local/src/${NGX_PACKAGE}.tar.gz && \
yum install -y proc-devel gcc gcc-c++ zlib zlib-devel make openssl-devel wget && \
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_gzip_static_module \
--with-http_stub_status_module \
--with-http_realip_module && \
make -j2 && make install && \
echo "daemon off;" >> /usr/local/nginx/conf/nginx.conf && yum clean all && rm -rf /var/cache/yum/*
EXPOSE 80/tcp 443/tcp
ADD run.sh /run.sh
CMD ["/run.sh"]Build a tomcat image
# Dockerfile
FROM centos:centos7
LABEL maintainer="hukey <[email protected]>"
ADD jdk-8u77-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-8.5.61.tar.gz /usr/local/
ENV JAVA_HOME="/usr/local/java" \
JAVA_BIN="/usr/local/java/bin" \
JRE_HOME="/usr/local/java/jre" \
PATH="$PATH:/usr/local/java/bin:/usr/local/java/jre/bin" \
CLASSPATH="/usr/local/java/jre/bin:/usr/local/java/lib:/usr/local/java/jre/lib/charsets.jar"
WORKDIR /usr/local/
RUN mv jdk1.8.0_77 java && mv apache-tomcat-8.5.61 tomcat8
EXPOSE 8080
ENTRYPOINT ["/usr/local/tomcat8/bin/catalina.sh","run"]These examples illustrate how to define base images, set environment variables, copy files, expose ports, and combine CMD and ENTRYPOINT for flexible container startup.
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.
Raymond Ops
Linux ops automation, cloud-native, Kubernetes, SRE, DevOps, Python, Golang and related tech discussions.
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.
