易君召
易君召
发布于 2026-07-24 / 1 阅读
0
0

Dockerfile 完整基础语法详解

Dockerfile 是构建 Docker 镜像的文本文件,由指令(大写关键字)+ 参数组成,指令自上而下顺序执行,每行一条指令,注释以 # 开头。

一、核心基础指令(必掌握)

1. FROM(镜像基础,第一条有效指令

指定构建镜像的父基础镜像,所有 Dockerfile 必须以 FROM 开头(除 ARG 外)。

语法:

dockerfile

# 格式1:基础镜像:标签
FROM ubuntu:22.04
# 格式2:镜像@哈希(固定版本,防止标签更新)
FROM nginx@sha256:xxxxxx
# 多阶段构建(多个FROM,用于精简镜像)
FROM golang:1.22 AS builder
  • AS 别名:多阶段构建给阶段命名,后续可复制该阶段文件

2. WORKDIR(设置工作目录)

设定容器内的默认工作路径,后续 RUN/COPY/ADD/CMD 都会基于该目录;目录不存在会自动创建。

dockerfile

# 绝对路径推荐
WORKDIR /app
# 可多层连续设置,自动拼接
WORKDIR src
# 最终目录:/app/src

替代 RUN mkdir -p /app && cd /app,更简洁规范

3. COPY(复制本地文件到镜像,日常首选

构建主机本地的文件 / 文件夹复制到镜像内,只支持本地资源,无解压、远程下载功能。

语法:

dockerfile

# 格式:COPY [源路径1,源路径2...] [容器目标路径]
# 1. 普通写法(路径不含空格)
COPY ./target/demo.jar /app/demo.jar
# 2. 数组写法(路径带空格时使用)
COPY ["my app.txt", "/app/data.txt"]

# 复制整个目录,目标目录不存在自动创建
COPY ./static /app/static

特性:

  1. 源路径是Docker 构建上下文内的文件(上下文为 docker build . 最后的 .

  2. 自动保留文件权限

  3. 不支持 URL、压缩包自动解压

4. ADD(增强版 COPY,仅特殊场景用)

兼容 COPY 所有能力,额外两个特性:

  1. 源是 .tar/.gz/.bz2 压缩包:自动解压到目标目录

  2. 源是 HTTP/HTTPS URL:自动下载远程文件到镜像

dockerfile

# 自动解压压缩包
ADD app.tar.gz /app/
# 下载远程文件
ADD https://xxx.com/jdk17.tar.gz /tmp/

使用建议:单纯复制本地文件优先用 COPY,语义清晰;只有需要解压 / 下载远程文件才用 ADD。

5. RUN(构建镜像时执行命令)

镜像构建阶段运行 shell 命令,执行结果写入镜像分层;常用于安装依赖、编译代码。

两种语法:

dockerfile

# 写法1:shell 格式(底层调用 /bin/sh -c)
RUN apt update && apt install -y curl

# 写法2:exec 数组格式(无shell环境,适合无sh的基础镜像如alpine)
RUN ["apt", "update"]

优化技巧:多条命令合并成一个 RUN,减少镜像分层,减小镜像体积

dockerfile

# 不推荐:生成多层
RUN apt update
RUN apt install curl

# 推荐:合并单条RUN
RUN apt update && apt install -y curl && rm -rf /var/lib/apt/lists/*

6. CMD(容器启动默认执行命令)

容器运行阶段执行,镜像构建时不运行;一个 Dockerfile 只能有一条生效 CMD,多条仅最后一条生效。

作用:容器启动默认程序,docker run 末尾传参可覆盖 CMD。

三种写法:

dockerfile

# 1. exec 数组格式(推荐,无shell,PID1进程)
CMD ["java", "-jar", "/app/demo.jar"]

# 2. shell 格式(底层 /bin/sh -c,程序不是PID1,信号转发异常)
CMD java -jar /app/demo.jar

# 3. 配合ENTRYPOINT,仅传参数
CMD ["--port", "8080"]

7. ENTRYPOINT(容器入口程序,不可被直接覆盖)

和 CMD 类似,容器启动执行,但区别:

  1. docker run 后的参数不会覆盖 ENTRYPOINT,而是作为参数传给 ENTRYPOINT

  2. 适合固定启动脚本,CMD 仅作为默认参数

dockerfile

# exec格式(推荐)
ENTRYPOINT ["/bin/bash", "/app/start.sh"]
# 默认参数,run传参可替换
CMD ["8080"]

执行逻辑:/bin/bash /app/start.sh 8080

二、常用配置指令

8. EXPOSE(声明容器监听端口,仅文档作用)

声明容器内部应用使用的端口,不会自动映射宿主机端口,仅给阅读者、工具做提示。

dockerfile

# 声明TCP 8080端口
EXPOSE 8080
# 声明UDP端口
EXPOSE 9999/udp

实际端口映射仍需 docker run -p 宿主机端口:容器端口

9. ENV(设置环境变量,构建 + 运行阶段都生效)

定义镜像内环境变量,后续所有指令(RUN/CMD/ENTRYPOINT)均可引用。

dockerfile

# 单变量
ENV APP_NAME=demo
# 多变量
ENV JAVA_HOME=/usr/local/jdk \
    PORT=8080

# 使用变量
CMD ["java", "-jar", "/app/${APP_NAME}.jar"]

运行时可通过 docker run -e PORT=9090 覆盖环境变量

10. ARG(构建参数,仅镜像构建阶段生效)

构建镜像时传入的临时变量,容器运行阶段失效;配合 docker build --arg KEY=VALUE 使用。

dockerfile

# 定义参数,可设置默认值
ARG JDK_VERSION=17
# 使用ARG参数
FROM openjdk:${JDK_VERSION}

区分 ENV / ARG:

  • ARG:构建镜像时临时参数,容器运行看不到

  • ENV:写入镜像,容器启动后环境永久存在

三、进阶运维指令

11. VOLUME(声明数据卷,持久化存储)

声明容器内目录为数据卷,容器删除后数据保留;自动挂载匿名卷,避免容器写入数据随容器销毁丢失。

dockerfile

# 声明多个持久化目录
VOLUME ["/app/logs", "/app/data"]

注意:Dockerfile 无法指定宿主机挂载路径,宿主机绑定挂载只能在 docker run -v 指定。

12. USER(切换执行用户)

切换后续 RUN/CMD/ENTRYPOINT 指令的执行用户,默认 root;生产环境禁止容器以 root 运行,安全规范必备。

dockerfile

# 创建普通用户
RUN useradd -m appuser
# 切换用户
USER appuser
# 后续命令都以 appuser 执行
CMD ["java", "-jar", "/app/demo.jar"]

13. LABEL(镜像元数据标签)

给镜像添加自定义元数据,如作者、版本、描述,使用 docker inspect 镜像名 查看。

dockerfile

# 多标签写法
LABEL author="zhangsan" \
      version="1.0" \
      description="SpringBoot demo image"

14. HEALTHCHECK(容器健康检查)

定义健康检测命令,Docker 定期执行判断容器是否正常,支持 HTTP / 命令 / TCP 检测。

dockerfile

# 基础语法:检测命令,间隔30s,超时5s,失败3次标记不健康
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD curl -f http://127.0.0.1:8080/actuator/health || exit 1

15. SHELL(自定义 shell 解释器,极少使用)

修改 RUN shell 格式默认使用的解释器,默认 /bin/sh -c,alpine 可改为 ash。

dockerfile

# 替换shell为bash
SHELL ["/bin/bash", "-c"]
RUN source /app/env.sh

四、生命周期对比总结表

指令

执行阶段

核心用途

FROM

构建开始

指定基础镜像

ARG

构建阶段

构建临时参数

RUN

构建阶段

安装依赖、编译

COPY/ADD

构建阶段

拷贝文件到镜像

WORKDIR

构建阶段

设置工作目录

ENV

构建 + 运行

全局环境变量

LABEL

构建阶段

镜像元数据

USER

构建 + 运行

切换运行用户

VOLUME

运行阶段

持久化数据目录

EXPOSE

仅文档声明

标注应用端口

ENTRYPOINT

容器启动

固定入口程序

CMD

容器启动

默认启动参数 / 命令

HEALTHCHECK

容器运行

健康状态巡检

五、完整极简示例 Dockerfile

dockerfile

# 构建参数
ARG JDK_VER=17
# 基础镜像
FROM openjdk:${JDK_VER}
# 镜像标签
LABEL author="demo" version="1.0"
# 环境变量
ENV APP_PORT=8080
# 工作目录
WORKDIR /app
# 复制jar包
COPY ./target/demo.jar /app/app.jar
# 声明端口
EXPOSE ${APP_PORT}
# 健康检查
HEALTHCHECK --interval=20s CMD curl -f http://127.0.0.1:${APP_PORT}/health || exit 1
# 容器启动命令
CMD ["java", "-jar", "/app/app.jar", "--server.port=${APP_PORT}"]


评论