From b3d150831076e3da1ebf595bbf8ae3e92da18fb9 Mon Sep 17 00:00:00 2001 From: yeasy Date: Sun, 19 Apr 2026 22:35:28 -0700 Subject: [PATCH] Add new content and update versions --- 01_introduction/1.1_quickstart.md | 6 ++-- 01_introduction/1.2_what.md | 8 ++++-- 01_introduction/1.3_why.md | 22 ++++++++------- 01_introduction/README.md | 2 +- 02_basic_concept/2.3_repository.md | 4 +-- 04_image/4.5_build.md | 2 +- 05_container/5.5_import_export.md | 2 +- 06_repository/6.1_dockerhub.md | 2 +- 06_repository/6.2_registry.md | 2 +- 07_dockerfile/7.12_healthcheck.md | 10 +++++++ 07_dockerfile/7.1_run.md | 37 +++++++++++++++++++++++++ 07_dockerfile/7.2_copy.md | 5 ++++ 11_compose/11.3_usage.md | 2 ++ 11_compose/11.5_compose_file.md | 37 +++++++++++++++++++++++-- 13_kubernetes_concepts/13.2_concepts.md | 2 +- 15_etcd/15.3_cluster.md | 6 ++-- 17_ecosystem/17.2_coreos_install.md | 2 +- 17_ecosystem/17.6_containerd.md | 2 +- 18 files changed, 122 insertions(+), 31 deletions(-) diff --git a/01_introduction/1.1_quickstart.md b/01_introduction/1.1_quickstart.md index e1d7515..d42532f 100644 --- a/01_introduction/1.1_quickstart.md +++ b/01_introduction/1.1_quickstart.md @@ -2,7 +2,9 @@ 本节将通过一个简单的 Web 应用例子,带你快速体验 Docker 的核心流程:构建镜像、运行容器。 -在学习 Docker 之前,我们先来理解为什么这个例子适合初学者。Docker 的核心价值在于 **一致性交付**:无论你在本地、云端还是他人的机器上运行容器,应用的行为都应该保持一致。这个 Nginx + 静态 HTML 的例子之所以被广泛采用,是因为它展现了 Docker 工作流的三个核心阶段: +### 为什么选择 Nginx + HTML 作为入门例子? + +在学习 Docker 之前,我们先来理解为什么这个例子是最适合初学者的。Docker 的核心价值在于**一致性交付**——无论你在本地、云端还是他人的机器上运行容器,应用的行为都是完全一致的。这个 Nginx + 静态 HTML 的例子之所以被广泛采用,是因为它展现了 Docker 工作流的三个核心阶段: 1. **镜像定义(Image Layer)**:通过 Dockerfile 描述如何把应用打包成一个自包含的单元 2. **镜像构建(Build)**:执行 `docker build`,Docker 根据 Dockerfile 逐层构建镜像 @@ -27,8 +29,6 @@ FROM nginx:alpine COPY index.html /usr/share/nginx/html/index.html ``` -这里的 `/usr/share/nginx/html/` 是 Nginx 官方镜像默认提供静态页面的目录。把 `index.html` 复制到这个位置后,Nginx 启动时就会直接对外提供该页面,因此这个例子能把“准备文件 -> 打包镜像 -> 启动服务”的最短路径展示得很清楚。 - ### 1.1.3 构建镜像 打开终端,进入该目录,执行构建命令: diff --git a/01_introduction/1.2_what.md b/01_introduction/1.2_what.md index 3ab4786..f088213 100644 --- a/01_introduction/1.2_what.md +++ b/01_introduction/1.2_what.md @@ -79,7 +79,9 @@ Docker 使用 [Go 语言](https://golang.google.cn/)开发,基于 Linux 内核 > 如果你对这些底层技术感兴趣,可以阅读本书的[底层实现](../12_implementation/README.md)章节。 -**Docker 架构演进**:Docker 的底层实现经历了多次演进: +#### Docker 架构演进 + +Docker 的底层实现经历了多次演进: ```mermaid flowchart LR @@ -104,13 +106,13 @@ flowchart LR ### 1.2.5 Docker 的历史与生态 -**Docker** 最初是 `dotCloud` 公司创始人 [Solomon Hykes](https://github.com/shykes) 发起的一个公司内部项目,于 [2013 年 3 月以 Apache 2.0 授权协议开源](https://en.wikipedia.org/wiki/Docker_%28software%29)。 +**Docker** 最初是 `dotCloud` 公司创始人 [Solomon Hykes](https://github.com/shykes) 在法国期间发起的一个公司内部项目,于 [2013 年 3 月以 Apache 2.0 授权协议开源](https://en.wikipedia.org/wiki/Docker_%28software%29)。 Docker 的发展历程: - **2013 年 3 月**:开源发布 - **2013 年底**:dotCloud 公司改名为 Docker,Inc。 - **2015 年**:成立[开放容器联盟 (OCI)](https://opencontainers.org/),推动容器标准化 -- **截至 2026 年 4 月**:[GitHub 项目](https://github.com/moby/moby)超过 7 万星标 +- **至今**:[GitHub 项目](https://github.com/moby/moby)超过 7 万星标 Docker 的成功推动了整个容器生态的发展,催生了 Kubernetes、Podman 等众多相关项目。笔者认为,Docker 最大的贡献不仅是技术本身,更是它 **让容器技术从系统管理员的工具变成了每个开发者都能使用的标准工具**。 diff --git a/01_introduction/1.3_why.md b/01_introduction/1.3_why.md index 48f7522..6b6f7b4 100644 --- a/01_introduction/1.3_why.md +++ b/01_introduction/1.3_why.md @@ -45,7 +45,9 @@ ### 1.3.2 Docker 如何解决这些问题 -Docker 的出现为上述问题提供了系统性的解决方案。它通过 “一次构建,到处运行” 的核心理念,从根本上改变了软件交付的方式。 +Docker 的出现为上述问题提供了完美的解决方案。它通过 “一次构建,到处运行” 的核心理念,从根本上改变了软件交付的方式。 + +#### 核心理念:一次构建,到处运行 ```mermaid flowchart LR @@ -99,27 +101,27 @@ $ docker compose up #### 3. 资源效率 Docker 容器共享宿主机内核,无需为每个应用运行完整的操作系统。以一台 64GB 内存的物理服务器为例: -- **传统虚拟机方案**:每个虚拟机都需要额外运行一套完整操作系统,会带来持续的基础资源开销;随着实例数增加,可真正分配给业务进程的内存会被不断压缩。 -- **Docker 方案**:容器直接共享宿主机系统,只保留宿主机和容器引擎的基础开销,因此通常能把更多内存留给实际业务负载。 +- **传统虚拟机方案**:每个虚拟机都需要运行完整的操作系统(每个额外占用如 2GB 内存),产生大量资源开销,实际可用于应用的内存可能只有约 18GB。 +- **Docker 方案**:容器直接共享宿主机系统,只需付出很少的基础开销(OS 及引擎约 4GB),即可将约 60GB 的内存全部用于实际应用。 ```mermaid flowchart TD subgraph VM ["传统虚拟机方案 ❌"] direction TB Server1["物理服务器 (64GB 内存)"] - subgraph VMs ["可用应用内存: 较少"] + subgraph VMs ["可用应用内存: 约 18GB"] direction LR - VM1["VM 1: 应用 1
(含独立 OS 开销)"] - VM2["VM 2: 应用 2
(含独立 OS 开销)"] - VM3["VM 3: 应用 3
(含独立 OS 开销)"] + VM1["VM 1: 应用 1
(含 2GB OS)"] + VM2["VM 2: 应用 2
(含 2GB OS)"] + VM3["VM 3: 应用 3
(含 2GB OS)"] end Server1 --- VMs end subgraph Docker ["Docker 方案 ✅"] direction TB - Server2["物理服务器 (64GB 内存)
含宿主 OS 与引擎基础开销"] - subgraph Containers ["可用应用内存: 更多"] + Server2["物理服务器 (64GB 内存)
含约 4GB OS及引擎配置"] + subgraph Containers ["可用应用内存: 约 60GB"] direction LR C1["容器 1: 应用 1
(按需分配)"] C2["容器 2: 应用 2
(按需分配)"] @@ -158,7 +160,7 @@ Docker 可以在几乎任何平台上运行: #### 6. 微服务架构的基石 -现代微服务实践大量采用容器技术作为交付基础。Docker 让你可以先把每个服务标准化封装;而在更大规模场景下,通常还需要配合编排、服务发现、网络治理和可观测性体系一起落地: +现代微服务架构几乎都依赖容器技术。Docker 让你可以: - **隔离服务**:每个服务运行在独立容器中,互不干扰 - **独立扩展**:哪个服务负载高,就单独扩展哪个 diff --git a/01_introduction/README.md b/01_introduction/README.md index 3096899..d471d18 100644 --- a/01_introduction/README.md +++ b/01_introduction/README.md @@ -2,7 +2,7 @@ 本章将带领你进入 **Docker** 的世界。 -> **版本提示**:本书内容及示例基于 **Docker Engine v29.x** 及以上版本。自 Docker Engine v29 起,全新安装默认启用 `containerd image store` 作为镜像存储后端;这意味着后续涉及多架构镜像、本地镜像元数据和供应链安全能力的章节,会以这一路径为背景展开说明。 +> **版本提示**:本书内容及示例基于 **Docker Engine v29.x** 及以上版本。值得注意的是,自 Docker Engine v29 起,官方在全新安装场景下 **默认启用 `containerd image store` 作为镜像存储后端**(取代传统 classic store 路径下的 graph driver 体系)。这项底层革新极大增强了 Docker 对多架构镜像(Multi-platform)以及软件供应链安全元数据(Attestations, SBOM, Provenance)的本地支持原生性。 ## 本章内容 diff --git a/02_basic_concept/2.3_repository.md b/02_basic_concept/2.3_repository.md index 362c2e4..0c7dd2a 100644 --- a/02_basic_concept/2.3_repository.md +++ b/02_basic_concept/2.3_repository.md @@ -251,9 +251,9 @@ someuser/myapp # ⚠️ 需要评估 #### 镜像签名 -当前更推荐使用 Sigstore / Notation 体系进行镜像签名与验证。`Docker Content Trust (DCT)` 已进入退场阶段,不建议作为新项目主方案。 +当前更推荐使用 Sigstore / Notation 体系进行镜像签名与验证。`Docker Content Trust (DCT)` 已于 2025 年 8 月 8 日开始停用,官方 Docker 镜像已停止 DCT 签名,2028 年 3 月 31 日将完全删除此功能,不建议作为新项目方案。 -> 注意:Cosign 默认会把签名写回镜像所在仓库,请使用你有推送权限的镜像地址。 +> 注意:Cosign 默认会把签名推送回镜像所在仓库,请使用你有推送权限的镜像地址。 ```bash ## 准备一个你有写权限的镜像地址 diff --git a/04_image/4.5_build.md b/04_image/4.5_build.md index cfc96a2..14d47f6 100644 --- a/04_image/4.5_build.md +++ b/04_image/4.5_build.md @@ -11,7 +11,7 @@ Docker 提供了 `docker init` 命令,可以根据项目类型自动生成 Doc ```bash $ docker init ``` -该命令会交互式地询问项目类型 (如 Go、Node.js、Python、Rust 等),并生成符合最佳实践的配置文件。对于新项目,这是推荐的起步方式。 +该命令会交互式地询问项目类型(支持 Go、Node.js、Python、Rust、Java、ASP.NET Core、PHP 等),并生成符合最佳实践的配置文件。对于新项目,这是推荐的起步方式。 ### 4.5.2 手动创建 Dockerfile diff --git a/05_container/5.5_import_export.md b/05_container/5.5_import_export.md index 700a494..77dfe3a 100644 --- a/05_container/5.5_import_export.md +++ b/05_container/5.5_import_export.md @@ -20,7 +20,7 @@ $ docker export 7691a814370e > ubuntu.tar ```bash $ cat ubuntu.tar | docker import - test/ubuntu:v1.0 $ docker image ls -REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE +REPOSITORY TAG IMAGE ID CREATED SIZE test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB ``` 此外,也可以通过指定 URL 或者某个目录来导入,例如 diff --git a/06_repository/6.1_dockerhub.md b/06_repository/6.1_dockerhub.md index 81f364d..b55ea7e 100644 --- a/06_repository/6.1_dockerhub.md +++ b/06_repository/6.1_dockerhub.md @@ -112,7 +112,7 @@ $ echo "dckr_pat_xxxxxxx" | docker login --username username --password-stdin #### 3. 关注镜像漏洞 -Docker Hub 会对官方镜像和付费用户的镜像进行安全扫描。在镜像标签页可以看到漏洞扫描结果。 +Docker Hub 提供 Docker Scout 安全扫描功能。官方镜像的漏洞扫描结果对所有用户免费可见。Docker Scout 的持续扫描功能在免费层可以覆盖 1 个私有仓库,付费用户可以扫描更多仓库。在镜像标签页可以看到漏洞扫描结果。 --- diff --git a/06_repository/6.2_registry.md b/06_repository/6.2_registry.md index 4f91d3c..b41e82b 100644 --- a/06_repository/6.2_registry.md +++ b/06_repository/6.2_registry.md @@ -4,7 +4,7 @@ 本节介绍如何使用本地仓库。 -[Docker Registry](https://docs.docker.com/registry/) 是官方提供的工具,可以用于构建私有的镜像仓库。本文内容基于 [docker/distribution](https://github.com/docker/distribution) v2.x 版本。 +[Docker Registry](https://docs.docker.com/registry/) 是官方提供的工具,可以用于构建私有的镜像仓库。本文内容基于 [distribution/distribution](https://github.com/distribution/distribution) v2.x 版本。 ### 6.2.1 安装运行 docker-registry diff --git a/07_dockerfile/7.12_healthcheck.md b/07_dockerfile/7.12_healthcheck.md index e71945a..45232f6 100644 --- a/07_dockerfile/7.12_healthcheck.md +++ b/07_dockerfile/7.12_healthcheck.md @@ -186,4 +186,14 @@ HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1 健康检查应主要关注 **当前服务** 是否可用,而不是检查其下游依赖 (数据库等)。下游依赖的检查应由应用逻辑处理。 +#### 5. 与容器编排平台的关系 + +不同平台对 HEALTHCHECK 的支持有所不同: + +- **Docker Compose**:直接使用 Dockerfile 中定义的 HEALTHCHECK,也可在 `compose.yaml` 中覆盖 +- **Docker Swarm**:使用 HEALTHCHECK 进行服务健康判断和滚动更新决策 +- **Kubernetes**:**忽略** Dockerfile 中的 HEALTHCHECK,使用自己的 `livenessProbe` 和 `readinessProbe` 机制 + +如果应用同时部署在 Docker Compose 和 Kubernetes 环境中,建议在 Dockerfile 中保留 HEALTHCHECK(供 Compose 使用),同时在 Kubernetes 的 Pod 配置中定义对应的探针。 + --- diff --git a/07_dockerfile/7.1_run.md b/07_dockerfile/7.1_run.md index 8606e30..327c552 100644 --- a/07_dockerfile/7.1_run.md +++ b/07_dockerfile/7.1_run.md @@ -158,4 +158,41 @@ RUN --mount=type=cache,target=/go/pkg/mod \ RUN --mount=type=secret,id=mysecret \ cat /run/secrets/mysecret ``` + +#### 3. Heredoc 语法 + +BuildKit 支持使用 heredoc 语法编写多行脚本,无需行末反斜杠 `\` 连接: + +```docker +RUN < 💡 使用 heredoc 需要在 Dockerfile 首行声明 BuildKit 语法版本:`# syntax=docker/dockerfile:1` + --- diff --git a/07_dockerfile/7.2_copy.md b/07_dockerfile/7.2_copy.md index 1230996..f34598c 100644 --- a/07_dockerfile/7.2_copy.md +++ b/07_dockerfile/7.2_copy.md @@ -203,6 +203,11 @@ COPY --link --from=builder /app/dist /usr/share/nginx/html - 并行化构建过程 - 加速多阶段构建 +> ⚠️ **注意**:使用 `--link` 需要满足以下条件: +> - 启用 BuildKit(Docker Engine 23.0+ 默认启用) +> - Dockerfile 语法版本 1.4 或更高(在首行声明 `# syntax=docker/dockerfile:1`) +> - 目标路径在前序指令中应不存在或为空目录 + --- ### 7.2.9 dockerignore diff --git a/11_compose/11.3_usage.md b/11_compose/11.3_usage.md index 1173418..9ca177f 100644 --- a/11_compose/11.3_usage.md +++ b/11_compose/11.3_usage.md @@ -117,3 +117,5 @@ $ docker compose run web python app.py $ docker compose config $ docker compose down ``` + +> 💡 `docker compose down` 默认会删除容器和网络,但 **保留数据卷**。如需同时删除数据卷,请使用 `docker compose down -v`。 diff --git a/11_compose/11.5_compose_file.md b/11_compose/11.5_compose_file.md index 59d0369..ad424db 100644 --- a/11_compose/11.5_compose_file.md +++ b/11_compose/11.5_compose_file.md @@ -493,7 +493,14 @@ mac_address: 08-00-27-00-0C-0A ```yaml privileged: true ``` -指定容器退出后的重启策略为始终重启。该命令对保持服务始终运行十分有效,在生产环境中推荐配置为 `always` 或者 `unless-stopped`。 +指定容器退出后的重启策略。该命令对保持服务始终运行十分有效,在生产环境中推荐配置为 `always` 或者 `unless-stopped`。 + +| 策略 | 说明 | +|------|------| +| `no` | 默认值,不自动重启 | +| `always` | 无论退出码如何,始终重启;Docker 守护进程启动时也会重启 | +| `on-failure[:max-retries]` | 仅在非零退出码时重启,可指定最大重试次数 | +| `unless-stopped` | 类似 `always`,但手动停止的容器在守护进程重启后不会自动启动 | ```yaml restart: always @@ -514,7 +521,33 @@ stdin_open: true tty: true ``` -### 11.5.34 读取变量 +### 11.5.34 `profiles` + +`profiles` 用于按场景选择性启动服务。未指定 `profiles` 的服务默认始终启动;标记了 `profiles` 的服务仅在激活对应 profile 时才启动。 + +```yaml +services: + web: + image: nginx + + debug: + image: busybox + profiles: + - debug + + test: + image: node + profiles: + - test +``` +启动时通过 `--profile` 激活: + +```bash +$ docker compose --profile debug up # 启动 web + debug +$ docker compose up # 仅启动 web +``` + +### 11.5.35 读取变量 Compose 模板文件支持动态读取主机的系统环境变量和当前目录下的 `.env` 文件中的变量。 diff --git a/13_kubernetes_concepts/13.2_concepts.md b/13_kubernetes_concepts/13.2_concepts.md index 4499702..6007b07 100644 --- a/13_kubernetes_concepts/13.2_concepts.md +++ b/13_kubernetes_concepts/13.2_concepts.md @@ -166,7 +166,7 @@ spec: spec: containers: - name: nginx - image: nginx:1.27 + image: nginx:1.30 ports: - containerPort: 80 ``` diff --git a/15_etcd/15.3_cluster.md b/15_etcd/15.3_cluster.md index 44a2fb4..82acea4 100644 --- a/15_etcd/15.3_cluster.md +++ b/15_etcd/15.3_cluster.md @@ -8,7 +8,7 @@ services: node1: - image: quay.io/coreos/etcd:v3.5.17 + image: quay.io/coreos/etcd:v3.5.21 volumes: - node1-data:/etcd-data expose: @@ -40,7 +40,7 @@ services: - docker-etcd node2: - image: quay.io/coreos/etcd:v3.5.17 + image: quay.io/coreos/etcd:v3.5.21 volumes: - node2-data:/etcd-data networks: @@ -72,7 +72,7 @@ services: - docker-etcd node3: - image: quay.io/coreos/etcd:v3.5.17 + image: quay.io/coreos/etcd:v3.5.21 volumes: - node3-data:/etcd-data networks: diff --git a/17_ecosystem/17.2_coreos_install.md b/17_ecosystem/17.2_coreos_install.md index 0489835..1fac31d 100644 --- a/17_ecosystem/17.2_coreos_install.md +++ b/17_ecosystem/17.2_coreos_install.md @@ -43,5 +43,5 @@ $ sudo coreos-installer install /dev/sda --ignition-file example.ign ```bash $ ssh core@虚拟机IP -$ docker --version +$ podman --version ``` diff --git a/17_ecosystem/17.6_containerd.md b/17_ecosystem/17.6_containerd.md index 13075c1..1f76a38 100644 --- a/17_ecosystem/17.6_containerd.md +++ b/17_ecosystem/17.6_containerd.md @@ -35,7 +35,7 @@ Kubernetes 作为一个容器编排系统,为了屏蔽底层不同容器运行 - 早期版本中,Kubernetes 默认使用 docker 作为运行时,通过一个名为 `dockershim` 的桥接组件对接 Docker,Docker 再对接 containerd。 - 随着 containerd 原生支持了 CRI 插件,Kubernetes 开始直接与 containerd 通信,去掉了 `dockershim` 和 `dockerd` 的中间层。这就是为什么从 Kubernetes v1.24 开始”弃用 Docker”引发了广泛关注,实际上 Kubernetes 只是弃用 `dockershim`,底层依然在使用从 Docker 基因中诞生的 containerd。 -- containerd 2.0 移除了已弃用的 CRI v1alpha2 接口,仅保留 CRI v1(Kubernetes 自 v1.23 起已支持 CRI v1)。如果集群中仍有依赖 CRI v1alpha2 的组件,升级 containerd 2.x 前需先完成迁移。 +- containerd 2.0 移除了已弃用的 CRI v1alpha2 接口,仅保留 CRI v1(Kubernetes 自 v1.26 起仅支持 CRI v1)。如果集群中仍有依赖 CRI v1alpha2 的组件,升级 containerd 2.x 前需先完成迁移。 ### 为什么直接使用 containerd?