Dockerfile 指令

一.Dockerfile概述


1. 什么是 Dockerfile

Dockerfile 是一个用于构建 Docker 镜像的文本文件,其中包含一系列 指令(Instruction)

Docker 引擎会根据这些指令,自上而下、逐条执行 ,最终生成一个不可变的镜像(Image)


2. 镜像、Layer 与容器的关系

  • Docker 镜像(Image) 由多个 只读 Layer 组成
  • 每一条 Dockerfile 指令都会生成一个 Layer
  • Layer 是不可变的增量快照
  • 构建缓存、镜像复用、镜像瘦身,全部基于 Layer 机制

镜像 = 多个只读 Layer 的叠加

容器 = 镜像 + 一层可写层(Container Layer)


3. Dockerfile 到 Layer 的真实映射

示例 Dockerfile:

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


1.1 指令说明

FROM 用于指定当前镜像所基于的基础镜像 ,是 Dockerfile 中的第一条有效指令

一个 Dockerfile 中可以存在多个 FROM(用于多阶段构建)。

基础镜像来源:

  1. Docker 会优先在本地查找基础镜像
  2. 本地不存在则从 Docker Hub 或私有仓库拉取
  3. 镜像不存在则构建失败

1.2 语法格式

Dockerfile 复制代码
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
Dockerfile 复制代码
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]

1.3 参数说明

参数 是否必需 含义 示例 工程建议
FROM 必需 声明新的构建阶段并指定基础镜像 FROM ubuntu 每个 Dockerfile 至少一个
--platform 可选 指定 OS / CPU 架构 linux/amd64、linux/arm64 跨平台 / CI 推荐
<image> 必需 基础镜像名称 openjdkubuntu 使用可信镜像源
:<tag> 推荐 镜像版本标签 :11-jre 不指定则默认最新版本,生产必须指定版本
@<digest> 可选 镜像内容哈希(不可变) @sha256:... 强一致性与安全
AS <name> 可选 构建阶段命名 AS builder 多阶段构建必用

1.4 示例

Dockerfile 复制代码
FROM williamyeh/java8:latest
Dockerfile 复制代码
FROM williamyeh/java8@sha256:174d528516a0eae5c4df69966eeb5e51d7c0dc1a532249af61013953eab1d9f3
Dockerfile 复制代码
FROM --platform=linux/amd64 ubuntu:20.04 AS builder

1.5 多阶段构建(Multi-stage Build)

多阶段构建通过 多个 FROM构建环境运行环境 分离,仅保留最终运行所需的产物,从而:大幅减小镜像体积、降低安全风险、提高可维护性。

❌ 错误示例(单阶段)
dockerfile 复制代码
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"]

问题:

  • Maven 与源码永久存在镜像中
  • 镜像臃肿,攻击面扩大

✅ 正确示例(多阶段构建)
dockerfile 复制代码
# 构建阶段
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"]

最终镜像仅包含 JRE 与 app.jar


2.WORKDIR

2.1 指令说明

WORKDIR指令用于在 Docker 镜像内部设置工作目录 。一旦设置了 WORKDIR,后续的 RUN、CMD、ENTRYPOINT、COPY 和 ADD 这几个指令的执行环境,都会以这个目录为当前起点。

如果一个 Dockerfile 中从未使用过 WORKDIR,那么所有指令的**默认当前目录是根目录 /。


2.2 语法格式

Dockerfile 复制代码
WORKDIR /path/to/workdir

2.3 示例

绝对路径:

Dockerfile 复制代码
FROM ubuntu:22.04
WORKDIR /usr/why/app
RUN pwd
COPY . . 

RUN 和之后的所有命令,都是在 /usr/why/app 下执行 COPY 方法则是将宿主机当前目录下所有文件,复制到 /usr/src/app 文件夹下

相对路径:

Dockerfile 复制代码
FROM ubuntu:22.04
WORKDIR /app
RUN pwd  # 输出:/app
 
WORKDIR why
RUN pwd  # 输出:/app/why
 
WORKDIR test
RUN pwd  # 输出:/app/why/test

设置相对路径后,依次增加追加前置的工作目录


3.COPY

3.1 指令说明

COPY 用于将构建上下文中的文件或目录 复制到镜像中,这些文件或目录会被添加到镜像的文件系统 里,成为镜像的一部分。是最推荐使用的文件复制指令


3.2 语法格式

Dockerfile 复制代码
COPY [--from=<name>] [--chown=<user>:<group>] [--chmod=<perms>] [--link] [--parents] [--exclude=<pattern>] <src>... <dest>
Dockerfile 复制代码
COPY [--from=<name>] [--chown=<user>:<group>] [--chmod=<perms>] [--link] [--parents] [--exclude=<pattern>] ["<src>",... "<dest>"]

3.3 参数说明

参数 作用 典型使用场景 备注
--from=<stage> 从指定构建阶段复制文件 多阶段构建中复制编译产物 多阶段构建核心参数
--chown=<user>:<group> 设置文件属主和属组 非 root 用户运行容器 优于 RUN chown
--chmod=<perms> 设置文件权限 shell 脚本 / 可执行文件 755644
--exclude=<pattern> 排除匹配的文件 精细控制 COPY 内容 类似 .dockerignore,但更局部
--parents 保留源文件目录结构 批量复制并保持路径 适合复制深层文件
--link 使用硬链接代替复制 大文件/不可变文件/构建性能优化 多个 Layer 共享同一文件数据减少 IO、加快构建

3.4 示例

从指定构建阶段复制文件:

Dockerfile 复制代码
COPY --from=builder /build/target/app.jar /app/app.jar

设置文件属主和属组:

Dockerfile 复制代码
COPY --chown=appuser:appgroup app.jar /app/app.jar

设置文件权限:

Dockerfile 复制代码
COPY --chmod=755 start.sh /app/start.sh

排除匹配的文件:

Dockerfile 复制代码
COPY --exclude=*.md --exclude=test/ . /app/

保留源文件目录结构:

Dockerfile 复制代码
COPY --parents src/main/resources/application.yml /app/

使用硬链接代替复制:

注:需开启 DOCKER_BUILDKIT=1

Dockerfile 复制代码
COPY --link app.jar /app/app.jar

4.ADD

4.1 指令说明

ADD指令时一个比COPY 指令功能更宽泛的资源引入指令 ,主要功能为向镜像文件系统中引入新的数据,数据内容可以来自上下文文件远程URL ,并对于某些类型的压缩文件可自动解压


4.2 语法格式

Dockerfile 复制代码
ADD [--keep-git-dir] [--checksum=<checksum>] [--chown=<user>:<group>] [--chmod=<perms>] [--link] [--exclude=<pattern>] <src>... <dest>
Dockerfile 复制代码
ADD [--keep-git-dir] [--checksum=<checksum>] [--chown=<user>:<group>] [--chmod=<perms>] [--link] [--exclude=<pattern>] ["<src>", ... "<dest>"]

4.3 参数说明

参数 作用 典型使用场景 备注
--keep-git-dir 保留 .git 目录 构建时需要 Git 元信息 当 ADD 的源是 Git 仓库 时,保留 .git 目录
--checksum=<checksum> 校验下载内容的完整性 ADD URL 资源 校验通过 URL 下载的文件是否被篡改
--chown=<user>:<group> 设置文件属主/属组 非 root 容器 设置 ADD 后文件的属主和属组
--chmod=<perms> 设置文件权限 脚本 / 可执行文件 755644
--link 使用硬链接而非复制 构建性能优化 多个 Layer 共享同一文件数据减少 IO、加快构建
--exclude=<pattern> 排除匹配文件 精细控制 ADD 内容 在 ADD 时排除指定文件

4.4 示例

下载远程 git 链接并保留 .git 目录:

使用 git 需启用 BuildKit

Dockerfile 复制代码
ADD --keep-git-dir https://github.com/example/repo.git /src

校验下载内容的完整性:

注:url下载的文件不会解压

Dockerfile 复制代码
ADD --checksum=sha256:abc123 https://example.com/app.tar.gz /app/

设置文件属主/属组:

Dockerfile 复制代码
ADD --chown=app:app app.tar.gz /app/

设置文件权限:

Dockerfile 复制代码
ADD --chmod=755 start.sh /app/start.sh

使用硬链接:

Dockerfile 复制代码
ADD --link app.tar.gz /app/

排除匹配文件:

Dockerfile 复制代码
ADD --exclude=*.md --exclude=test/ . /app/

4.5 与 COPY 的对比

对比维度 COPY ADD 备注
基本功能 复制本地文件/目录 复制文件 + 扩展功能 能用 COPY 就用 COPY
是否支持 URL ❌ 不支持 ✅ 支持 url下载的文件不会解压
是否自动解压 ❌ 否 ✅ 是 支持的格式:.tar .tar.gz .tgz .tar.bz2 .tbz2 .tar.xz .txz
是否支持 Git 仓库 ⚠️(BuildKit 支持) 需开启 BuildKit,docker高版本自动开启
行为可预测性 ⭐⭐⭐⭐⭐ ⭐⭐ COPY 更安全
构建可控性 COPY 更易维护
构建缓存稳定性 稳定 不稳定 ADD 易失效
是否推荐用于生产 ✅ 强烈推荐 ⚠️ 谨慎 官方态度
可读性 高(即复制) 低(可能有隐式行为) 团队友好性
安全风险 较高 ADD 可能引入供应链风险

5. MAINTAINER(已废弃)

5.1 指令说明

MAINTAINER 指令设置 Docker 镜像的制作者的个人信息


5.2 语法格式

Dockerfile 复制代码
MAINTAINER <作者信息>

5.3 示例

Dockerfile 复制代码
MAINTAINER xiaoyangzi

MAINTAINER xiaoyangzi <xiaoyangzi@email.com>

6.LABEL

6.1 指令说明

LABEL指令为镜像添加元数据 (metadata)的指令。这些元数据以键值对(key-value) 的形式存在,用于描述镜像的作者、版本、用途、来源 等信息。

LABEL 不会影响镜像的构建流程和运行行为,其主要作用是信息标注与管理。


6.2 语法格式

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

6.3 示例

设置制作人信息:

Dockerfile 复制代码
LABEL maintainer="xiaoyangzi <xiaoyangzi@email.com>"

设置多个标签:

Dockerfile 复制代码
LABEL maintainer="xiaoyangzi <xiaoyangzi@email.com>" \
      version="1.0" \
      description="测试镜像"

7.ENV

7.1 指令说明

ENV 指令用于在 Docker 镜像构建过程中设置环境变量 。这些变量会被设置在由该 Dockerfile 构建出的镜像环境里。环境变量可以在Dockerfile的许多指令中使用,包括但不限于:WORKDIR、ENV、LABEL、RUN、CMD、ENTRYPOINT、COPY、ADD等。

当以某个镜像运行容器时,使用ENV设置的环境变量将持续存在。可以使用docker inspect 查看这些值,并使用 docker run --env <key>=<value> 来更改它们。


7.2 语法格式

常用形式:

Dockerfile 复制代码
ENV <key>=<value> [<key>=<value>...]

一对一形式(不推荐):

Dockerfile 复制代码
ENV <key> <value>

在 Dockerfile 中,环境变量的引用有两种方式:$variable_name${variable_name}

  • 基本引用使用 \$variable_name 时,变量名后面不能紧跟字母、数字、下划线,需以空格、换行、特殊字符等来表示变量名的结束。如果变量名后面需要紧接着其他字母数字下划线,就必须使用${variable_name}形式来明确变量名的范围。
  • 括号形式使用 \${variable_name} 可以明确指定变量名的边界,这样可以在字符串中直接嵌入变量而不会引起歧义。
  • 转义 :如果需要使用$字符本身,而不是作为变量引用,可以用\$来转义。

7.3 示例

一对一形式:

Dockerfile 复制代码
ENV NAME "XYZ"

常用形式:

Dockerfile 复制代码
ENV NAME="XYZ" \
    AGE=18 \
    gender=male

使用示例:

Dockerfile 复制代码
ENV NAME XYZ
CMD echo "Hello, $NAME"
CMD echo "Hello, ${NAME}"

8.ARG

8.1 指令说明

ARG(Argument)是 Dockerfile 中用于定义构建阶段变量的指令。该变量仅在镜像构建过程中 可用,用于向构建过程传递参数,而不会在容器运行时自动保留

ARG 的主要作用是提高 Dockerfile 的可配置性与复用性。


8.2 语法格式

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

一个 ARG 变量从它被定义的那一行开始才生效,在这行之前使用它是无效的。

在使用 docker build 命令构建镜像时,使用 --build-arg 标志来为 ARG 变量赋值。

bash 复制代码
docker build --build-arg <变量名>=<值> --build-arg <变量名>=<值> .

8.3 示例

定义变量

Dockerfile 复制代码
ARG APP_ENV=dev
ARG APP_VERSION
ARG BUILD_TIME

使用变量:

与ENV使用方法相似:

Dockerfile 复制代码
RUN echo "Environment: $APP_ENV"
RUN echo "Version: ${APP_VERSION}"

同样可以使用shell方式 ${APP_VERSION:-v0.0.1},如果 APP_VERSION 未被定义则默认 v0.0.1

Dockerfile 复制代码
RUN echo "Environment: $APP_ENV"
RUN echo "Version: ${APP_VERSION:-v0.0.1}"

构建时传参:

bash 复制代码
docker build \
  --build-arg APP_ENV=prod \
  --build-arg APP_VERSION=1.2.3 \
  --build-arg BUILD_TIME=2025-01-01 \
  .

8.4 ENV和ARG的区别

维度 ARG ENV
生命周期 构建阶段(ARG在构建阶段可传参改变) 构建 + 容器运行阶段(容器期可用)
可否在容器运行时访问
默认值 Dockerfile 内可定义 Dockerfile 内可定义
多阶段构建作用域 每个阶段需重新声明,或者在 FROM 前全局声明 继承上阶段,可重新定义进行覆盖
安全性 不安全,可能出现在镜像历史 同样不安全,存在于镜像元数据
使用场景 动态构建参数、版本号、条件编译 容器运行期配置、路径、端口、标识等

联合使用 ARG 和 ENV

Dockerfile 复制代码
ARG APP_ENV=dev
ENV APP_ENV=${APP_ENV}
RUN echo "Build environment: $APP_ENV"

注:ARG的只会被 ENV定义的值覆盖:

Dockerfile 复制代码
FROM ubuntu
ARG NAME=xyz
ENV NAME=why
RUN echo $NAME
Dockerfile 复制代码
FROM ubuntu
ENV NAME=why
ARG NAME=xyz
RUN echo $NAME

两个的NAME的输出均为 why


8.5 内置 ARG 变量

在 Dockerfile 里,有一些内置(预定义)ARG 变量,主要是为了支持构建阶段的一些特定场景。它们不是所有变量都自动存在,而是 Docker 官方定义的、可以直接使用或覆盖的构建参数。

变量名 说明 可用阶段
BUILD_DATE 构建时间(通常用来标记镜像构建时间) 构建阶段
VCS_REF Git 提交 hash(可选,用于标记源代码版本) 构建阶段
TARGETPLATFORM 当前构建的平台(例如 linux/amd64 构建阶段
BUILDPLATFORM 执行构建的宿主平台(例如 linux/amd64 构建阶段
TARGETOS 构建目标操作系统(例如 linuxwindows 构建阶段
TARGETARCH 构建目标 CPU 架构(例如 amd64arm64 构建阶段
TARGETVARIANT 构建目标架构的变体(例如 v7 构建阶段

9. RUN

9.1 指令说明

RUN指令用于在镜像构建阶段 执行命令,并将执行结果提交为一个新的镜像层(image layer)。

RUN = 构建时执行命令 + 固化结果到镜像中


9.2 语法格式

Shell 格式:

会启动 shell 来执行命令,通常是 /bin/sh, 实际执行时会包装为 /bin/sh -c ""

注:支持变量替换,通配符,管道,逻辑运算符等操作,可使用 $HOME、*.txt、|、&&等功能。

Dockerfile 复制代码
RUN [OPTIONS] <command> ...
Exec 格式:

使用一个数组来明确指定要运行的可执行文件路径以及它的参数。

Docker 会直接调用这个可执行文件,而不通过任何默认的 Shell。

Dockerfile 复制代码
RUN [OPTIONS] [ "<command>", ... ]

注:环境变量不会自动展开,通配符、管道和逻辑运算符无效,如不能使用 $HOME、*.txt、|、&&等功能。

如果既想使用 Exec 格式,又需要 Shell 的特性(比如变量替换),你必须显式地调用一个 Shell:

Dockerfile 复制代码
RUN ["/bin/bash", "-c", "echo $HOME && rm -rf *.log"]

两种形式对比

格式类型 Dockerfile 写法 是否启动 shell 变量展开 逻辑运算符 是否支持管道 是否支持重定向 是否支持 glob 适合复杂逻辑
Shell 格式 RUN echo hello ✅ 是(/bin/sh -c) ✅ 非常适合
Exec 格式 RUN ["echo","hello"] ❌ 否 ❌ 不适合
OPTIONS 参数:

以下参数仅在 BuildKit 启用时可用:

参数 作用对象 解决什么问题 常见取值 / 类型 是否进入最终镜像 典型使用场景 关键注意点
--mount 文件系统 在构建阶段临时挂载资源 type=cache 构建缓存 type=bind 绑定主机或上下文文件 type=secret 构建期密钥 type=ssh 构建期 SSH 访问 ❌ 不会 依赖缓存 私有仓库凭证 SSH 拉代码 仅当前 RUN 有效 构建结束即销毁
--network 网络 控制构建期联网行为 default 默认网络 none 完全断网 host 使用宿主机网络 ❌ 不会 禁止隐式下载 可复现构建 none 可显著提升安全性
--security 安全策略 放宽构建沙箱限制 sandbox(默认) insecure 放宽安全限制 ❌ 不会 私有仓库 token、npm / pip 私服凭证、SSH key CI 中慎用
--device 硬件设备 构建期访问宿主设备 /dev/kvm /dev/nvidia0 ❌ 不会 QEMU / GPU 构建 极少数场景需要

9.3 示例

shell 形式:

Dockerfile 复制代码
RUN echo "Hello Docker"

Exec 形式:

Dockerfile 复制代码
RUN ["echo", "Hello Docker"]

合并 RUN:

Dockerfile 复制代码
RUN apt-get update \
 && apt-get install -y curl \
 && rm -rf /var/lib/apt/lists/*

使用变量:

Dockerfile 复制代码
ARG APP_VERSION
RUN echo "version=$APP_VERSION"

构建缓存:

Dockerfile 复制代码
RUN --mount=type=cache,target=/root/.cache \
    pip install -r requirements.txt

绑定主机或上下文文件:

Dockerfile 复制代码
RUN --mount=type=bind,source=requirements.txt,target=/tmp/req.txt \
    pip install -r /tmp/req.txt

构建期密钥:

Dockerfile 复制代码
RUN --mount=type=secret,id=mytoken \
    cat /run/secrets/mytoken

构建命令:

bash 复制代码
docker build --secret id=mytoken,src=token.txt .

构建期 SSH 访问:

Dockerfile 复制代码
RUN --mount=type=ssh git clone git@github.com:private/repo.git

构建命令:

bash 复制代码
docker build --ssh default .

在构建阶段禁止联网

Dockerfile 复制代码
RUN --network=none go build

控制构建阶段的安全策略:

Dockerfile 复制代码
RUN --security=insecure some-command

临时暴露设备给 RUN:

Dockerfile 复制代码
RUN --device=/dev/kvm make test

组合使用:

Dockerfile 复制代码
RUN --mount=type=cache,target=/root/.cache \
    --mount=type=secret,id=npm_token \
    --network=default \
    npm install

10.ENTRYPOINT

10.1 指令说明

ENTRYPOINT 用于定义容器启动时的固定入口程序 。无论用户在 docker run 后面传什么,ENTRYPOINT 都会被执行

当使用 docker run 命令启动一个基于该镜像的容器时,Docker 守护进程会执行 ENTRYPOINT 所指定的命令。这个命令会成为容器的"主进程"(PID 1)。


10.2 语法格式

Exec 格式:

使用字符串数组组成命令,且必须是双引号。

Dockerfile 复制代码
ENTRYPOINT ["executable", "param1", "param2"]
Shell 格式:

会启动 shell 来执行命令,通常是 /bin/sh, 实际执行时会包装为 /bin/sh -c "<command>"

Dockerfile 复制代码
ENTRYPOINT command param1 param2

两者区别:

对比维度 Exec 格式 Shell 格式
Dockerfile 写法 ENTRYPOINT ["nginx"] ENTRYPOINT nginx
是否启动 shell ❌ 否 ✅ 是(/bin/sh -c
实际执行模型 直接 execve 程序 /bin/sh -c "cmd"
PID 1 是谁 应用程序本身 /bin/sh
是否直接接收 SIGTERM ✅ 是 ❌ 否(可能被吞)
是否支持优雅停止 ✅ 是 ❌(不可靠)
信号传递可靠性 ⭐⭐⭐⭐⭐
容器停止行为 可预测、可控 不稳定
是否支持 $VAR
是否支持 `&& / `
是否支持重定向 >
是否支持管道
是否支持通配符
是否支持 shell 内建
CMD 是否作为参数 ✅(强) ❌(语义混乱)
docker run 参数追加 ⚠️ 不直观
工程可维护性 ⭐⭐⭐⭐⭐ ⭐⭐
生产环境推荐度 ⭐⭐⭐⭐⭐
替换 ENTRYPOINT:

ENTRYPOINT 一般是不可变的,但是可以在启动容器时使用 --entrypoint 参数覆盖

bash 复制代码
docker run --entrypoint bash image

如果我们采用 --entrypoint 覆盖了 ENTRYPOINT,则 Dockerfile 中作为 ENTRYPOINT 参数的原始 CMD 命令会被忽略


10.3 示例

Exec 格式:

Dockerfile 复制代码
ENTRYPOINT ["python"]
docker run 命令 实际执行
docker run image app.py python app.py

Shell 格式:

Dockerfile 复制代码
ENTRYPOINT nginx -g "daemon off;"

与CMD组合执行:

Dockerfile 复制代码
ENTRYPOINT ["python"]
CMD ["app.py"]
docker run 命令 实际执行
docker run image python app.py
docker run image other.py python other.py

11.CMD

11.1 指令说明

CMD 用于为容器提供默认启动命令或默认参数 。它只在容器启动时执行(docker run),不会在构建 docker build 阶段执行。

Dockerfile 中只能有一个 CMD,如果有多个 CMD 指令,也只有最后一个会生效,并且可以被运行时参数覆盖:

Dockerfile 复制代码
CMD ["echo", "hello"]
bash 复制代码
docker run image echo world

echo hello 会被 echo world 覆盖,只会输出 world。


11.2 语法格式

Shell 格式:

会启动 shell 来执行命令,通常是 /bin/sh, 实际执行时会包装为 /bin/sh -c "<command>"

Dockerfile 复制代码
CMD command param1 param2
Exec 格式:

使用字符串数组组成命令,且必须是双引号。

Dockerfile 复制代码
CMD ["executable","param1","param2"]
为 ENTRYPOINT 提供默认参数:

和 ENTRYPOINT 指令配合使用,CMD 的作用不再是直接运行一个命令,而是为 ENTRYPOINT 指定的命令提供一组默认的参数。

Dockerfile 复制代码
CMD ["param1","param2"]

两者区别:

对比维度 Exec 格式 Shell 格式 参数格式(配合 ENTRYPOINT)
Dockerfile 写法 CMD ["executable","arg1","arg2"] CMD command arg1 arg2 ENTRYPOINT ["exe"] CMD ["arg1","arg2"]
是否启动 shell ❌ 否 ✅ 是(/bin/sh -c ❌ 否
实际执行模型 直接 execve /bin/sh -c "cmd" execve(ENTRYPOINT + CMD)
PID 1 是谁 可执行程序 /bin/sh ENTRYPOINT 程序
是否接收 SIGTERM ❌(不可靠)
是否支持优雅停止
是否支持 $VAR 有在 ENTRYPOINT 本身是 shell 时才可以。
是否支持 `&& / `
是否支持重定向 > 有在 ENTRYPOINT 本身是 shell 时才可以。
是否支持 管道 有在 ENTRYPOINT 本身是 shell 时才可以。
是否支持通配符 有在 ENTRYPOINT 本身是 shell 时才可以。
CMD 是否可被覆盖 ✅(整体替换) ✅(整体替换) ✅(仅替换参数
docker run 参数行为 覆盖整个 CMD 覆盖整个 CMD 追加 / 替换参数
与 ENTRYPOINT 协作能力 一般 ⭐⭐⭐⭐⭐
行为可预测性 ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐
生产环境推荐度 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
典型使用场景 固定启动命令 临时调试 官方镜像、服务型容器

11.3 示例

Exec 形式:

Dockerfile 复制代码
CMD ["nginx", "-g", "daemon off;"]

Shell 形式:

Dockerfile 复制代码
CMD nginx -g "daemon off;"

配合 ENTRYPOINT:

Dockerfile 复制代码
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
docker run 实际执行
docker run image nginx -g daemon off;
docker run image -t nginx -t

RUN、ENTRYPOINT、CMD 区别

对比维度 RUN ENTRYPOINT CMD
所属阶段 构建阶段(build time) 运行阶段(run time) 运行阶段(run time)
核心作用 构建镜像内容 定义容器的固定入口程序 定义默认启动命令或参数
是否生成镜像层 ✅ 每条 RUN 生成一层
是否在构建时执行
是否在容器启动时执行
是否必须存在
是否只能有一条 ✅(最后一条生效) ✅(最后一条生效)
是否支持 Shell 格式 ✅(不推荐) ✅(不推荐)
是否支持 Exec 格式 ✅(强烈推荐) ✅(推荐)
是否启动 shell Shell 格式会 Shell 格式会 Shell 格式会
是否支持 $VAR && ` > *` ✅(Shell) ❌(Exec) / ✅(Shell) ❌(Exec) / ✅(Shell)
是否成为 PID 1 取决于是否有 ENTRYPOINT
是否直接接收 SIGTERM ✅(Exec) ❌ / ✅(取决于 ENTRYPOINT)
是否支持优雅停止 ✅(Exec) 依赖 ENTRYPOINT
是否可被 docker run 覆盖 ⚠️(需 --entrypoint
docker run 参数行为 无意义 参数会追加 覆盖或作为参数
与 ENTRYPOINT 的关系 定义"是什么程序" 定义"默认参数"
典型使用次数 多次 1 次 1 次
生产环境重要性 ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐

12.EXPOSE

12.1 指令说明

EXPOSE 用于声明容器在运行时"预期会监听"的端口 。可以理解为一种文档化的端口声明 + 元数据提示,而不是网络规则。

EXPOSE 指令本身只是声明端口,不会真的打开端口,也不会创建防火墙规则、让宿主机能访问、自动映射端口。


12.2 语法格式

默认协议是 tcp

Dockerfile 复制代码
EXPOSE <port> [<port>/<protocol>...]

12.3 示例

声明端口:

Dockerfile 复制代码
EXPOSE 80
EXPOSE 80/tcp
EXPOSE 53/udp
EXPOSE 80 443

声明多个端口:

Dockerfile 复制代码
EXPOSE 80 443 9000

12.4 启动示例

-p 映射启动:

bash 复制代码
docker run -d -p 80:7000 -p 8080:8080/udp image

-P 启动:

bash 复制代码
docker run -P image

会自动映射所有 EXPOSE 的端口到宿主机的一个高端口(通常从 32768 开始)


13.VOLUME

13.1 指令说明

VOLUME 用于声明容器中的某个路径是持久化数据目录 。这个目录的数据不应该随着容器销毁而消失。

工作原理:

  1. Docker 会自动在宿主机上生成一个随机名字的目录,这个目录被称为"匿名卷"。(默认在 /var/lib/docker/volumes/ 下,可以通过 docker inspect 查看容器元数据找到)。
  2. 将这个主机上的随机目录,与容器内部的 VOLUME 目录绑定起来
  3. 任何写入容器内 VOLUME 目录的文件,实际上都被保存在了主机上的那个随机目录里。
  4. 容器被删除后,宿主机上的随机目录及其里面的数据默认不会被删除

13.2 语法格式

单路径模式:
Dockerfile 复制代码
VOLUME ["/data"]
数组模式:
Dockerfile 复制代码
VOLUME ["/var/lib/mysql", "/var/log/mysql"]

13.3 示例

1. VOLUME 示例

该形式会在宿主机 Docker volume 内部目录 /var/lib/docker/volumes/ 下创建一个随机名称的目录与镜像目录挂载

Dockerfile 复制代码
VOLUME ["/data"]

2.-v 示例
宿主机指定 volume 目录名称:

该形式会在宿主机 Docker volume 内部目录 /var/lib/docker/volumes/ 下创建一个 mydata 名称的目录与镜像目录挂载

bash 复制代码
docker run -v mydata:/data image

宿主机指定绝对路径:

该形式会在宿主机指定的绝对路径目录与镜像目录挂载

bash 复制代码
docker run -v /host/data:/data image

3.--mount type=volume 示例

该形式会在宿主机 Docker volume 内部目录 /var/lib/docker/volumes/ 下创建一个 mydata 名称的目录与镜像目录挂载

bash 复制代码
docker run --mount type=volume,source=mydata,target=/data image

4.--mount type=bind 示例:

该形式会在宿主机指定的绝对路径目录与镜像目录挂载

bash 复制代码
docker run --mount type=bind,source=/host/data,target=/data image

13.4 VOLUME、-v、--mount 区别

以下出现的 volume 目录为宿主机Docker目录下,默认:/var/lib/docker/volumes/

对比维度 VOLUME (Dockerfile) -v --mount type=volume --mount type=bind
定义位置 Dockerfile docker run / Compose docker run / Compose docker run / Compose
生效时机 容器启动时 容器启动时 容器启动时 容器启动时
目的 声明容器内持久化目录 挂载 volume 或宿主机目录 明确挂载 volume 挂载宿主机目录
是否创建 volume ✅ 自动匿名 volume ✅ 可创建 ✅ 可创建 ❌(只能挂已有宿主机目录)
容器路径 ✅ 必须 ✅ 必须 ✅ 必须 ✅ 必须
宿主机路径 / source ❌ 无法指定 ✅ 可指定 ✅ volume 名称 ✅ 宿主机目录
数据实际存储位置 宿主机 Docker volume 内部目录 /var/lib/docker/volumes/... 宿主机 Docker volume 内部目录 /var/lib/docker/volumes/...或宿主机指定目录 宿主机 Docker volume 内部目录 /var/lib/docker/volumes/... 宿主机指定目录
是否可控
是否影响镜像层 ✅ 切断容器目录与镜像层
工程实践推荐度 ⚠️ 官方镜像兜底 ⚠️ 快捷方案 ✅ 工程首选 ✅ 生产挂宿主机首选

14.SHELL

14.1 指令说明

SHELL 的作用只有一个:修改后续 Shell Form 指令所使用的"默认 shell"

它影响的是这些以 shell 方式执行的指令格式:

Dockerfile 复制代码
RUN <string>
CMD <string>
ENTRYPOINT <string>

默认情况下:

  • 在 Linux 容器中,默认是 ["/bin/sh", "-c"]
  • 在 Windows 容器中,默认是["cmd", "/S", "/C"]

例如当执行 RUN echo "Hello World" 时:

  • Docker 在 Linux 底层实际上执行的是:/bin/sh -c "echo \"Hello World\"
  • Docker 在 Windows 底层实际上执行的是:cmd /S /C "echo \"Hello World\"

每个 SHELL 指令都会覆盖所有先前的 SHELL 指令,并影响所有后续指令

注意:SHELL 不影响 Exec 形式的指令

14.2 语法格式

Dockerfile 复制代码
SHELL ["executable", "parameters"]

参数说明:

  • executable :要使用的 Shell 程序的完整路径。如 /bin/bash、powershell 等。
  • parameters :传递给该 Shell 程序的参数。如 -c、 -Command等。

14.3 示例

Bash 常用模式:
Dockerfile 复制代码
SHELL ["/bin/bash", "-c"]
Bash 严格模式:
Dockerfile 复制代码
SHELL ["/bin/bash", "-euxo", "pipefail", "-c"]

参数说明:

  • -e:出错即失败。
  • -u:未定义变量报错。
  • -x:打印执行命令。
  • pipefail:管道中任意失败即失败。
  • -c:后面接需要执行的命令。
Windows 默认(cmd):
Dockerfile 复制代码
SHELL ["cmd", "/S", "/C"]

参数说明:

  • /S改变 /C 后面命令字符串的解析规则,防止复杂命令容易被错误拆分或转义失败
  • /C:执行完后面的命令字符串后立即退出。
Windows PowerShell:
Dockerfile 复制代码
SHELL ["powershell", "-Command"]
PowerShell 严格模式:
Dockerfile 复制代码
SHELL ["powershell", "-NoProfile", "-Command", "$ErrorActionPreference = 'Stop';"]

参数说明:

  • -NoProfile启动 PowerShell 时不加载任何用户或系统 Profile 脚本。使Docker 构建要 可重复、可预测。
  • -Command:后面的字符串就是要执行的命令。
  • $ErrorActionPreference = 'Stop';任何非终止性错误,都会升级为终止性错误,报错立即停止执行

15.USER

15.1 指令说明

USER 指令用于指定后续 Dockerfile 指令以及容器运行时所使用的用户和用户组默认情况下,容器的运行身份为 root 用户USER指令可以修改后续的 RUN、CMD、 ENTRYPOINT 等指令以哪个用户的权限来执行。

注:可以在一个 Dockerfile 中使用多个 USER 来切换身份


15.2 语法格式

必须在系统 /etc/passwd 文件中定义的用户名/组

用户名/用户组名:
Dockerfile 复制代码
USER <user>[:<group>]
用户ID/组ID:
Dockerfile 复制代码
USER UID[:GID]

15.3 示例

创建用户并使用:

Dockerfile 复制代码
# 创建一个用户组,指定组id为 1001,组名为 appgroup
# 并创建一个系统用户 appuser,指定用户id为 1001,并加入 appgroup 组
RUN groupadd -g 1001 appgroup && useradd -r -u 1001 -g appgroup appuser

WORKDIR /app
# 将宿主机构建上下文中的 app 文件复制到容器内(COPY 后文件一定是 root 拥有的,这是后面要 chown 的原因。)
COPY app.sh /app/app.sh
# 修改 /app 目录的所有权,并赋予 app.sh 可执行权限
RUN chown -R appuser:appgroup /app && chmod +x /app/app.sh
# 切换用户
USER appuser
# 执行 app.sh 文件
CMD ["/app/app.sh"]

切换用户:

Dockerfile 复制代码
FROM ubuntu:22.04
RUN whoami
 
RUN useradd -r -u 1001 newuser
USER newuser
RUN whoami
 
USER root
RUN whoami

16.HEALTHCHECK

16.1 指令说明

HEALTHCHECK指令后定义一个命令,Docker 会周期性执行它,判断容器是否健康。

容器健康状态有三种:

  • healthy:健康
  • unhealthy:不健康
  • starting:刚启动,命令还未判断

16.2 语法格式

检查容器的健康状况:
Dockerfile 复制代码
HEALTHCHECK [OPTIONS] CMD command

参数说明:

  • --interval=DURATION两次健康检查命令之间的时间间隔。 (默认: 30s)
  • --timeout=DURATION单次健康检查命令的执行超时时间,如果超时则视为失败。 (默认: 30s)
  • --start-period=DURATION容器启动后的宽限期,在这段时间内,即使健康检查失败,也不会标记容器为 unhealthy。 (默认: 0s)
  • --start-interval=DURATION :这是 Docker 20.10+ 新增参数(比 --interval 更精细
    用于在启动期覆盖 --interval 的间隔时间 (默认: 5s`)
  • --retries=N连续失败多少次,才把容器标记为 unhealthy (默认: 3 次)
禁用从基础镜像继承而来的任何健康检查功能:

用于清理基础镜像继承的 HEALTHCHECK

Dockerfile 复制代码
HEALTHCHECK NONE

16.3 示例

  • 检查成功 → 返回 0 → healthy
  • 检查失败 → 执行 exit 1 → 返回非 0 → unhealthy
16.3.1 curl 方式

两次健康检查命令之间的时间间隔:

Dockerfile 复制代码
HEALTHCHECK --interval=10s CMD curl -f http://localhost:8080/health || exit 1

设置单次检查超时时间:

Dockerfile 复制代码
HEALTHCHECK --timeout=5s CMD curl -f http://localhost:8080/health || exit 1

容器启动后的宽限期:

Dockerfile 复制代码
HEALTHCHECK --start-period=20s CMD curl -f http://localhost:8080/health || exit 1

设置启动器时间间隔:

容器启动前 30 秒,每 5 秒执行一次检查;容器启动后每 30 秒执行一次检查

Dockerfile 复制代码
HEALTHCHECK --start-period=30s --start-interval=5s --interval=30s CMD curl -f http://localhost:8080/health || exit 1

设置连续失败多少次,把容器标记为 unhealthy:

Dockerfile 复制代码
HEALTHCHECK --retries=5 CMD curl -f http://localhost:8080/health || exit 1

综合示例:

Dockerfile 复制代码
HEALTHCHECK \
  --interval=30s \
  --timeout=5s \
  --start-period=20s \
  --start-interval=5s \
  --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1

16.3.2 TCP 端口检查

使用 Netcat 命令尝试是否能够连接,可以的话则为成功

  • 优点 :快速、无数据发送,适合数据库/Redis/MQ 等服务的端口探测
  • 缺点只能判断端口是否监听,不能判断协议/服务是否真正可用
Dockerfile 复制代码
HEALTHCHECK CMD nc -z localhost 3306 || exit 1

参数说明:

  • nc: Netcat 工具,万能网络工具
  • -z: 端口扫描/探测模式,不发送数据,只尝试建立 TCP 连接

16.3.3 命令/进程检查

扫描 /proc 目录,如 Linux 内核维护的 /proc/[pid]/cmdline,pgrep 遍历进程列表,查找匹配 myservice 的进程

Dockerfile 复制代码
HEALTHCHECK CMD pgrep myservice || exit 1

参数说明:

  • pgrep:Process GREP 的缩写,用于在 Linux 系统中 查找正在运行的进程。
  • myservice:进程名或部分匹配字符串。

pgrep 常用参数:

参数 含义 示例
-x 精确匹配命令名 pgrep -x nginx
-u <user> 只匹配特定用户 pgrep -u appuser myservice
-q 静默模式,只返回状态码 pgrep -q myservice
-f 匹配完整命令行 pgrep -f "python /app/app.py"

16.3.4 文件/目录检查
Dockerfile 复制代码
HEALTHCHECK CMD test -f /app/config.yaml || exit 1

参数说明:

  • test:内置 shell 命令,用于检查文件/字符串/数字等条件。
  • -f:判断目标是否存在且是普通文件(不是目录、链接、设备等)。

test 扩展用法:

参数 含义 示例
-f 判断是否普通文件 test -f /app/config.yaml
-d 判断是否目录 test -d /app/logs
-e 判断文件或目录是否存在 test -e /app/config.yaml
-r 文件是否可读 test -r /app/config.yaml
-w 文件是否可写 test -w /app/config.yaml
-x 文件是否可执行 test -x /app/app

16.3.5 自定义脚本(复杂逻辑)
Dockerfile 复制代码
HEALTHCHECK CMD /app/healthcheck.sh

17.ONBUILD

17.1 指令说明

ONBUILD = 构建触发器 ,它不会在当前镜像构建时执行,而是在基于当前镜像的子镜像构建时触发执行。

  • 当前 Dockerfile:定义基础镜像
  • ONBUILD:给"使用这个镜像作为父镜像的 Dockerfile"留的指令
  • 构建此镜像时(父镜像)不执行。
  • 基于父镜像构建子镜像时才执行。

ONBUILD 指令会在子镜像构建时首先执行,但严格来说是"在父镜像的 ONBUILD 队列中按顺序执行,紧接着子镜像自己的第一条指令之前。


17.2 语法格式

Dockerfile 复制代码
ONBUILD <INSTRUCTION>

<instruction> 可以是 Dockerfile 中的常用指令,例如:COPY、ADD、RUN、ENV 等。(不支持某些特殊指令,如 FROM、ONBUILD 自己)


17.3 示例

17.3.1 构建示例

构建父镜像:

Dockerfile 复制代码
# 基础镜像
FROM ubuntu:22.04
ONBUILD COPY . /app
ONBUILD RUN echo "Build triggered in child"

构建这个镜像时:

  • ONBUILD COPY 和 ONBUILD RUN 不会执行
  • 镜像构建完成 → 生成一个带有"触发器"的镜像

构建子镜像:

Dockerfile 复制代码
FROM mybaseimage:latest

构建子镜像时:

  • Docker 会自动执行父镜像的 ONBUILD 指令
  • COPY . /app → 将子镜像上下文复制到 /app
  • RUN echo ... → 执行命令
  • 然后执行子镜像自己的 Dockerfile 指令

17.3.2 典型使用场景:

父镜像:

Dockerfile 复制代码
# python:3.9-slim 的 Dockerfile
ONBUILD COPY requirements.txt /app/
ONBUILD RUN pip install -r /app/requirements.txt

子镜像:

Dockerfile 复制代码
FROM python:3.9-slim
COPY . /app

18.STOPSIGNAL

18.1 指令说明

当执行 docker stop 时,Docker 发送给容器主进程(PID 1)的 Unix 信号。

注:由于 STOPSIGNAL 是对 PID 1 的主进程有效,所以在 SHELL 格式的命令时 PID 1 是 /bin/sh,如下 myapp 是子进程,STOPSIGNAL 发给 sh,sh 不一定转发信号。从而导致 STOPSIGNAL 失效

Dockerfile 复制代码
CMD myapp
ENTRYPOINT myapp
写法 PID 1 是谁 STOPSIGNAL 是否生效
ENTRYPOINT Exec 应用进程
CMD Exec 应用进程
ENTRYPOINT Shell /bin/sh ❌(通常)
CMD Shell /bin/sh ❌(通常)

18.2 语法格式

Dockerfile 复制代码
STOPSIGNAL signal

支持两种写法:

Dockerfile 复制代码
# 信号名形式
STOPSIGNAL SIGTERM
# 编号形式
STOPSIGNAL 15

等同于在 docker run 或 docker create 时指定--stop-signal=:

bash 复制代码
docker run --stop-signal=SIGINT my-image

docker create --stop-signal SIGTERM my-image

常用 Unix 信号表

信号名 编号 含义 默认行为 常见用途
SIGTERM 15 请求终止 终止进程 Docker 默认 stop 信号
SIGINT 2 中断 终止进程 Ctrl+C、CLI 程序
SIGQUIT 3 退出并生成 core 终止 + core Nginx 优雅退出
SIGKILL 9 强制杀死 立即终止 无法捕获,兜底
SIGHUP 1 挂起/重载 终止或重载 重新加载配置
SIGUSR1 10 用户自定义 忽略 应用自定义控制
SIGUSR2 12 用户自定义 忽略 应用自定义控制
SIGPIPE 13 管道破裂 终止 写入已关闭管道
SIGCHLD 17 子进程退出 忽略 进程回收
SIGALRM 14 定时器超时 终止 超时控制

18.3 示例

18.3.1 SIGTERM:

请求进程正常退出(可捕获、可处理),docker stop 默认发送

Dockerfile 复制代码
STOPSIGNAL SIGTERM
ENTRYPOINT ["myapp"]

18.3.2 SIGINT:

CLI 工具、通过命令行直接运行、执行完就退出的程序、运行时占着终端、用户能实时看到输出的程序

Dockerfile 复制代码
STOPSIGNAL SIGINT
CMD ["ffmpeg", "-i", "a.mp4", "b.mp4"]
Dockerfile 复制代码
STOPSIGNAL SIGINT
CMD ["node", "server.js"]
Dockerfile 复制代码
STOPSIGNAL SIGINT
CMD ["python", "server.py"]

18.3.3 SIGQUIT

Nginx 优雅退出:

Dockerfile 复制代码
STOPSIGNAL SIGQUIT

18.3.4 SIGKILL

立即杀死进程,不要在 Dockerfile 里用 STOPSIGNAL SIGKILL

bash 复制代码
docker kill mycontainer

18.3.5 SIGHUP

重新加载配置 / 重启逻辑

bash 复制代码
docker kill -s HUP nginx-container

等价于:

bash 复制代码
nginx -s reload

用 Bash 模拟配置重载:

bash 复制代码
#!/bin/sh

reload() {
  echo "Reload config at $(date)"
}

trap reload HUP

echo "App started, PID $$"

while true; do
  sleep 5
done
Dockerfile 复制代码
FROM alpine
COPY app.sh /app.sh
RUN chmod +x /app.sh
CMD ["/app.sh"]
bash 复制代码
docker run -d --name hup-demo hup-image
docker kill -s HUP hup-demo

输出:

复制代码
Reload config at 2026-01-08 ...

三.docker build 构建命令

1. docker build 介绍

docker build 是 Docker 客户端用于根据 Dockerfile 构建镜像(Image)的命令。
镜像是不可变的只读模板,容器是镜像的运行实例。docker build 只负责生成镜像,不运行任何容器。


2.docker build 的基本语法

2.1 语法格式

bash 复制代码
docker build [OPTIONS] PATH | URL | -

关键组成部分

部分 含义
OPTIONS 构建参数
PATH PATH 指的是构建上下文路径, 可以是相对路径或绝对路径
URL Git 仓库或者 HTTP(s) 资源
- 从 stdin 读取 Dockerfile

2.2 OPTIONS 可用参数列表

参数 简述 用法 / 示例 备注
-t, --tag 给生成的镜像打标签 docker build -t myapp:1.0 . 可指定多个标签,多标签镜像共享同一镜像 ID,如果不指定标签,则会生成一个随机镜像id,而不会有名字
-f, --file 指定 Dockerfile 路径 docker build -f Dockerfile.prod . 可以是相对路径或绝对路径(如果不指定,则会在构建上下文的根目录寻找Dockerfile)
--build-arg 构建时传入参数 docker build --build-arg VERSION=1.2.3 . 仅在 build 阶段有效,不进入最终镜像环境变量
--cache-from 指定缓存来源镜像 docker build --cache-from myapp:cache . 用于加速构建,常与 CI/CD 配合
--no-cache 禁用缓存 docker build --no-cache . 强制重新执行每一条 Dockerfile 指令
--pull 强制拉取最新基础镜像 docker build --pull . 避免使用本地旧镜像
--quiet, -q 静默构建,仅输出镜像 ID docker build -q . CI/CD 常用,减少日志输出
--rm 构建完成后删除中间容器 默认 true 一般不用手动设置,除非调试
--force-rm 即使构建失败也删除中间容器 docker build --force-rm . 调试时避免残留垃圾容器
--compress 压缩发送给 daemon 的上下文 默认开启 对大文件夹有明显效果
--isolation 设置构建隔离方式 docker build --isolation=process . Windows 平台可用,Linux 通常忽略
--network 构建网络模式 docker build --network=host . 默认 bridge,复杂网络需求可指定
--output, -o 构建输出到本地目录或其他后端 docker build -o type=local,dest=./out . 用于 BuildKit,支持多种输出类型
--progress 控制日志显示方式 docker build --progress=plain . 可选 auto/plain/tty
--secret 构建时使用 secret docker build --secret id=mysecret,src=./secret.txt . 需 BuildKit 支持,用于安全传递密码等
--ssh 构建时使用 SSH agent docker build --ssh default . 常用于私有 Git 拉取依赖
--platform 指定目标平台 docker build --platform linux/amd64 . 用于跨架构构建,多架构镜像
--iidfile 将构建完成镜像 ID 写入文件 docker build --iidfile image_id.txt . CI/CD 常用
--label 给构建的镜像打标签信息 docker build --label version=1.0 . metadata,不影响镜像 ID
--build-context 指定额外构建上下文 docker build --build-context docs=./docs . BuildKit 支持,可引入多个上下文
--ulimit 设置构建时的 ulimit docker build --ulimit nofile=1024:2048 . BuildKit 支持,控制资源限制

2.3 URL 参数说明

如执行:

bash 复制代码
docker build -t myapp:latest https://github.com/user/repo.git
  1. Docker daemon 下载远程仓库到临时目录:如果 URL 指定了 branch/tag/commit,则下载指定版本,默认是 HEAD
  2. 仓库下载完成后,这个下载的内容就是构建上下文
  3. Docker daemon 读取 Dockerfile 内容,按顺序解析每条构建指令(FROM, RUN, COPY, ADD, ENV 等)。

注意:Dockerfile 默认在仓库根目录下找 Dockerfile,如果文件名不是 Dockerfile,必须加 -f 指定。


- 参数说明:

用法 描述 构建上下文 Dockerfile 来源 示例(单元格安全) 优势 限制 / 注意事项
Here Document Shell 使用 HereDoc 把 Dockerfile 内容送入 stdin 默认空 stdin docker build -t tempimage - <<EOF FROM alpine RUN echo hello EOF 无需 Dockerfile 文件,适合临时测试、教学 无上下文,不能 COPY 本地文件
管道 echo 用 echo 输出 Dockerfile,通过管道传给 docker build 默认空 stdin `echo "FROM alpine\nRUN echo hello" docker build - -t tempimage` 最简单、脚本友好
tar 方式传上下文 将目录打包为 tar,通过 stdin 传给 Docker stdin 中的 tar 包 stdin Dockerfile + 上下文 `tar -czf - . docker build - -t myimage` 可在无 Dockerfile 文件情况下构建完整项目
动态生成 Dockerfile 脚本动态生成 Dockerfile 内容 视脚本而定 stdin `generate.sh docker build - -t ci-image` CI/CD 自动化利器
stdin + BuildKit 上下文 使用 BuildKit 引入额外构建上下文 多上下文 stdin docker build --build-context src=./src - < Dockerfile 解决 stdin 无上下文问题 依赖 BuildKit,复杂度高

2.4 dockerignore 文件

.dockerignore 是位于构建上下文根目录的配置文件 ,用于在构建开始之前过滤构建上下文中不需要发送给 Docker daemon 的文件和目录。防止一些大文件或者没有的文件创建到镜像中。

如:

conf 复制代码
.git
.gitignore
node_modules
target
dist
*.log

3.示例

3.1 镜像标签

bash 复制代码
docker build -t repo/name:tag .

多标签:

bash 复制代码
docker build -t app:1.0 -t app:latest .

3.2 指定 DOckerfile

不指定标签

bash 复制代码
docker build -f Dockerfile.prod .

3.3 传入构建参数

给 Dockerfile 中的 ARG 传参

bash 复制代码
docker build --build-arg VERSION=1.2.3 .

3.4 禁用缓存

bash 复制代码
docker build --no-cache .

3.5 平台指定

bash 复制代码
docker build --platform linux/amd64 .

3.6 本地文件路径

bash 复制代码
docker build -t myapp:1.0 .
docker build -t myapp:1.0 ./docker
docker build -t myapp:1.0 /home/user/project
  • Dockerfile:默认在 PATH 根目录下找 Dockerfile。
  • COPY / ADD只能访问上下文里的文件,不能访问 PATH 以外的文件。
  • 性能注意不要把不必要的大文件夹放入上下文,否则每次 build 都要上传,耗时很长。
  • 解决方案使用 .dockerignore 忽略不需要的文件

3.7 Git 仓库或者 HTTP(s) 资源

bash 复制代码
docker build -t myapp:latest https://github.com/user/repo.git
docker build -t myapp:latest https://github.com/user/repo.git#branch-name
docker build -t myapp:latest https://github.com/user/repo.git#commit-hash

3.8 从标准输入读取 Dockerfile

动态生成 Dockerfile:

CI/CD 脚本生成 Dockerfile 内容,然后直接构建,不用在磁盘上写文件

bash 复制代码
echo -e "FROM alpine\nRUN echo hello" | docker build - -t myimage

临时构建:

bash 复制代码
# <<EOF 表示 把后续直到 EOF 的内容当作标准输入
docker build -t tempimage - <<EOF
FROM busybox
RUN echo hello
EOF

四.docker 部署 springboot 示例

1.docker 下拉 java 镜像

bash 复制代码
docker pull williamyeh/java8

该镜像不必启动

2.编写 Dockerfile 文件

Dockerfile 复制代码
#指定基础镜像,本地没有会从dockerHub pul1下来
FROM williamyeh/java8
#把可执行jar包复制到基础镜像的根目录下
ADD api-test.jar /api-test.jar
#镜像要暴露的端口,如要使用端口,在执行docker run命令时使用-p生效
EXPOSE 8087
#在镜像运行为容器后执行的命令
ENTRYPOINT ["java","-jar","/api-test.jar"]

3.打包 jar 为镜像

上传 jar 包到服务器 Dockerfile 文件同目录下

bash 复制代码
docker build -f Dokcerfile -t why/api-test:v1.0 .

参数说明:

  • -f: 指定Dockerfile文件的路径
  • -t: 指定镜像名字和TAG
  • .: 指当前目录,这里实际上需要一个上下文路径

4.启动 api-test 镜像

bash 复制代码
docker run -d --name api-test -p 8087:8087 why/api-test:v1.0

我们可以在一台机器上, 部署多个该微服务, 内部同一个端口, 宿主机多个端口, 以此用来负载均衡

bash 复制代码
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
相关推荐
释怀不想释怀17 小时前
Docker(安装软件)
运维·docker·容器
超龄超能程序猿18 小时前
Docker常用中间件部署笔记:MongoDB、Redis、MySQL、Tomcat快速搭建
笔记·docker·中间件
奔波霸的伶俐虫18 小时前
windows docker desktop 安装修改镜像学习
学习·docker·容器
阿杰 AJie18 小时前
安装 docker.io(不走外网 Docker 域名)
docker·容器·eureka
.hopeful.18 小时前
Docker——镜像仓库和镜像
运维·docker·容器
CodeCaptain18 小时前
Dify结合vllm-openai docker镜像出现docker: invalid reference format问题的解决方案
运维·docker·容器
忍冬行者18 小时前
k8s的etcd的一键备份和故障恢复
docker·云原生·容器·kubernetes·云计算
小二·18 小时前
前端 DevOps 完全指南:从 Docker 容器化到 GitHub Actions 自动化部署(Vue 3 + Vite)
前端·docker·devops
huaweichenai1 天前
docker部署kkFileView实现文件预览功能
运维·docker·容器