Dockerfile 编写指南:13 个核心指令详解
概述
Dockerfile 是 Docker 镜像的构建蓝图。写好 Dockerfile,镜像体积更小、构建更快、运行更安全。本文将 13 个核心指令按功能分类,逐一讲解用法和最佳实践,适合作为速查手册。
13 个指令分为四大类:
分类指令
基础镜像信息FROM
维护者信息LABEL(原 MAINTAINER)
镜像构建操作RUN、COPY、ADD、EXPOSE、WORKDIR、ONBUILD、USER、VOLUME、ENV
容器启动执行CMD、ENTRYPOINT
- FROM:指定基础镜像
必须是 Dockerfile 第一个非注释行,指定后续指令基于哪个镜像构建。
FROM openjdk:8-jdk-alpine
建议优先使用官方镜像和特定版本 Tag,避免使用 latest。
- LABEL:镜像元数据(替代 MAINTAINER)
旧版用 MAINTAINER 指定作者,现已废弃,推荐使用 LABEL:
LABEL org.opencontainers.image.authors=“your-name your-email@gmail.com”
LABEL 还可以添加版本、描述等其他元数据:
LABEL version=“1.0” description=“My application”
-
RUN:执行命令
构建镜像时运行命令,每一条 RUN 都会创建一层镜像。尽量用 && 把多条命令合并,减少镜像层数:
RUN apk add --no-cache tzdata && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone -
COPY:复制文件
将文件从宿主机(构建上下文)复制到镜像内。源文件需和 Dockerfile 在同目录或相对路径。
COPY update.json /usr/local/nginx/share/html/
支持通配符:
COPY *.jar /app/
一般优先使用 COPY,ADD 只在需要自动解压时使用。
-
CMD:容器启动命令
容器启动时默认执行的命令。如果 Dockerfile 中有多个 CMD,只有最后一个生效。docker run 指定的命令会覆盖 CMD。
推荐使用 exec 格式:
CMD [“nginx”, “-g”, “daemon off;”] -
EXPOSE:声明端口
声明容器打算暴露哪个端口。这只是声明,并不会自动在宿主机打开端口。运行时需要用 -p 映射:
EXPOSE 8080
docker run -p 8080:80 my-image
- WORKDIR:配置工作目录
指定容器启动后默认所在目录。目录不存在会自动创建。
WORKDIR /usr/local/nginx/share/html/
后续的 RUN、CMD、ENTRYPOINT 指令都会在这个目录下执行。
- ENTRYPOINT:容器启动入口命令
ENTRYPOINT 和 CMD 语法类似,关键区别:
CMD 的命令会被 docker run 的参数覆盖,而 ENTRYPOINT 不会
如果两者同时存在,CMD 的内容会变成 ENTRYPOINT 的默认参数
ENTRYPOINT [“java”, “-Djava.security.egd=file:/dev/./urandom”, “-jar”, “/app.jar”, “–spring.profiles.active=test”]
典型用法:ENTRYPOINT 指定固定入口程序,CMD 指定可变参数。
- VOLUME:挂载卷
指定容器内的路径会被自动挂载为匿名卷,防止数据写入容器存储层。
VOLUME /tmp
启动容器时可以手动挂载到宿主机目录:
docker run -v /host/path:/container/path my-image
-
USER:指定用户
指定后续 RUN、CMD、ENTRYPOINT 指令使用什么用户运行。出于安全考虑,不建议以 root 用户运行:
USER daemon -
ADD:添加文件
用法和 COPY 基本相同,但 ADD 额外支持:
自动解压压缩文件(.tar、.gz、.bz2 等)
从 URL 下载文件
ADD nginx-1.15.8.tar.gz /usr/src/
推荐:能用 COPY 就用 COPY,只在需要自动解压时用 ADD。
-
ONBUILD:延迟构建指令
当本镜像作为其他镜像的基础镜像时,ONBUILD 指定的指令才会执行。适用于构建基础镜像或 SDK 镜像。
ONBUILD COPY . /app
ONBUILD RUN cd /app && make -
ENV:设置环境变量
设置环境变量,在后续所有 Dockerfile 指令中都可以使用,并且会保留到运行的容器中。
ENV TZ=Asia/Shanghai
ENV JAVA_HOME=/opt/jdk
ENV PATH= P A T H : PATH: PATH:JAVA_HOME/bin
ENV 具有传递性——当前镜像被用作基础镜像时,新镜像会继承所有环境变量。
完整示例:编译安装 Nginx
FROM centos
LABEL org.opencontainers.image.authors=“your-name your-email@gmail.com”
安装依赖
RUN yum -y install gcc make pcre-devel zlib-devel tar zlib
复制源码包
ADD nginx-1.15.8.tar.gz /usr/src/
编译安装
RUN cd /usr/src/nginx-1.15.8 && mkdir /usr/local/nginx && ./configure --prefix=/usr/local/nginx && make && make install && ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
清理源码
RUN rm -rf /usr/src/nginx-1.15.8
EXPOSE 80
CMD [“nginx”, “-g”, “daemon off;”]
构建与常用参数
docker build -t nginx:v1.0 .
参数说明
–build-arg=[]设置镜像创建时的变量
-f指定要使用的 Dockerfile 路径
–force-rm构建过程中删除中间容器
–rm构建成功后删除中间容器
-t, --tag镜像的名字及标签,格式 name:tag
几点最佳实践
减少层数:用 && 合并 RUN 命令,减少镜像层
优先 COPY 而非 ADD:COPY 更透明,ADD 只在需要自动解压时用
使用 .dockerignore:排除不需要的文件,缩小构建上下文
指定版本号:FROM 和依赖安装都指定明确版本,避免 latest
不以 root 运行:用 USER 切换到非 root 用户
清理临时文件:在同一个 RUN 中安装、清理,避免垃圾留在镜像层
更多推荐

所有评论(0)