Dockerfile详解

Dockerfile 是用来定义 Docker 镜像构建过程的纯文本文件。通过一系列指令,Docker 可以自动读取并执行,最终生成一个可运行的镜像。下面是 完整、详细的 Dockerfile 核心指令与配置详解,包含语法、作用、示例、区别与最佳实践。


一、Dockerfile 基本结构

一个标准 Dockerfile 通常包含:

  1. 解析器指令(可选,开头)
  2. 基础镜像(FROM,必选)
  3. 元数据(LABEL、MAINTAINER)
  4. 环境变量(ENV、ARG)
  5. 文件操作(COPY、ADD)
  6. 构建时命令(RUN)
  7. 工作目录(WORKDIR)
  8. 用户(USER)
  9. 端口声明(EXPOSE)
  10. 数据卷(VOLUME)
  11. 健康检查(HEALTHCHECK)
  12. 启动命令(CMD、ENTRYPOINT)

二、核心指令详解(按常用顺序)

1. FROM ------ 基础镜像(必选)

作用 :指定构建新镜像所依赖的基础镜像(所有镜像都必须基于某个基础镜像)。
语法

dockerfile 复制代码
FROM <image>[:<tag>] [AS <name>]  # 多阶段构建可用 AS

示例

dockerfile 复制代码
FROM ubuntu:22.04
FROM openjdk:17-jdk-slim
FROM scratch  # 空镜像(用于构建最底层镜像)

要点

  • 必须是 第一个非注释指令(ARG 可在 FROM 前)。
  • 标签尽量固定(如 22.04),不要用 latest(不稳定)。
  • 多阶段构建:FROM ... AS builder 可拆分构建与运行阶段,大幅减小镜像体积。

2. ARG ------ 构建参数(构建时有效)

作用 :定义构建过程中 可用的变量(容器运行时不存在)。
语法

dockerfile 复制代码
ARG <name>[=<default value>]

示例

dockerfile 复制代码
ARG NGINX_VERSION=1.25.3
FROM nginx:${NGINX_VERSION}

# 构建时覆盖:
# docker build --build-arg NGINX_VERSION=1.24.0 -t my-nginx .

与 ENV 区别

  • ARG:仅构建时有效,镜像/容器中不保留。
  • ENV:构建与运行时都有效,会写入镜像。

3. LABEL ------ 元数据标签

作用 :给镜像添加键值对元数据(作者、版本、描述等)。
语法

dockerfile 复制代码
LABEL <key>=<value> <key>=<value> ...

示例

dockerfile 复制代码
LABEL maintainer="yourname@example.com"
LABEL version="1.0" description="Hadoop Base Image"

替代 :旧指令 MAINTAINER 已废弃,用 LABEL 代替。


4. ENV ------ 环境变量(永久生效)

作用 :设置环境变量(构建、运行、子进程都可用)。
语法

dockerfile 复制代码
ENV <key>=<value> ...  # 推荐一行多个
ENV <key> <value>      # 旧格式

示例

dockerfile 复制代码
ENV JAVA_HOME=/usr/lib/jvm/default-java \
    HADOOP_HOME=/usr/local/hadoop \
    PATH=$PATH:$HADOOP_HOME/bin

作用

  • 简化后续指令路径
  • 容器运行时可直接使用
  • 可被 docker run -e key=val 覆盖

5. WORKDIR ------ 工作目录

作用 :设置后续 RUN/CMD/ENTRYPOINT/COPY/ADD 的工作目录(自动创建)。
语法

dockerfile 复制代码
WORKDIR <path>

示例

dockerfile 复制代码
WORKDIR /usr/local/hadoop
RUN pwd  # 输出 /usr/local/hadoop

最佳实践

  • 用绝对路径
  • 不要多次 RUN cd /path,用 WORKDIR 代替
  • 推荐:/app/usr/src/app

6. COPY ------ 复制文件(推荐)

作用 :从 构建上下文(宿主机) 复制文件/目录到镜像内。
语法

dockerfile 复制代码
COPY <src> <dest>
COPY ["<src>", "<dest>"]  # 路径含空格用此格式

示例

dockerfile 复制代码
COPY hadoop-config /usr/local/hadoop/etc/hadoop
COPY target/app.jar /app/

特点

  • 仅本地文件,不支持 URL、不解压
  • 透明、可缓存、安全(推荐优先用 COPY)

7. ADD ------ 增强复制(慎用)

作用:类似 COPY,但额外支持:

  1. 自动解压 本地 tar.gz 到目标目录
  2. URL 下载文件到目标(不推荐)
    语法
dockerfile 复制代码
ADD <src> <dest>

示例

dockerfile 复制代码
ADD apache-hive-3.1.3-bin.tar.gz /usr/local/  # 自动解压
ADD https://example.com/file.txt /tmp/         # 下载(不推荐)

注意

  • 会破坏缓存、增加镜像体积
  • 仅需解压时用 ADD,其他一律用 COPY

8. RUN ------ 构建时执行命令(核心)

作用 :在构建镜像阶段 执行命令(安装软件、配置、编译等)。
两种格式

(1)Shell 格式(常用)
dockerfile 复制代码
RUN apt update && apt install -y vim
  • 会用 /bin/sh -c 执行
  • 支持管道、变量
(2)Exec 格式(推荐)
dockerfile 复制代码
RUN ["apt", "update"]
  • 不启动 shell,信号传递更好
  • 无环境变量解析

最佳实践(非常重要)

  • 合并多个 RUN(减少镜像层数)
dockerfile 复制代码
RUN apt update && \
    apt install -y openjdk-11-jdk ssh && \
    apt clean && \
    rm -rf /var/lib/apt/lists/*  # 清理缓存,减小体积
  • 每一层尽量清理临时文件、缓存

9. EXPOSE ------ 声明端口

作用声明 容器运行时监听的端口(仅文档作用,不会自动映射 )。
语法

dockerfile 复制代码
EXPOSE <port>[/<protocol>]
EXPOSE 80 443/tcp 9000

要点

  • 只是声明,实际暴露需 docker run -p 主机端口:容器端口
  • 帮助使用者了解端口用途

10. VOLUME ------ 匿名数据卷

作用 :声明容器内的匿名挂载点 ,用于持久化、防止数据丢失。
语法

dockerfile 复制代码
VOLUME ["/path1", "/path2"]
VOLUME /usr/local/hadoop/namenode_dir

效果

  • 运行时自动创建匿名卷
  • 容器删除后,卷数据保留
  • 可被 docker run -v 主机路径:容器路径 覆盖

11. USER ------ 指定运行用户

作用 :指定后续 RUN/CMD/ENTRYPOINT 执行的用户(默认 root)。
语法

dockerfile 复制代码
USER <user>[:<group>]
USER uid[:gid]

示例

dockerfile 复制代码
RUN groupadd -r hadoop && useradd -r -g hadoop hadoop
USER hadoop

安全意义

  • 避免以 root 运行,降低容器逃逸风险

12. CMD ------ 容器默认启动命令(可被覆盖)

作用 :指定 容器启动时默认执行的命令 ,可被 docker run 后面的命令覆盖。
三种格式

dockerfile 复制代码
# 1. Exec 格式(推荐,信号正常传递)
CMD ["executable","param1","param2"]

# 2. Shell 格式
CMD command param1 param2

# 3. 给 ENTRYPOINT 传参
CMD ["param1","param2"]

示例

dockerfile 复制代码
CMD ["hadoop", "namenode", "-foreground"]

规则

  • 一个 Dockerfile 只能有一个 CMD(最后一个生效)
  • docker run 镜像名 命令 覆盖

13. ENTRYPOINT ------ 容器入口点(不易覆盖)

作用 :指定容器真正入口程序 ,通常不希望被覆盖。
两种格式

dockerfile 复制代码
# 1. Exec 格式(推荐)
ENTRYPOINT ["executable", "param1"]

# 2. Shell 格式(不推荐,信号丢失)
ENTRYPOINT command param1

与 CMD 组合(经典用法)

dockerfile 复制代码
ENTRYPOINT ["hadoop"]
CMD ["namenode", "-foreground"]

# 效果:
# docker run my-hadoop → hadoop namenode -foreground
# docker run my-hadoop datanode → hadoop datanode

区别总结

指令 覆盖性 用途
CMD 易被覆盖 默认参数/命令
ENTRYPOINT 不易覆盖(需 --entrypoint) 固定主程序

14. HEALTHCHECK ------ 健康检查

作用 :定义如何检查容器是否正常运行。
语法

dockerfile 复制代码
HEALTHCHECK [选项] CMD <命令>

选项

  • --interval=5s:检查间隔
  • --timeout=3s:超时
  • --retries=3:重试次数
    示例
dockerfile 复制代码
HEALTHCHECK --interval=10s --timeout=3s \
  CMD curl -f http://localhost:9870/ || exit 1

15. ONBUILD ------ 子镜像触发指令

作用 :当前镜像作为基础镜像 被其他 Dockerfile 使用时,才执行的指令。
示例

dockerfile 复制代码
ONBUILD COPY . /app
ONBUILD RUN mvn install

三、COPY vs ADD 对比(必懂)

特性 COPY ADD
本地文件
自动解压 tar
支持 URL ✅(不推荐)
构建缓存
安全性
推荐场景 绝大多数复制 仅需解压

四、CMD vs ENTRYPOINT 对比(必懂)

  • 单独使用 CMD:可被完全覆盖 → 适合默认命令
  • 单独使用 ENTRYPOINT:不易覆盖 → 适合固定主程序
  • ENTRYPOINT + CMD
    • ENTRYPOINT = 主程序
    • CMD = 默认参数
    • docker run 后面参数会替换 CMD → 最灵活

五、多阶段构建(关键优化)

作用 :把「构建环境」和「运行环境」分离,极大减小最终镜像体积
示例(Java 项目)

dockerfile 复制代码
# 阶段1:构建(含 Maven/JDK,体积大)
FROM maven:3.8-openjdk-11 AS builder
WORKDIR /app
COPY . .
RUN mvn clean package -DskipTests

# 阶段2:运行(仅 JRE,体积小)
FROM openjdk:11-jre-slim
WORKDIR /app
# 从上一阶段复制 jar
COPY --from=builder /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

六、Dockerfile 最佳实践(避坑)

  1. 使用官方最小基础镜像(alpine > slim > 普通)
  2. 合并 RUN 指令,减少层数
  3. 安装后立即清理缓存(apt clean、yum clean、rm -rf /var/lib/apt/lists/*)
  4. 优先用 COPY,少用 ADD
  5. 用 WORKDIR 代替 RUN cd
  6. 非必要不 root,使用 USER 切换普通用户
  7. EXPOSE 声明端口,便于使用
  8. VOLUME 声明持久化目录
  9. CMD/ENTRYPOINT 用 Exec 格式(信号正常)
  10. 多阶段构建减小镜像
  11. 标签固定版本,不用 latest
  12. 一行一个 ENV,减少层数

七、完整示例(Hadoop Base)

dockerfile 复制代码
# syntax=docker/dockerfile:1
FROM ubuntu:22.04

LABEL maintainer="admin@example.com"
LABEL version="3.3.4"
LABEL description="Hadoop Base Image"

ENV DEBIAN_FRONTEND=noninteractive
ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
ENV HADOOP_VERSION=3.3.4
ENV HADOOP_HOME=/usr/local/hadoop
ENV PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

# 安装依赖
RUN apt update && \
    apt install -y openjdk-11-jdk-headless ssh pdsh && \
    apt clean && \
    rm -rf /var/lib/apt/lists/*

# 安装 Hadoop
ADD hadoop-${HADOOP_VERSION}.tar.gz /usr/local/
RUN ln -s /usr/local/hadoop-${HADOOP_VERSION} $HADOOP_HOME

# 复制配置
WORKDIR $HADOOP_HOME
COPY hadoop-config etc/hadoop/

# 端口
EXPOSE 9000 9870 8088

# 数据卷
VOLUME ["$HADOOP_HOME/namenode_dir", "$HADOOP_HOME/datanode_dir"]

# 启动脚本
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["bash"]

八、构建与运行

bash 复制代码
# 构建
docker build -t hadoop-base .

# 运行
docker run -itd --name master hadoop-base

如果你需要,我可以根据你 已有的 Hadoop Docker 环境 ,直接给你写一个 可直接使用的 Hive Dockerfile + 构建运行脚本,适配你的集群。需要吗?

相关推荐
AI浩2 小时前
别卷 Prompt 了,2026 年 AI 工程的新战场是 Harness
java·人工智能·prompt
南境十里·墨染春水2 小时前
C++笔记 类模板(面向对象)
开发语言·c++·笔记
小白学大数据2 小时前
攻克滑动拼图反爬:Python 高效爬取网页图片实战案例
开发语言·爬虫·python
煜磊2 小时前
C/C++语言部署安装_C/C++Api学习
开发语言·c++
BPM_宏天低代码3 小时前
【宏天源码】CRM系统的通信中心:邮件/短信/企微消息集成
java·spring boot·freemarker·crm系统
低频电磁之道3 小时前
C++ 源码文本格式规范
开发语言·c++
大尚来也3 小时前
Java反射机制:从底层原理到Spring框架的深度实践
开发语言