跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Shell / Bashjava

Dockerfile 核心指令详解与构建实践

Dockerfile 是构建 Docker 镜像的文件,包含一系列自上而下执行的指令。了 FROM、WORKDIR、COPY、ADD、ENV、ARG、RUN、ENTRYPOINT、CMD、EXPOSE、VOLUME 等核心指令的语法、参数及最佳实践,重点介绍了多阶段构建以减小镜像体积。同时涵盖了 docker build 命令的使用、构建上下文管理以及 .dockerignore 配置。最后提供了基于 Spring Boot 的 Docker 部署完整示例,帮助开发者掌握容器化应用的标准流程。

GRACE Grace发布于 2026/3/17更新于 2026/7/1946 浏览
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:

FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y curl
COPY app.sh /app/app.sh

生成的镜像层如下:

层号Dockerfile 指令Layer 内容
1FROM ubuntuUbuntu 文件系统
2RUN apt-get updateapt 缓存
3RUN apt-get installcurl 二进制
4COPY app.shapp.sh 文件

注意:Dockerfile 不是合并执行,而是逐层叠加。

二、Dockerfile 核心指令详解

1. FROM

1.1 指令说明

FROM 用于指定当前镜像所基于的基础镜像,是 Dockerfile 中的第一条有效指令。 一个 Dockerfile 中可以存在多个 FROM(用于多阶段构建)。

基础镜像来源:

  1. Docker 会优先在本地查找基础镜像
  2. 本地不存在则从 Docker Hub 或私有仓库拉取
  3. 镜像不存在则构建失败
1.2 语法格式
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>@<digest> [AS <name>]
1.3 参数说明
参数是否必需含义示例工程建议
FROM必需声明新的构建阶段并指定基础镜像FROM ubuntu每个 Dockerfile 至少一个
--platform可选指定 OS / CPU 架构linux/amd64, linux/arm64跨平台 / CI 推荐
<image>必需基础镜像名称openjdk, ubuntu使用可信镜像源
:<tag>推荐镜像版本标签:11-jre不指定则默认最新版本,生产必须指定版本
@<digest>可选镜像内容哈希(不可变)@sha256:...强一致性与安全
AS <name>可选构建阶段命名AS builder多阶段构建必用
1.4 示例
FROM williamyeh/java8:latest
FROM williamyeh/java8@sha256:174d528516a0eae5c4df69966eeb5e51d7c0dc1a532249af61013953eab1d9f3
FROM --platform=linux/amd64 ubuntu:20.04 AS builder
1.5 多阶段构建(Multi-stage Build)

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

❌ 错误示例(单阶段)
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 与源码永久存在镜像中
  • 镜像臃肿,攻击面扩大
✅ 正确示例(多阶段构建)
# 构建阶段
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 语法格式
WORKDIR /path/to/workdir
2.3 示例

绝对路径:

FROM ubuntu:22.04
WORKDIR /usr/why/app
RUN pwd
COPY . .

RUN 和之后的所有命令,都是在 /usr/why/app 下执行。COPY 方法则是将宿主机当前目录下所有文件,复制到 /usr/src/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

3.1 指令说明

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

3.2 语法格式
COPY [--from=<name>] [--chown=<user>:<group>] [--chmod=<perms>] [--link] [--parents] [--exclude=<pattern>] <src>... <dest>
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 脚本 / 可执行文件如 755、644
--exclude=<pattern>排除匹配的文件精细控制 COPY 内容类似 .dockerignore,但更局部
--parents保留源文件目录结构批量复制并保持路径适合复制深层文件
--link使用硬链接代替复制大文件/不可变文件/构建性能优化多个 Layer 共享同一文件数据减少 IO、加快构建
3.4 示例

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

COPY --from=builder /build/target/app.jar /app/app.jar

设置文件属主和属组:

COPY --chown=appuser:appgroup app.jar /app/app.jar

设置文件权限:

COPY --chmod=755 start.sh /app/start.sh

排除匹配的文件:

COPY --exclude=*.md --exclude=test/ . /app/

保留源文件目录结构:

COPY --parents src/main/resources/application.yml /app/

使用硬链接代替复制:

注:需开启 DOCKER_BUILDKIT=1

COPY --link app.jar /app/app.jar

4. ADD

4.1 指令说明

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

4.2 语法格式
ADD [--keep-git-dir] [--checksum=<checksum>] [--chown=<user>:<group>] [--chmod=<perms>] [--link] [--exclude=<pattern>] <src>... <dest>
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>设置文件权限脚本 / 可执行文件如 755、644
--link使用硬链接而非复制构建性能优化多个 Layer 共享同一文件数据减少 IO、加快构建
--exclude=<pattern>排除匹配文件精细控制 ADD 内容在 ADD 时排除指定文件
4.4 示例

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

使用 git 需启用 BuildKit

ADD --keep-git-dir https://github.com/example/repo.git /src

校验下载内容的完整性:

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

ADD --checksum=sha256:abc123 https://example.com/app.tar.gz /app/

设置文件属主/属组:

ADD --chown=app:app app.tar.gz /app/

设置文件权限:

ADD --chmod=755 start.sh /app/start.sh

使用硬链接:

ADD --link app.tar.gz /app/

排除匹配文件:

ADD --exclude=*.md --exclude=test/ . /app/
4.5 与 COPY 的对比
对比维度COPYADD备注
基本功能复制本地文件/目录复制文件 + 扩展功能能用 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 语法格式
MAINTAINER <作者信息>
5.3 示例
MAINTAINER xiaoyangzi
MAINTAINER xiaoyangzi <[email protected]>

6. LABEL

6.1 指令说明

LABEL 指令为镜像添加元数据(metadata) 的指令。这些元数据以键值对(key-value) 的形式存在,用于描述镜像的作者、版本、用途、来源等信息。 LABEL 不会影响镜像的构建流程和运行行为,其主要作用是信息标注与管理。

6.2 语法格式
LABEL <key>=<value> <key>=<value> <key>=<value> ...
6.3 示例

设置制作人信息:

LABEL maintainer="xiaoyangzi <[email protected]>"

设置多个标签:

LABEL maintainer="xiaoyangzi <[email protected]>" \
      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 语法格式

常用形式:

ENV <key>=<value> [<key>=<value>...]

一对一形式(不推荐):

ENV <key> <value>

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

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

一对一形式:

ENV NAME "XYZ"

常用形式:

ENV NAME="XYZ" \
    AGE=18 \
    gender=male

使用示例:

ENV NAME XYZ
CMD echo "Hello, $NAME"
CMD echo "Hello, ${NAME}"

8. ARG

8.1 指令说明

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

8.2 语法格式
ARG <name>[=<default value>] [<name>[=<default value>]...]

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

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

docker build --build-arg <变量名>=<值> --build-arg <变量名>=<值>.
8.3 示例

定义变量

ARG APP_ENV=dev
ARG APP_VERSION
ARG BUILD_TIME

使用变量:

与 ENV 使用方法相似:

RUN echo "Environment: $APP_ENV"
RUN echo "Version: ${APP_VERSION}"

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

RUN echo "Environment: $APP_ENV"
RUN echo "Version: ${APP_VERSION:-v0.0.1}"

构建时传参:

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

联合使用 ARG 和 ENV

ARG APP_ENV=dev
ENV APP_ENV=${APP_ENV}
RUN echo "Build environment: $APP_ENV"

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

FROM ubuntu
ARG NAME=xyz
ENV NAME=why
RUN echo $NAME
FROM ubuntu
ENV NAME=why
ARG NAME=xyz
RUN echo $NAME

两个的 NAME 的输出均为 why

8.5 内置 ARG 变量

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

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

9. RUN

9.1 指令说明

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

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

9.2 语法格式
Shell 格式:

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

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

RUN [OPTIONS] <command> ...
Exec 格式:

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

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

RUN [OPTIONS] [ "<command>", ... ]

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

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

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 keyCI 中慎用
--device硬件设备构建期访问宿主设备/dev/kvm /dev/nvidia0❌ 不会QEMU / GPU 构建极少数场景需要
9.3 示例

shell 形式:

RUN echo "Hello Docker"

Exec 形式:

RUN ["echo", "Hello Docker"]

合并 RUN:

RUN apt-get update \
  && apt-get install -y curl \
  && rm -rf /var/lib/apt/lists/*

使用变量:

ARG APP_VERSION
RUN echo "version=$APP_VERSION"

构建缓存:

RUN --mount=type=cache,target=/root/.cache \
  pip install -r requirements.txt

绑定主机或上下文文件:

RUN --mount=type=bind,source=requirements.txt,target=/tmp/req.txt \
  pip install -r /tmp/req.txt

构建期密钥:

RUN --mount=type=secret,id=mytoken \
  cat /run/secrets/mytoken

构建命令:

docker build --secret id=mytoken,src=token.txt .

构建期 SSH 访问:

RUN --mount=type=ssh git clone [email protected]:private/repo.git

构建命令:

docker build --ssh default .

在构建阶段禁止联网

RUN --network=none go build

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

RUN --security=insecure some-command

临时暴露设备给 RUN:

RUN --device=/dev/kvm make test

组合使用:

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 格式:

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

ENTRYPOINT ["executable", "param1", "param2"]
Shell 格式:

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

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 参数覆盖

docker run --entrypoint bash image

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

10.3 示例

Exec 格式:

ENTRYPOINT ["python"]
docker run 命令实际执行
docker run image app.pypython app.py

Shell 格式:

ENTRYPOINT nginx -g "daemon off;"

与 CMD 组合执行:

ENTRYPOINT ["python"]
CMD ["app.py"]
docker run 命令实际执行
docker run imagepython app.py
docker run image other.pypython other.py

11. CMD

11.1 指令说明

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

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

CMD ["echo", "hello"]
docker run image echo world

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

11.2 语法格式
Shell 格式:

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

CMD command param1 param2
Exec 格式:

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

CMD ["executable","param1","param2"]
为 ENTRYPOINT 提供默认参数:

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

CMD ["param1","param2"]

两者区别:

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

Exec 形式:

CMD ["nginx", "-g", "daemon off;"]

Shell 形式:

CMD nginx -g "daemon off;"

配合 ENTRYPOINT:

ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
docker run实际执行
docker run imagenginx -g daemon off;
docker run image -tnginx -t

RUN、ENTRYPOINT、CMD 区别

对比维度RUNENTRYPOINTCMD
所属阶段构建阶段(build time)运行阶段(run time)运行阶段(run time)
核心作用构建镜像内容定义容器的固定入口程序定义默认启动命令或参数
是否生成镜像层✅ 每条 RUN 生成一层❌❌
是否在构建时执行✅❌❌
是否在容器启动时执行❌✅✅
是否必须存在❌❌❌
是否只能有一条❌✅(最后一条生效)✅(最后一条生效)
是否支持 Shell 格式✅✅(不推荐)✅(不推荐)
是否支持 Exec 格式✅✅(强烈推荐)✅(推荐)
是否启动 shellShell 格式会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

EXPOSE <port> [<port>/<protocol>...]
12.3 示例

声明端口:

EXPOSE 80
EXPOSE 80/tcp
EXPOSE 53/udp
EXPOSE 80 443

声明多个端口:

EXPOSE 80 443 9000
12.4 启动示例

-p 映射启动:

docker run -d -p 80:7000 -p 8080:8080/udp image

-P 启动:

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 语法格式
单路径模式:
VOLUME ["/data"]
数组模式:
VOLUME ["/var/lib/mysql", "/var/log/mysql"]
13.3 示例
1. VOLUME 示例

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

VOLUME ["/data"]

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

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

docker run -v mydata:/data image

宿主机指定绝对路径:

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

docker run -v /host/data:/data image

3.–mount type=volume 示例

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

docker run --mount type=volume,source=mydata,target=/data image

4.–mount type=bind 示例:

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

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
定义位置Dockerfiledocker run / Composedocker run / Composedocker 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 方式执行的指令格式:

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 语法格式
SHELL ["executable", "parameters"]

参数说明:

  • executable:要使用的 Shell 程序的完整路径。如 /bin/bash、powershell 等。
  • parameters:传递给该 Shell 程序的参数。如 -c、 -Command等。
14.3 示例
Bash 常用模式:
SHELL ["/bin/bash", "-c"]
Bash 严格模式:
SHELL ["/bin/bash", "-euxo", "pipefail", "-c"]

参数说明:

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

参数说明:

  • /S:改变 /C 后面命令字符串的解析规则,防止复杂命令容易被错误拆分或转义失败。
  • /C:执行完后面的命令字符串后立即退出。
Windows PowerShell:
SHELL ["powershell", "-Command"]
PowerShell 严格模式:
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 文件中定义的用户名/组

用户名/用户组名:
USER <user>[:<group>]
用户 ID/组 ID:
USER UID[:GID]
15.3 示例

创建用户并使用:

# 创建一个用户组,指定组 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"]

切换用户:

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 语法格式
检查容器的健康状况:
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

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

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

HEALTHCHECK --interval=10s CMD curl -f http://localhost:8080/health || exit 1

设置单次检查超时时间:

HEALTHCHECK --timeout=5s CMD curl -f http://localhost:080/health || exit 1

容器启动后的宽限期:

HEALTHCHECK --start-period=20s CMD curl -f http://localhost:8080/health || exit 1

设置启动器时间间隔:

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

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

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

HEALTHCHECK --retries=5 CMD curl -f http://localhost:8080/health || exit 1

综合示例:

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 等服务的端口探测
  • 缺点:只能判断端口是否监听,不能判断协议/服务是否真正可用
HEALTHCHECK CMD nc -z localhost 3306 || exit 1

参数说明:

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

16.3.3 命令/进程检查

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

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 文件/目录检查
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 自定义脚本(复杂逻辑)
HEALTHCHECK CMD /app/healthcheck.sh

17. ONBUILD

17.1 指令说明

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

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

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

17.2 语法格式
ONBUILD <INSTRUCTION>

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

17.3 示例
17.3.1 构建示例

构建父镜像:

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

构建这个镜像时:

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

构建子镜像:

FROM mybaseimage:latest

构建子镜像时:

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

17.3.2 典型使用场景:

父镜像:

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

子镜像:

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 失效

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

18.2 语法格式
STOPSIGNAL signal

支持两种写法:

# 信号名形式
STOPSIGNAL SIGTERM
# 编号形式
STOPSIGNAL 15

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

docker run --stop-signal=SIGINT my-image
docker create --stop-signal SIGTERM my-image

常用 Unix 信号表

信号名编号含义默认行为常见用途
SIGTERM15请求终止终止进程Docker 默认 stop 信号
SIGINT2中断终止进程Ctrl+C、CLI 程序
SIGQUIT3退出并生成 core终止 + coreNginx 优雅退出
SIGKILL9强制杀死立即终止无法捕获,兜底
SIGHUP1挂起/重载终止或重载重新加载配置
SIGUSR110用户自定义忽略应用自定义控制
SIGUSR212用户自定义忽略应用自定义控制
SIGPIPE13管道破裂终止写入已关闭管道
SIGCHLD17子进程退出忽略进程回收
SIGALRM14定时器超时终止超时控制

18.3 示例
18.3.1 SIGTERM:

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

STOPSIGNAL SIGTERM
ENTRYPOINT ["myapp"]

18.3.2 SIGINT:

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

STOPSIGNAL SIGINT
CMD ["ffmpeg", "-i", "a.mp4", "b.mp4"]
STOPSIGNAL SIGINT
CMD ["node", "server.js"]
STOPSIGNAL SIGINT
CMD ["python", "server.py"]

18.3.3 SIGQUIT

Nginx 优雅退出:

STOPSIGNAL SIGQUIT

18.3.4 SIGKILL

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

dockerkill mycontainer

18.3.5 SIGHUP

重新加载配置 / 重启逻辑

dockerkill -s HUP nginx-container

等价于:

nginx -s reload

用 Bash 模拟配置重载:

#!/bin/sh
reload(){echo"Reload config at $(date)"}
trap reload HUP
echo"App started, PID $$"
while true; do
  sleep 5
done
FROM alpine
COPY app.sh /app.sh
RUN chmod +x /app.sh
CMD ["/app.sh"]
docker run -d --name hup-demo hup-image
dockerkill -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 语法格式
docker build [OPTIONS] PATH| URL | -

关键组成部分

部分含义
OPTIONS构建参数
PATHPATH 指的是构建上下文路径,可以是相对路径或绝对路径
URLGit 仓库或者 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静默构建,仅输出镜像 IDdocker 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构建时使用 secretdocker build --secret id=mysecret,src=./secret.txt .需 BuildKit 支持,用于安全传递密码等
--ssh构建时使用 SSH agentdocker 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设置构建时的 ulimitdocker build --ulimit nofile=1024:2048 .BuildKit 支持,控制资源限制

2.3 URL 参数说明

如执行:

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 DocumentShell 使用 HereDoc 把 Dockerfile 内容送入 stdin默认空stdindocker 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 传给 Dockerstdin 中的 tar 包stdin Dockerfile + 上下文`tar -czf - .docker build - -t myimage`可在无 Dockerfile 文件情况下构建完整项目
动态生成 Dockerfile脚本动态生成 Dockerfile 内容视脚本而定stdin`generate.shdocker build - -t ci-image`CI/CD 自动化利器
stdin + BuildKit 上下文使用 BuildKit 引入额外构建上下文多上下文stdindocker build --build-context src=./src - < Dockerfile解决 stdin 无上下文问题依赖 BuildKit,复杂度高
2.4 dockerignore 文件

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

如:

.git
.gitignore
node_modules
target
dist
*.log

3. 示例

3.1 镜像标签
docker build -t repo/name:tag .

多标签:

docker build -t app:1.0 -t app:latest .
3.2 指定 DOckerfile

不指定标签

docker build -f Dockerfile.prod .
3.3 传入构建参数

给 Dockerfile 中的 ARG 传参

docker build --build-arg VERSION=1.2.3 .
3.4 禁用缓存
docker build --no-cache .
3.5 平台指定
docker build --platform linux/amd64 .
3.6 本地文件路径
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) 资源
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 内容,然后直接构建,不用在磁盘上写文件

echo -e "FROM alpine\nRUN echo hello" | docker build - -t myimage

临时构建:

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

四、docker 部署 springboot 示例

1. docker 下拉 java 镜像

docker pull williamyeh/java8

该镜像不必启动

2. 编写 Dockerfile 文件

#指定基础镜像,本地没有会从 dockerHub pull 下来
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 文件同目录下

docker build -f Dockerfile -t why/api-test:v1.0 .

参数说明:

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

4. 启动 api-test 镜像

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

目录

  1. 一、Dockerfile 概述
  2. 1. 什么是 Dockerfile
  3. 2. 镜像、Layer 与容器的关系
  4. 3. Dockerfile 到 Layer 的真实映射
  5. 二、Dockerfile 核心指令详解
  6. 1. FROM
  7. 1.1 指令说明
  8. 1.2 语法格式
  9. 1.3 参数说明
  10. 1.4 示例
  11. 1.5 多阶段构建(Multi-stage Build)
  12. ❌ 错误示例(单阶段)
  13. ✅ 正确示例(多阶段构建)
  14. 构建阶段
  15. 运行阶段
  16. 2. WORKDIR
  17. 2.1 指令说明
  18. 2.2 语法格式
  19. 2.3 示例
  20. 3. COPY
  21. 3.1 指令说明
  22. 3.2 语法格式
  23. 3.3 参数说明
  24. 3.4 示例
  25. 4. ADD
  26. 4.1 指令说明
  27. 4.2 语法格式
  28. 4.3 参数说明
  29. 4.4 示例
  30. 4.5 与 COPY 的对比
  31. 5. MAINTAINER(已废弃)
  32. 5.1 指令说明
  33. 5.2 语法格式
  34. 5.3 示例
  35. 6. LABEL
  36. 6.1 指令说明
  37. 6.2 语法格式
  38. 6.3 示例
  39. 7. ENV
  40. 7.1 指令说明
  41. 7.2 语法格式
  42. 7.3 示例
  43. 8. ARG
  44. 8.1 指令说明
  45. 8.2 语法格式
  46. 8.3 示例
  47. 8.4 ENV 和 ARG 的区别
  48. 8.5 内置 ARG 变量
  49. 9. RUN
  50. 9.1 指令说明
  51. 9.2 语法格式
  52. Shell 格式:
  53. Exec 格式:
  54. OPTIONS 参数:
  55. 9.3 示例
  56. 10. ENTRYPOINT
  57. 10.1 指令说明
  58. 10.2 语法格式
  59. Exec 格式:
  60. Shell 格式:
  61. 替换 ENTRYPOINT:
  62. 10.3 示例
  63. 11. CMD
  64. 11.1 指令说明
  65. 11.2 语法格式
  66. Shell 格式:
  67. Exec 格式:
  68. 为 ENTRYPOINT 提供默认参数:
  69. 11.3 示例
  70. RUN、ENTRYPOINT、CMD 区别
  71. 12. EXPOSE
  72. 12.1 指令说明
  73. 12.2 语法格式
  74. 12.3 示例
  75. 12.4 启动示例
  76. 13. VOLUME
  77. 13.1 指令说明
  78. 13.2 语法格式
  79. 单路径模式:
  80. 数组模式:
  81. 13.3 示例
  82. 1. VOLUME 示例
  83. 2.-v 示例
  84. 宿主机指定 volume 目录名称:
  85. 宿主机指定绝对路径:
  86. 3.–mount type=volume 示例
  87. 4.–mount type=bind 示例:
  88. 13.4 VOLUME、-v、–mount 区别
  89. 14. SHELL
  90. 14.1 指令说明
  91. 14.2 语法格式
  92. 14.3 示例
  93. Bash 常用模式:
  94. Bash 严格模式:
  95. Windows 默认(cmd):
  96. Windows PowerShell:
  97. PowerShell 严格模式:
  98. 15. USER
  99. 15.1 指令说明
  100. 15.2 语法格式
  101. 用户名/用户组名:
  102. 用户 ID/组 ID:
  103. 15.3 示例
  104. 创建一个用户组,指定组 id 为 1001,组名为 appgroup # 并创建一个系统用户 appuser,指定用户 id 为 1001,并加入 appgroup 组
  105. 将宿主机构建上下文中的 app 文件复制到容器内 (COPY 后文件一定是 root 拥有的,这是后面要 chown 的原因。)
  106. 修改 /app 目录的所有权,并赋予 app.sh 可执行权限
  107. 切换用户
  108. 执行 app.sh 文件
  109. 16. HEALTHCHECK
  110. 16.1 指令说明
  111. 16.2 语法格式
  112. 检查容器的健康状况:
  113. 禁用从基础镜像继承而来的任何健康检查功能:
  114. 16.3 示例
  115. 16.3.1 curl 方式
  116. 16.3.2 TCP 端口检查
  117. 16.3.3 命令/进程检查
  118. 16.3.4 文件/目录检查
  119. 16.3.5 自定义脚本(复杂逻辑)
  120. 17. ONBUILD
  121. 17.1 指令说明
  122. 17.2 语法格式
  123. 17.3 示例
  124. 17.3.1 构建示例
  125. 基础镜像
  126. 17.3.2 典型使用场景:
  127. python:3.9-slim 的 Dockerfile
  128. 18. STOPSIGNAL
  129. 18.1 指令说明
  130. 18.2 语法格式
  131. 信号名形式
  132. 编号形式
  133. 18.3 示例
  134. 18.3.1 SIGTERM:
  135. 18.3.2 SIGINT:
  136. 18.3.3 SIGQUIT
  137. 18.3.4 SIGKILL
  138. 18.3.5 SIGHUP
  139. 三、docker build 构建命令
  140. 1. docker build 介绍
  141. 2. docker build 的基本语法
  142. 2.1 语法格式
  143. 2.2 OPTIONS 可用参数列表
  144. 2.3 URL 参数说明
  145. 2.4 dockerignore 文件
  146. 3. 示例
  147. 3.1 镜像标签
  148. 3.2 指定 DOckerfile
  149. 3.3 传入构建参数
  150. 3.4 禁用缓存
  151. 3.5 平台指定
  152. 3.6 本地文件路径
  153. 3.7 Git 仓库或者 HTTP(s) 资源
  154. 3.8 从标准输入读取 Dockerfile
  155. <<EOF 表示 把后续直到 EOF 的内容当作标准输入
  156. 四、docker 部署 springboot 示例
  157. 1. docker 下拉 java 镜像
  158. 2. 编写 Dockerfile 文件
  159. 3. 打包 jar 为镜像
  160. 4. 启动 api-test 镜像
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 从 BERT 到 GPT:Transformer 模型在 AI 发展中的作用
  • 使用 SiliconCloud 免费体验 Llama3.1-405B 开源大模型
  • FPGA 电源系统设计及器件选型指南
  • AI 辅助开发:使用 DeepSeek 构建贪吃蛇游戏
  • 滑动窗口与哈希表实战:串联所有单词子串与最小覆盖子串
  • Windows 下安装 OpenClaw 并接入飞书机器人指南
  • B 站生态观察:从二次元社区到 AI 创新孵化器
  • 并查集数据结构详解与实战应用
  • GitHub Copilot vs Cursor vs Codeium 对比与选择指南
  • 银发族的 AI 助手:AIGC 如何陪伴父母防骗解闷
  • 产品经理是否有必要学习大模型技术
  • 10 篇今日必读的大模型前沿论文研究
  • Stable Diffusion 模型加载报错:CheckpointLoaderSimple 错误修复
  • JavaScript 基础语法与 jQuery 入门详解
  • Flutter 组件 tavily_dart 在鸿蒙 Harmony 上的适配与 AI 搜索集成实战
  • Spring Bean 作用域、生命周期与自动装配源码解析
  • STL 缩略图完全指南:提升 Windows 文件管理效率
  • Hymba:融合注意力与 SSM 头的新型语言模型架构
  • Web 开发技术全景:从基础原理到全栈架构与未来趋势
  • Python 3.12.0 Windows 环境安装与配置指南

相关免费在线工具

  • 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