跳到主要内容
Dockerfile 核心指令详解与实战指南 | 极客日志
Shell / Bash java
Dockerfile 核心指令详解与实战指南 Dockerfile 是构建 Docker 镜像的核心脚本,通过逐层指令生成不可变镜像。本文详解了 FROM、RUN、COPY、CMD/ENTRYPOINT 等关键指令,重点解析了多阶段构建如何减小镜像体积,以及 Shell 格式与 Exec 格式的区别。同时涵盖了构建参数传递、缓存优化、安全实践及 SpringBoot 部署实战,帮助开发者掌握高效、安全的容器化构建流程。
BigDataPan 发布于 2026/3/15 0 浏览Dockerfile 概述
什么是 Dockerfile
Dockerfile 是构建 Docker 镜像的文本脚本,里面包含了一系列 指令(Instruction) 。Docker 引擎会自上而下、逐条执行这些指令,最终生成一个不可变的镜像。
镜像、Layer 与容器的关系
理解 Docker 的核心在于理解 Layer:
Docker 镜像(Image) 由多个 只读 Layer 组成。
每一条 Dockerfile 指令都会生成一个 Layer 。
Layer 是不可变的增量快照。
构建缓存、镜像复用、镜像瘦身,全部基于 Layer 机制。
简单来说:镜像 = 多个只读 Layer 的叠加,而 容器 = 镜像 + 一层可写层(Container Layer)。
Dockerfile 到 Layer 的真实映射
看个简单的例子,你的 Dockerfile 长这样:
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y curl
COPY app.sh /app/app.sh
生成的镜像层大致如下:
层号 Dockerfile 指令 Layer 内容 1 FROM ubuntu Ubuntu 文件系统 2 RUN apt-get update apt 缓存 3 RUN apt-get install curl 二进制 4 COPY app.sh app.sh 文件
注意:Dockerfile 不是合并执行 ,而是逐层叠加 。这意味着每一行指令如果变动,后续所有层的缓存都会失效。
Dockerfile 核心指令详解
1. FROM
指令说明
FROM 用于指定当前镜像所基于的基础镜像 ,它是 Dockerfile 中的第一条有效指令 。一个 Dockerfile 中可以存在多个 FROM,这通常用于多阶段构建。
基础镜像来源逻辑很简单:Docker 会优先在本地查找;本地不存在则从 Docker Hub 或私有仓库拉取;如果找不到,构建直接失败。
语法格式
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>@<digest> [AS <name>]
参数建议
参数 是否必需 含义 工程建议 <image>必需 基础镜像名称
:<tag>推荐 镜像版本标签 生产必须指定版本 ,不指定默认最新
示例 # 指定具体版本标签
FROM williamyeh/java8:latest
# 指定内容哈希(最安全)
FROM williamyeh/java8@sha256:174d528516a0eae5c4df69966eeb5e51d7c0dc1a532249af61013953eab1d9f3
# 跨平台构建
FROM --platform=linux/amd64 ubuntu:20.04 AS builder
多阶段构建(Multi-stage Build) 多阶段构建通过 多个 FROM 将构建环境 与运行环境 分离,仅保留最终运行所需的产物。这能大幅减小镜像体积、降低安全风险。
❌ 错误示例(单阶段) :Maven 与源码永久存在镜像中,导致臃肿。
FROM openjdk:11
RUN apt-get update && apt-get install -y maven
COPY . /app
WORKDIR /app
RUN mvn package
ENTRYPOINT ["java", "-jar", "target/app.jar"]
# 构建阶段
FROM maven:3.9-eclipse-temurin-11 AS builder
WORKDIR /build
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests
# 运行阶段
FROM openjdk:11-jre
WORKDIR /app
COPY --from=builder /build/target/app.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
2. WORKDIR WORKDIR 用于在 Docker 镜像内部设置工作目录 。一旦设置,后续的 RUN、CMD、ENTRYPOINT、COPY 和 ADD 等指令的执行环境都会以这个目录为当前起点。如果不设置,默认是根目录 /。
FROM ubuntu:22.04
WORKDIR /usr/why/app
RUN pwd
COPY . .
这里 RUN 和之后的命令都在 /usr/why/app 下执行。
FROM ubuntu:22.04
WORKDIR /app
RUN pwd # 输出:/app
WORKDIR why
RUN pwd # 输出:/app/why
WORKDIR test
RUN pwd # 输出:/app/why/test
3. COPY COPY 用于将构建上下文中的文件或目录 复制到镜像中。这是最推荐使用的文件复制指令 ,行为更可控。
--from=<stage>:从指定构建阶段复制文件(多阶段构建核心)。
--chown=<user>:<group>:设置文件属主和属组(优于 RUN chown)。
--chmod=<perms>:设置文件权限。
--exclude=<pattern>:排除匹配的文件。
--link:使用硬链接代替复制(需开启 BuildKit),减少 IO。
# 从构建阶段复制
COPY --from=builder /build/target/app.jar /app/app.jar
# 设置属主
COPY --chown=appuser:appgroup app.jar /app/app.jar
# 使用硬链接优化性能
COPY --link app.jar /app/app.jar
4. ADD ADD 功能比 COPY 宽泛,支持远程 URL 下载并自动解压压缩文件。但因为它有隐式行为(如自动解压),官方推荐使用 COPY ,除非你需要 URL 下载或解压功能。
URL 支持 :ADD 支持,COPY 不支持。
自动解压 :ADD 支持 (.tar, .gz 等),COPY 不支持。
安全性 :COPY 更安全,ADD 可能引入供应链风险。
缓存稳定性 :COPY 稳定,ADD 不稳定。
5. LABEL LABEL 为镜像添加元数据(metadata) ,以键值对形式存在,描述作者、版本等信息。它不影响构建流程,主要用于信息标注与管理。
LABEL maintainer="xiaoyangzi <[email protected] >"
LABEL version="1.0" description="测试镜像"
6. ENV ENV 用于在构建过程中设置环境变量 ,这些变量会持久化在镜像里。可以在 Dockerfile 中使用 $variable_name 或 ${variable_name} 引用。
ENV NAME="XYZ" AGE=18 gender=male
CMD echo "Hello, $NAME"
7. ARG ARG 定义构建阶段变量 ,仅在构建时可用,不会在容器运行时保留。适合传递动态参数(如版本号)。
ARG APP_ENV=dev
ARG APP_VERSION
RUN echo "Version: ${APP_VERSION:-v0.0.1}"
docker build --build-arg APP_ENV=prod --build-arg APP_VERSION=1.2.3 .
ARG APP_ENV=dev
ENV APP_ENV=${APP_ENV}
注意:如果先定义 ENV 再定义 ARG,ENV 的值会覆盖 ARG。
8. RUN RUN 用于在镜像构建阶段 执行命令,并将结果提交为新的镜像层。
Shell 格式 (RUN cmd):启动 /bin/sh -c,支持管道、变量替换、通配符。适合复杂逻辑。
Exec 格式 (RUN ["cmd", "arg"]):直接调用可执行文件,不经过 Shell。PID 1 更可靠,适合优雅停止。
--mount=type=cache:挂载缓存目录(如 pip cache)。
--mount=type=secret:安全传递密钥。
--network=none:禁止联网,提高安全性。
# 合并 RUN 以减少层数
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
# 使用缓存
RUN --mount=type=cache,target=/root/.cache pip install -r requirements.txt
9. ENTRYPOINT & CMD 这两个指令容易混淆,简单记:ENTRYPOINT 是程序本身,CMD 是默认参数。
ENTRYPOINT :定义容器启动时的固定入口程序。无论 docker run 传什么,ENTRYPOINT 都会被执行。推荐使用 Exec 格式以保证 PID 1 是应用进程,支持 SIGTERM 优雅停止。
CMD :提供默认启动命令或参数。如果有多个 CMD,只有最后一个生效。可以被运行时参数覆盖。
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
这样 docker run image 执行 nginx -g daemon off;,而 docker run image -t 执行 nginx -t。
10. EXPOSE EXPOSE 声明容器在运行时'预期会监听'的端口 。它只是文档化的元数据提示,不会真的打开端口 。实际映射需要 -p 或 -P 参数。
EXPOSE 80/tcp
EXPOSE 443/tcp
11. VOLUME VOLUME 声明容器中的某个路径是持久化数据目录 。数据存储在宿主机的随机目录(匿名卷)或指定目录中,容器销毁后数据保留。
12. USER USER 指定后续指令及容器运行时所使用的用户。默认是 root,为了安全,建议在最后切换到非 root 用户。
RUN groupadd -g 1001 appgroup && useradd -r -u 1001 -g appgroup appuser
USER appuser
13. HEALTHCHECK HEALTHCHECK 定义周期性执行的命令,判断容器是否健康。状态包括 healthy、unhealthy、starting。
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s \
CMD curl -f http://localhost:8080/health || exit 1
14. ONBUILD ONBUILD 是构建触发器。它在当前镜像构建时不执行 ,而是在基于当前镜像的子镜像构建时触发。常用于制作基础镜像模板。
15. STOPSIGNAL 当执行 docker stop 时,Docker 发送给容器主进程的信号。默认是 SIGTERM。对于某些应用(如 Nginx),可能需要 SIGQUIT 来优雅重载配置。
docker build 构建命令
基本语法 docker build [OPTIONS] PATH | URL | -
PATH : 构建上下文路径。
URL : Git 仓库或 HTTP 资源。
- : 从 stdin 读取 Dockerfile。
常用参数
-t: 给镜像打标签。
-f: 指定 Dockerfile 路径。
--build-arg: 传入构建参数。
--no-cache: 禁用缓存。
--platform: 指定目标平台(如 linux/amd64)。
--secret: 安全传递密钥。
.dockerignore 位于构建上下文根目录,用于过滤不需要发送给 Docker daemon 的文件(如 .git, node_modules),加快构建速度。
.git
node_modules
target
dist
*.log
SpringBoot 部署示例
1. 拉取 Java 镜像 docker pull williamyeh/java8
2. 编写 Dockerfile FROM williamyeh/java8
ADD api-test.jar /api-test.jar
EXPOSE 8087
ENTRYPOINT ["java", "-jar", "/api-test.jar"]
3. 打包镜像 docker build -f Dockerfile -t why/api-test:v1.0 .
4. 启动容器 docker run -d --name api-test -p 8087:8087 why/api-test:v1.0
如果需要负载均衡,可以部署多个实例映射不同宿主机端口:
docker run -d --name api-test2 -p 8088:8087 why/api-test:v1.0
docker run -d --name api-test3 -p 8089:8087 why/api-test:v1.0
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online