diff --git a/01_introduction/1.1_quickstart.md b/01_introduction/1.1_quickstart.md index b53ef61..63eddb0 100644 --- a/01_introduction/1.1_quickstart.md +++ b/01_introduction/1.1_quickstart.md @@ -26,7 +26,7 @@ Nginx 是一个轻量级、使用广泛的 Web 服务器,学习完这个例子 ### 1.1.2 编写 Dockerfile -在同级目录下创建一个名为 `Dockerfile` (无后缀) 的文件: +在同级目录下创建一个名为 `Dockerfile`(无后缀)的文件: ```dockerfile FROM nginx:alpine @@ -42,7 +42,7 @@ $ docker build -t my-hello-world . ``` * `docker build`:构建命令 -* `-t my-hello-world`:给镜像起个名字 (标签) +* `-t my-hello-world`:给镜像起个名字(标签) * `.`:指定上下文路径为当前目录 ### 1.1.4 运行容器 diff --git a/01_introduction/1.2_what.md b/01_introduction/1.2_what.md index 038faa6..f8391f6 100644 --- a/01_introduction/1.2_what.md +++ b/01_introduction/1.2_what.md @@ -67,15 +67,15 @@ flowchart LR | **隔离级别** | 进程级隔离 | 完全隔离 | | **单机数量** | 可运行上千个 | 通常几十个 | -> 笔者经常用这个类比来解释:虚拟机像是每个应用都住在一栋独立的房子里 (有自己的地基、水电系统),而容器像是大家住在同一栋公寓楼里的不同房间 (共享地基和水电系统,但各自独立)。 +> 笔者经常用这个类比来解释:虚拟机像是每个应用都住在一栋独立的房子里(有自己的地基、水电系统),而容器像是大家住在同一栋公寓楼里的不同房间(共享地基和水电系统,但各自独立)。 ### 1.2.4 Docker 的技术基础 Docker 使用 [Go 语言](https://golang.google.cn/)开发,基于 Linux 内核的以下技术: -- **[Namespace](https://en.wikipedia.org/wiki/Linux_namespaces)**:实现资源隔离 (进程、网络、文件系统等) -- **[Cgroups](https://zh.wikipedia.org/wiki/Cgroups)**:实现资源限制 (CPU、内存、I/O 等) -- **[Union FS](https://en.wikipedia.org/wiki/Union_mount)**:实现分层存储 (如 OverlayFS) +- **[Namespace](https://en.wikipedia.org/wiki/Linux_namespaces)**:实现资源隔离(进程、网络、文件系统等) +- **[Cgroups](https://zh.wikipedia.org/wiki/Cgroups)**:实现资源限制(CPU、内存、I/O 等) +- **[Union FS](https://en.wikipedia.org/wiki/Union_mount)**:实现分层存储(如 OverlayFS) > 如果你对这些底层技术感兴趣,可以阅读本书的[底层实现](../12_implementation/README.md)章节。 @@ -96,7 +96,7 @@ flowchart LR - **LXC** (2013):Docker 最初基于 Linux Containers - **libcontainer** (2014,Docker 0.9):Docker 自研的容器运行时 -- **runC** (2015,Docker 1.11 整合):捐献给 OCI 的标准容器运行时 +- **runC**(2015,Docker 1.11 整合):捐献给 OCI 的标准容器运行时 - **containerd**:高级容器运行时,管理容器生命周期 ![Docker 架构](../_images/docker-on-linux.png) diff --git a/01_introduction/1.3_why.md b/01_introduction/1.3_why.md index d8449bd..f49d62c 100644 --- a/01_introduction/1.3_why.md +++ b/01_introduction/1.3_why.md @@ -82,7 +82,7 @@ $ docker compose up #### 2. 秒级启动 -传统虚拟机启动需要几分钟 (引导操作系统),而 Docker 容器启动通常只需要 **几秒甚至几百毫秒**。 +传统虚拟机启动需要几分钟(引导操作系统),而 Docker 容器启动通常只需要 **几秒甚至几百毫秒**。 笔者实测数据: @@ -153,7 +153,7 @@ flowchart LR Docker 可以在几乎任何平台上运行: - ✅ 本地开发机 (macOS、Windows、Linux) -- ✅ 公有云 (AWS、Azure、GCP、阿里云、腾讯云) +- ✅ 公有云(AWS、Azure、GCP、阿里云、腾讯云) - ✅ 私有云和自建数据中心 - ✅ 边缘设备和 IoT diff --git a/01_introduction/README.md b/01_introduction/README.md index d471d18..50ced36 100644 --- a/01_introduction/README.md +++ b/01_introduction/README.md @@ -10,7 +10,7 @@ * 通过一个简单的 Web 应用例子,带你快速体验 Docker 的核心流程:构建镜像、运行容器。 * [什么是 Docker](1.2_what.md) - * 介绍 Docker 的起源、发展历程以及其背后的核心技术 (Cgroups,Namespaces,UnionFS,以及 `containerd` 引擎的演进)。 + * 介绍 Docker 的起源、发展历程以及其背后的核心技术(Cgroups,Namespaces,UnionFS,以及 `containerd` 引擎的演进)。 * 了解 Docker 是如何改变软件交付方式的。 * [为什么要用 Docker](1.3_why.md) diff --git a/02_basic_concept/2.1_image.md b/02_basic_concept/2.1_image.md index 8006393..7cc1cec 100644 --- a/02_basic_concept/2.1_image.md +++ b/02_basic_concept/2.1_image.md @@ -28,7 +28,7 @@ flowchart TD ``` 对于 Linux 而言,内核启动后会挂载 `root` 文件系统来提供用户空间支持。**Docker 镜像** 本质上就是一个 `root` 文件系统。 -例如,官方镜像 `ubuntu:24.04` 包含了一套完整的 Ubuntu 24.04 最小系统的 root 文件系统——但 **不包含 Linux 内核** (因为容器共享宿主机的内核)。 +例如,官方镜像 `ubuntu:24.04` 包含了一套完整的 Ubuntu 24.04 最小系统的 root 文件系统——但 **不包含 Linux 内核**(因为容器共享宿主机的内核)。 ### 2.1.3 镜像包含什么? @@ -210,5 +210,5 @@ Docker 镜像可以通过以下方式获取: |------|------|------| | **从 Registry 拉取** | 最常用的方式 | `docker pull nginx` | | **从 Dockerfile 构建** | 自定义镜像 | `docker build -t myapp .` | -| **从容器提交** | 保存容器状态 (不推荐)| `docker commit` | +| **从容器提交** | 保存容器状态(不推荐)| `docker commit` | | **从文件导入** | 离线传输 | `docker load < image.tar` | diff --git a/02_basic_concept/2.2_container.md b/02_basic_concept/2.2_container.md index 8df111d..748f4c5 100644 --- a/02_basic_concept/2.2_container.md +++ b/02_basic_concept/2.2_container.md @@ -81,7 +81,7 @@ flowchart TD #### 镜像层 + 容器层 -当容器运行时,Docker 会在镜像的只读层之上创建一个 **可写层** (容器存储层): +当容器运行时,Docker 会在镜像的只读层之上创建一个 **可写层**(容器存储层): ```mermaid flowchart TD diff --git a/02_basic_concept/2.3_repository.md b/02_basic_concept/2.3_repository.md index 27572ec..f4ea474 100644 --- a/02_basic_concept/2.3_repository.md +++ b/02_basic_concept/2.3_repository.md @@ -49,8 +49,8 @@ flowchart TB | 概念 | 说明 | 示例 | |------|------|------| | **Registry** | 存储镜像的服务 | Docker Hub、ghcr.io | -| **Repository (仓库)** | 同一软件的镜像集合 | `nginx`、`mysql`、`mycompany/myapp` | -| **Tag (标签)** | 仓库内的版本标识 | `latest`、`1.28`、`alpine` | +| **Repository(仓库)** | 同一软件的镜像集合 | `nginx`、`mysql`、`mycompany/myapp` | +| **Tag(标签)** | 仓库内的版本标识 | `latest`、`1.28`、`alpine` | #### 镜像的完整名称 @@ -97,7 +97,7 @@ us-west1-docker.pkg.dev/my-project/my-repo/myapp:v1.0 **特点**: -- 拥有大量[官方镜像](https://hub.docker.com/search?q=&type=image&image_filter=official) (nginx、mysql、redis 等) +- 拥有大量[官方镜像](https://hub.docker.com/search?q=&type=image&image_filter=official)(nginx、mysql、redis 等) - 免费账户可以创建公开仓库 - 免费个人账户可创建 1 个私有仓库;更高套餐支持更多私有仓库 @@ -172,8 +172,8 @@ $ docker pull localhost:5000/myapp:v1.0 | 方案 | 特点 | |------|------| -| **[Harbor](https://goharbor.io/)** | CNCF 项目,功能全面 (用户管理、漏洞扫描、镜像签名)| -| **[Nexus Repository](../06_repository/6.4_nexus3_registry.md)** | 支持多种制品类型 (Docker、Maven、npm 等)| +| **[Harbor](https://goharbor.io/)** | CNCF 项目,功能全面(用户管理、漏洞扫描、镜像签名)| +| **[Nexus Repository](../06_repository/6.4_nexus3_registry.md)** | 支持多种制品类型(Docker、Maven、npm 等)| | **云厂商服务** | 阿里云 ACR、腾讯云 TCR、AWS ECR 等 | 笔者建议: @@ -238,7 +238,7 @@ $ docker logout #### 使用官方镜像 -Docker Hub 的[官方镜像](https://hub.docker.com/search?q=&type=image&image_filter=official) (标有 “Official Image” 标识) 经过 Docker 团队审核,相对更安全。示例如下: +Docker Hub 的[官方镜像](https://hub.docker.com/search?q=&type=image&image_filter=official)(标有 “Official Image” 标识)经过 Docker 团队审核,相对更安全。示例如下: ```bash ## 官方镜像示例 diff --git a/02_basic_concept/README.md b/02_basic_concept/README.md index 4e5a3e1..97bfc8c 100644 --- a/02_basic_concept/README.md +++ b/02_basic_concept/README.md @@ -4,7 +4,7 @@ **Docker** 包括三个基本概念: -* **镜像** (`Image`):Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数 (如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。 +* **镜像** (`Image`):Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。 * **容器** (`Container`):镜像 (`Image`) 和容器 (`Container`) 的关系,就像是面向对象程序设计中的 `类` 和 `实例` 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。 * **仓库** (`Repository`):镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。 diff --git a/03_install/3.2_debian.md b/03_install/3.2_debian.md index f1dac08..b092162 100644 --- a/03_install/3.2_debian.md +++ b/03_install/3.2_debian.md @@ -17,8 +17,8 @@ Debian 以其稳定性著称,是 Docker 的理想宿主系统。本节将指 Docker 支持以下版本的 [Debian](https://www.debian.org/intro/about) 操作系统(具体以官方 [安装文档](https://docs.docker.com/engine/install/debian/) 为准): * Debian Trixie 13 (stable) -* Debian Bookworm 12 (oldstable,全面支持至 2026 年 6 月 10 日,LTS 至 2028 年 6 月 30 日) -* Debian Bullseye 11 (oldoldstable,LTS 支持至 2026 年 8 月 31 日) +* Debian Bookworm 12(oldstable,全面支持至 2026 年 6 月 10 日,LTS 至 2028 年 6 月 30 日) +* Debian Bullseye 11(oldoldstable,LTS 支持至 2026 年 8 月 31 日) > **注意**:Debian Bullseye 11 将于 2026 年 8 月底结束长期支持。建议新部署使用 Bookworm 12 或 Trixie 13。 diff --git a/03_install/3.4_centos.md b/03_install/3.4_centos.md index 283997a..1a60529 100644 --- a/03_install/3.4_centos.md +++ b/03_install/3.4_centos.md @@ -1,6 +1,6 @@ ## 3.4 CentOS -CentOS (及其替代品 Rocky Linux、AlmaLinux) 是企业级服务器常用的操作系统。本节介绍在这些系统上安装 Docker 的步骤。 +CentOS(及其替代品 Rocky Linux、AlmaLinux)是企业级服务器常用的操作系统。本节介绍在这些系统上安装 Docker 的步骤。 ### 企业级部署的版本选择 diff --git a/03_install/3.7_mac.md b/03_install/3.7_mac.md index a63eddd..8148173 100644 --- a/03_install/3.7_mac.md +++ b/03_install/3.7_mac.md @@ -32,7 +32,7 @@ Docker Desktop 为 Mac 用户提供了标准的图形化安装体验。官方当 > 如果你的电脑搭载的是 Apple Silicon 芯片(`arm64` 架构),请使用 [Docker Desktop for Mac Apple Silicon 版](https://desktop.docker.com/mac/main/arm64/Docker.dmg)。 -如同 macOS 其它软件一样,安装也非常简单,双击下载的 `.dmg` 文件,然后将那只叫 [Moby](https://www.docker.com/blog/call-me-moby-dock/) 的鲸鱼图标拖拽到 `Application` 文件夹即可 (其间需要输入用户密码)。 +如同 macOS 其它软件一样,安装也非常简单,双击下载的 `.dmg` 文件,然后将那只叫 [Moby](https://www.docker.com/blog/call-me-moby-dock/) 的鲸鱼图标拖拽到 `Application` 文件夹即可(其间需要输入用户密码)。 ![图](../_images/install-mac-dmg.jpg) diff --git a/03_install/3.9_mirror.md b/03_install/3.9_mirror.md index 60b9442..d4962ac 100644 --- a/03_install/3.9_mirror.md +++ b/03_install/3.9_mirror.md @@ -27,7 +27,7 @@ $ systemctl cat docker | grep '\-\-registry\-mirror' ``` 如果该命令有输出,那么请执行 `$ systemctl cat docker` 查看 `ExecStart=` 出现的位置,修改对应的文件内容去掉 `--registry-mirror` 参数及其值,并按接下来的步骤进行配置。 -如果以上命令没有任何输出,那么就可以在 `/etc/docker/daemon.json` 中写入如下内容 (如果文件不存在请新建该文件): +如果以上命令没有任何输出,那么就可以在 `/etc/docker/daemon.json` 中写入如下内容(如果文件不存在请新建该文件): ```json { diff --git a/04_image/4.1_pull.md b/04_image/4.1_pull.md index a5dea66..0fd988d 100644 --- a/04_image/4.1_pull.md +++ b/04_image/4.1_pull.md @@ -30,7 +30,7 @@ Registry地址 用户名 仓库名 标签 | 组成部分 | 说明 | 默认值 | |---------|------|--------| | Registry 地址 | 镜像仓库地址 | `docker.io` (Docker Hub)| -| 用户名 | 镜像所属用户/组织 | `library` (官方镜像)| +| 用户名 | 镜像所属用户/组织 | `library`(官方镜像)| | 仓库名 | 镜像名称 | 必须指定 | | 标签 | 版本标识 | `latest` | @@ -83,7 +83,7 @@ docker.io/library/ubuntu:24.04 | 输出内容 | 说明 | |---------|------| | `Pulling from library/ubuntu` | 正在从官方 ubuntu 仓库拉取 | -| `92dc2a97ff99: Pull complete` | 各层的下载状态 (显示层 ID 前 12 位)| +| `92dc2a97ff99: Pull complete` | 各层的下载状态(显示层 ID 前 12 位)| | `Digest: sha256:...` | 镜像内容的唯一摘要 | | `docker.io/library/ubuntu:24.04` | 镜像的完整名称 | @@ -211,7 +211,7 @@ $ docker pull ubuntu@sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9 1. 配置镜像加速器 2. 检查网络连接 -3. 尝试拉取更小的镜像版本 (如 `alpine` 变体) +3. 尝试拉取更小的镜像版本(如 `alpine` 变体) #### Q:提示镜像不存在 @@ -221,7 +221,7 @@ Error: pull access denied, repository does not exist 可能原因: - 镜像名拼写错误 -- 私有镜像未登录 (需要 `docker login`) +- 私有镜像未登录(需要 `docker login`) - 镜像确实不存在 #### Q:磁盘空间不足 diff --git a/04_image/4.2_list.md b/04_image/4.2_list.md index 215b70d..b9f1c84 100644 --- a/04_image/4.2_list.md +++ b/04_image/4.2_list.md @@ -25,8 +25,8 @@ ubuntu noble 329ed837d508 3 days ago 78MB | 字段 | 说明 | |------|------| | **REPOSITORY** | 仓库名 | -| **TAG** | 标签 (版本)| -| **IMAGE ID** | 镜像唯一标识 (短 ID,前 12 位)| +| **TAG** | 标签(版本)| +| **IMAGE ID** | 镜像唯一标识(短 ID,前 12 位)| | **CREATED** | 创建时间 | | **SIZE** | 本地占用空间 | diff --git a/04_image/4.3_rm.md b/04_image/4.3_rm.md index 3bcec72..3a34825 100644 --- a/04_image/4.3_rm.md +++ b/04_image/4.3_rm.md @@ -19,7 +19,7 @@ $ docker image rm [选项] <镜像1> [<镜像2> ...] | 方式 | 说明 | 示例 | |------|------|------| -| **短 ID** | ID 的前几位 (通常 3-4 位)| `docker rmi 501` | +| **短 ID** | ID 的前几位(通常 3-4 位)| `docker rmi 501` | | **长 ID** | 完整的镜像 ID | `docker rmi 501ad78535f0...` | | **镜像名:标签** | 仓库名和标签 | `docker rmi redis:7.0` | | **镜像摘要** | 精确的内容摘要 | `docker rmi nginx@sha256:...` | @@ -229,7 +229,7 @@ Error: image has dependent child images ### 4.3.7 清理策略 -针对不同的环境 (开发环境 vs 生产环境),我们应该采用不同的镜像清理策略。 +针对不同的环境(开发环境 vs 生产环境),我们应该采用不同的镜像清理策略。 #### 开发环境 diff --git a/04_image/4.4_commit.md b/04_image/4.4_commit.md index 79f177c..48839be 100644 --- a/04_image/4.4_commit.md +++ b/04_image/4.4_commit.md @@ -64,7 +64,7 @@ A /var/cache/nginx/uwsgi_temp 现在我们定制好了变化,我们希望能将其保存下来形成镜像。 -要知道,当我们运行一个容器的时候 (如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里。而 Docker 提供了一个 `docker commit` 命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。 +要知道,当我们运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里。而 Docker 提供了一个 `docker commit` 命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。 `docker commit` 的语法格式为: diff --git a/04_image/4.5_build.md b/04_image/4.5_build.md index 219f831..b750cfd 100644 --- a/04_image/4.5_build.md +++ b/04_image/4.5_build.md @@ -72,7 +72,7 @@ RUN echo '

Hello, Docker!

' > /usr/share/nginx/html/index.html > > 每一个 `RUN` 指令都会产生一个新的镜像层。为了减少镜像体积和层数,我们通常会将多个命令合并到一个 `RUN` 指令中执行。 > -> 更多关于 `RUN` 指令的详细用法、最佳实践 (如清理缓存、使用 pipefail 等) 及 `Union FS` 的层数限制等内容,请参阅 **[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)** 中的 **[RUN 指令](../07_dockerfile/7.1_run.md)** 小节。 +> 更多关于 `RUN` 指令的详细用法、最佳实践(如清理缓存、使用 pipefail 等)及 `Union FS` 的层数限制等内容,请参阅 **[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)** 中的 **[RUN 指令](../07_dockerfile/7.1_run.md)** 小节。 要想编写优秀的 `Dockerfile`,必须了解每一条指令的作用和副作用。在 **[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)** 中,我们将对 `COPY`,`ADD`,`CMD`,`ENTRYPOINT` 等指令进行详细讲解。 diff --git a/04_image/4.6_other.md b/04_image/4.6_other.md index 174e3cc..c996bab 100644 --- a/04_image/4.6_other.md +++ b/04_image/4.6_other.md @@ -63,7 +63,7 @@ filename: POSIX tar archive ``` 这里的 filename 可以为任意名称甚至任意后缀名,但文件的本质都是归档文件 -**注意:如果同名则会覆盖 (没有警告)** +**注意:如果同名则会覆盖(没有警告)** 若使用 `gzip` 压缩: diff --git a/04_image/4.7_internal.md b/04_image/4.7_internal.md index 8394eba..60f59c5 100644 --- a/04_image/4.7_internal.md +++ b/04_image/4.7_internal.md @@ -10,11 +10,11 @@ Docker 镜像并不是一个单纯的文件,而是由一组文件系统叠加 最底层的镜像称为 **基础镜像 (Base Image)**,通常是各种 Linux 发行版的 root 文件系统,如 Ubuntu、Debian、CentOS 等。 -当我们在基础镜像之上构建新的镜像时 (例如安装了 Nginx),Docker 并不是复制一份基础镜像,而是在基础镜像之上,**新建一个层 (Layer)**,并在该层中仅记录为了安装 Nginx 而发生的文件变更 (添加、修改、删除)。 +当我们在基础镜像之上构建新的镜像时(例如安装了 Nginx),Docker 并不是复制一份基础镜像,而是在基础镜像之上,**新建一个层 (Layer)**,并在该层中仅记录为了安装 Nginx 而发生的文件变更(添加、修改、删除)。 这种分层存储结构使得镜像的复用、分发变得非常高效: -* **复用**:如果多个镜像都基于同一个基础镜像 (例如都基于 `ubuntu:24.04`),那么宿主机只需要下载一份 `ubuntu:24.04`,所有镜像都可以共享它。 +* **复用**:如果多个镜像都基于同一个基础镜像(例如都基于 `ubuntu:24.04`),那么宿主机只需要下载一份 `ubuntu:24.04`,所有镜像都可以共享它。 * **轻量分发**:镜像可以复用已有层,只传输和存储新增差异层;不过镜像是否足够小,仍然取决于基础镜像和新增内容本身。 ### 4.7.2 容器层与读写 @@ -39,13 +39,13 @@ flowchart TD Note["所有的写操作都在容器层这里"] -.-> L4 ``` -* **读取文件**:当容器需要读取文件时,Docker 会从最上层 (容器层) 开始向下层 (镜像层) 寻找,直到找到该文件为止。 +* **读取文件**:当容器需要读取文件时,Docker 会从最上层(容器层)开始向下层(镜像层)寻找,直到找到该文件为止。 * **修改文件**:当容器需要修改某个文件时,Docker 会从下层镜像中将该文件复制到上层的容器层,然后对副本进行修改。这被称为 **写时复制 (Copy-on-Write,CoW)** 策略。 -* **删除文件**:当容器删除某个文件时,Docker 并不是真的去下层删除它 (因为下层是只读的),而是在容器层创建一个特殊的 “白障 (Whiteout)” 文件,用来标记该文件已被删除,从而在容器视图中隐藏它。 +* **删除文件**:当容器删除某个文件时,Docker 并不是真的去下层删除它(因为下层是只读的),而是在容器层创建一个特殊的 “白障 (Whiteout)” 文件,用来标记该文件已被删除,从而在容器视图中隐藏它。 这就是为什么: -1. **容器删除后数据会丢失**:因为所有的数据修改都保存在最上层的容器层中,容器销毁时,这个层也就随之销毁了。(除非使用了数据卷,详见[数据管理](../08_data/README.md))。 +1. **容器删除后数据会丢失**:因为所有的数据修改都保存在最上层的容器层中,容器销毁时,这个层也就随之销毁了。(除非使用了数据卷,详见[数据管理](../08_data/README.md))。 2. **镜像不可变**:无论我们在容器里删除了多少文件,基础镜像的体积并不会减小,因为它们依然存在于底层的只读层中。 ### 4.7.3 内容寻址与镜像 ID @@ -54,7 +54,7 @@ Docker 镜像的每一层都有一个唯一的 ID,这个 ID 是根据该层的 * **内容即 ID**:只要层的内容有一丁点变化,ID 就会变。 * **安全性**:确保了镜像内容的完整性,下载过程中如果数据损坏,ID 校验就会失败。 -* **去重**:如果两个不同的镜像 (甚至是不同来源的镜像) 包含相同的层 (ID 相同),Docker 引擎在本地只会存储一份,绝不重复下载。 +* **去重**:如果两个不同的镜像(甚至是不同来源的镜像)包含相同的层(ID 相同),Docker 引擎在本地只会存储一份,绝不重复下载。 ### 4.7.4 联合文件系统 diff --git a/05_container/5.2_daemon.md b/05_container/5.2_daemon.md index dd0015f..60ee952 100644 --- a/05_container/5.2_daemon.md +++ b/05_container/5.2_daemon.md @@ -39,7 +39,7 @@ $ docker run -d ubuntu:24.04 /bin/sh -c "while true; do echo hello world; sleep - 容器在后台运行 - 返回容器的完整 ID - 终端立即释放,可以继续执行其他命令 -- 输出不会直接显示 (需要用 `docker logs` 查看) +- 输出不会直接显示(需要用 `docker logs` 查看) ### 5.2.3 深入理解:容器为什么会 “立即退出”? @@ -66,7 +66,7 @@ flowchart TD 1. 容器启动 2. 没有指定命令,默认执行 `/bin/bash` -3. 但没有交互式终端 (没有 `-it` 参数),bash 发现没有输入源 +3. 但没有交互式终端(没有 `-it` 参数),bash 发现没有输入源 4. bash 立即退出 5. 主进程退出,容器停止 @@ -102,7 +102,7 @@ hello world hello world ... ``` -**实时查看日志** (类似 `tail -f`): +**实时查看日志**(类似 `tail -f`): ```bash $ docker container logs -f 77b2dc01fe0f diff --git a/05_container/5.3_stop.md b/05_container/5.3_stop.md index b044c00..0f829c6 100644 --- a/05_container/5.3_stop.md +++ b/05_container/5.3_stop.md @@ -113,8 +113,8 @@ c5d3a5e8f7b2 nginx "nginx" Up 5 minutes mynginx | 状态 | 说明 | |------|------| | `Up X minutes` | 运行中 | -| `Exited (0)` | 正常退出 (退出码 0)| -| `Exited (1)` | 异常退出 (非零退出码)| +| `Exited (0)` | 正常退出(退出码 0)| +| `Exited (1)` | 异常退出(非零退出码)| | `Exited (137)` | 被 SIGKILL 终止 (128 + 9)| | `Exited (143)` | 被 SIGTERM 终止 (128 + 15)| diff --git a/05_container/5.4_attach_exec.md b/05_container/5.4_attach_exec.md index 55a85c1..2919e1c 100644 --- a/05_container/5.4_attach_exec.md +++ b/05_container/5.4_attach_exec.md @@ -43,7 +43,7 @@ $ docker exec -it 容器名 /bin/sh | `-i` | 保持标准输入打开 (interactive)| | `-t` | 分配伪终端 (TTY)| | `-it` | 两者组合,获得完整交互体验 | -| `-u` | 指定用户 (如 `-u root`)| +| `-u` | 指定用户(如 `-u root`)| | `-w` | 指定工作目录 | | `-e` | 设置环境变量 | @@ -235,13 +235,13 @@ $ docker exec myapp python manage.py migrate 笔者建议:生产环境应尽量避免进入容器直接操作,而是通过: -- 日志系统查看日志 (如 `docker logs` 或集中式日志) +- 日志系统查看日志(如 `docker logs` 或集中式日志) - 监控系统查看状态 - 重新部署而非手动修改 #### 3. 无 shell 镜像的处理 -某些精简镜像 (如基于 `scratch` 或 `distroless`) 没有 shell: +某些精简镜像(如基于 `scratch` 或 `distroless`)没有 shell: ```bash ## 这会失败 diff --git a/05_container/5.5_import_export.md b/05_container/5.5_import_export.md index 6b29e1c..b9f5fd7 100644 --- a/05_container/5.5_import_export.md +++ b/05_container/5.5_import_export.md @@ -30,4 +30,4 @@ test/ubuntu v1.0 9d37a6082e97 About a minute ago ```bash $ docker import http://example.com/exampleimage.tgz example/imagerepo ``` -*注:用户既可以使用 `docker load` 来导入镜像存储文件到本地镜像库,也可以使用 `docker import` 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息 (即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。* +*注:用户既可以使用 `docker load` 来导入镜像存储文件到本地镜像库,也可以使用 `docker import` 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。* diff --git a/05_container/5.6_rm.md b/05_container/5.6_rm.md index ace1829..f6e1233 100644 --- a/05_container/5.6_rm.md +++ b/05_container/5.6_rm.md @@ -222,7 +222,7 @@ $ docker rm -f mycontainer 可能原因: -1. 容器的数据卷未删除 (使用 `-v` 参数) +1. 容器的数据卷未删除(使用 `-v` 参数) 2. 镜像未删除 3. 构建缓存未清理 diff --git a/05_container/README.md b/05_container/README.md index 3a851dc..6cc6f2b 100644 --- a/05_container/README.md +++ b/05_container/README.md @@ -2,7 +2,7 @@ 容器是 Docker 又一核心概念。 -简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统 (提供了运行态环境和其他系统环境) 和跑在上面的应用。 +简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环境)和跑在上面的应用。 本章将具体介绍如何来管理一个容器,包括创建、启动和停止等。 diff --git a/06_repository/6.1_dockerhub.md b/06_repository/6.1_dockerhub.md index 85b7ef6..b173ca9 100644 --- a/06_repository/6.1_dockerhub.md +++ b/06_repository/6.1_dockerhub.md @@ -9,7 +9,7 @@ Docker Hub 是 Docker 的中央镜像仓库,通过它您可以轻松地分享 它提供了: -- **官方镜像**:由 Docker 官方和软件厂商 (如 Nginx,MySQL,Node.js) 维护的高质量镜像。 +- **官方镜像**:由 Docker 官方和软件厂商(如 Nginx,MySQL,Node.js)维护的高质量镜像。 - **个人/组织仓库**:用户可以上传自己的镜像。 - **自动构建**:与 GitHub/Bitbucket 集成的历史功能,Docker 已标记为 deprecated,并计划于 2027-04-01 完全退役。 - **Webhooks**:镜像更新时触发回调。 @@ -71,15 +71,15 @@ Docker Hub 对不同类型用户实施拉取速率限制(基于 6 小时周期 | 用户类型 | 限制 | |---------|------| -| **匿名用户** (未登录) | 每 6 小时 100 次请求 | -| **免费账户** (已登录) | 每 6 小时 200 次请求 | +| **匿名用户**(未登录)| 每 6 小时 100 次请求 | +| **免费账户**(已登录)| 每 6 小时 200 次请求 | | **Pro/Team/Business 账户** | 无限制(公平使用政策) | > **注意**:Docker 曾计划于 2025 年 4 月调整拉取限制策略,但在 2025 年 2 月宣布取消该计划。目前付费订阅用户享有无限制拉取额度,匿名用户和免费账户的限制保持不变。建议在 CI/CD 环境中始终配置 `docker login` 以获得更高的拉取额度。 #### 滥用限流 -除了上述针对特定账号拉取镜像数量的 Pull Rate Limit 之外,Docker Hub 对所有用户(包含已认证及付费用户)还实施了 **滥用保护限流 (Abuse Rate Limiting)**。它是根据网络出口 IP (IPv4 或 IPv6 /64 子网) 计算整体请求频率,阈值动态触发(通常为每分钟数千级别请求)。 +除了上述针对特定账号拉取镜像数量的 Pull Rate Limit 之外,Docker Hub 对所有用户(包含已认证及付费用户)还实施了 **滥用保护限流 (Abuse Rate Limiting)**。它是根据网络出口 IP(IPv4 或 IPv6 /64 子网)计算整体请求频率,阈值动态触发(通常为每分钟数千级别请求)。 **两类的差异与排查方法**: @@ -87,7 +87,7 @@ Docker Hub 对不同类型用户实施拉取速率限制(基于 6 小时周期 - **Abuse Rate Limit**:防范接口频率打击。报错仅返回简化的 `429 Too Many Requests`。这一限流不分付费与否,常发生在“多终端共享出口 IP”的企业局域网或者第三方云 CI 服务(如 GitHub Actions 等)中,即使你已正常配置 `docker login` 也依旧可能触发。 > **提示**:如果在 CI/CD 等环境遇到 429 错误,建议: -> 1. 先甄别具体是哪类限流:普通的 pull rate limit 只要在 CI 中配置 `docker login` (并使用有效账号) 就能解除匿名限制。 +> 1. 先甄别具体是哪类限流:普通的 pull rate limit 只要在 CI 中配置 `docker login`(并使用有效账号)就能解除匿名限制。 > 2. 如果是 Abuse 频控导致,应考虑搭建私有仓库作为拉取缓存代理 (Registry pull-through cache),避免频繁直接请求官方 Hub。 > 3. 使用国内镜像加速器。 @@ -104,7 +104,7 @@ Docker Hub 对不同类型用户实施拉取速率限制(基于 6 小时周期 #### 2. 使用 Access Token -> **⚠️ 警告**:绝不要在脚本或 CI/CD 系统中,直接使用 `-p` 参数传递密码或 Token (类似 `docker login -p xxx`)!这会导致凭证直接暴露在系统的命令历史、进程列表和终端输出中。 +> **⚠️ 警告**:绝不要在脚本或 CI/CD 系统中,直接使用 `-p` 参数传递密码或 Token(类似 `docker login -p xxx`)!这会导致凭证直接暴露在系统的命令历史、进程列表和终端输出中。 1. 在 Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token (PAT)。 2. 将 Token 保存在权限受限的本地文件或 CI secret 中,再通过标准输入 (stdin) 传递给 Docker,避免把真实 Token 写进脚本、命令历史或日志: @@ -122,7 +122,7 @@ Docker Hub 提供 Docker Scout 安全扫描功能。官方镜像的漏洞扫描 ### 6.1.5 Webhooks -当镜像被推送时,可以自动触发 HTTP 回调 (例如通知 CI 系统部署)。 +当镜像被推送时,可以自动触发 HTTP 回调(例如通知 CI 系统部署)。 **配置方法**: 仓库页面 -> Webhooks -> Create Webhook。 diff --git a/06_repository/6.2_registry.md b/06_repository/6.2_registry.md index ef18e1e..9a9be89 100644 --- a/06_repository/6.2_registry.md +++ b/06_repository/6.2_registry.md @@ -101,7 +101,7 @@ REPOSITORY TAG IMAGE ID CREAT 默认情况下,Docker 强制使用 HTTPS 协议推送镜像。如果您搭建的私有仓库是 HTTP 协议,需要进行如下配置。 -对于使用 `systemd` 的系统,请在 `/etc/docker/daemon.json` 中写入如下内容 (如果文件不存在请新建该文件) +对于使用 `systemd` 的系统,请在 `/etc/docker/daemon.json` 中写入如下内容(如果文件不存在请新建该文件) ```json { diff --git a/06_repository/6.3_registry_auth.md b/06_repository/6.3_registry_auth.md index 04c3fa2..ff4b13f 100644 --- a/06_repository/6.3_registry_auth.md +++ b/06_repository/6.3_registry_auth.md @@ -138,7 +138,7 @@ $ docker run --rm \ ### 6.3.4 编辑 Docker Compose 配置 -编辑 `compose.yaml` (或 `docker-compose.yml`) 配置如下: +编辑 `compose.yaml`(或 `docker-compose.yml`)配置如下: ```yaml services: diff --git a/06_repository/6.4_nexus3_registry.md b/06_repository/6.4_nexus3_registry.md index 0a97048..e03a619 100644 --- a/06_repository/6.4_nexus3_registry.md +++ b/06_repository/6.4_nexus3_registry.md @@ -44,7 +44,7 @@ $ docker exec nexus3 cat /nexus-data/admin.password 创建一个私有仓库的方法:`Repository->Repositories` 点击右边菜单 `Create repository` 选择 `docker (hosted)` * **Name**:仓库的名称 -* **HTTP**:仓库单独的访问端口 (例如:**5001**) +* **HTTP**:仓库单独的访问端口(例如:**5001**) * **Hosted -> Deployment policy**:请选择 **Allow redeploy** 否则无法上传 Docker 镜像。 其它的仓库创建方法请各位自己摸索,还可以创建一个 `docker (proxy)` 类型的仓库链接到 DockerHub 上。再创建一个 `docker (group)` 类型的仓库把刚才的 `hosted` 与 `proxy` 添加在一起。主机在访问的时候默认下载私有仓库中的镜像,如果没有将链接到 DockerHub 中下载并缓存到 Nexus 中。 diff --git a/07_dockerfile/7.10_workdir.md b/07_dockerfile/7.10_workdir.md index 7320f7b..7c6f8fc 100644 --- a/07_dockerfile/7.10_workdir.md +++ b/07_dockerfile/7.10_workdir.md @@ -43,7 +43,7 @@ RUN echo "hello" > world.txt ↓ 启动新容器(工作目录在 /)→ 创建 /world.txt ``` -每个 RUN 都在新容器中执行,**前一个 RUN 的内存状态 (包括工作目录) 不会保留**。 +每个 RUN 都在新容器中执行,**前一个 RUN 的内存状态(包括工作目录)不会保留**。 #### 正确做法 diff --git a/07_dockerfile/7.11_user.md b/07_dockerfile/7.11_user.md index eb45d95..a1d1368 100644 --- a/07_dockerfile/7.11_user.md +++ b/07_dockerfile/7.11_user.md @@ -264,7 +264,7 @@ RUN mkdir -p /app/data && chown appuser:appuser /app/data **解决**: -1. 使用高端口 (如 8080) +1. 使用高端口(如 8080) 2. 在运行时映射端口:`docker run -p 80:8080` --- diff --git a/07_dockerfile/7.12_healthcheck.md b/07_dockerfile/7.12_healthcheck.md index 1b3e17b..40039dc 100644 --- a/07_dockerfile/7.12_healthcheck.md +++ b/07_dockerfile/7.12_healthcheck.md @@ -46,7 +46,7 @@ HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ - `0`:成功 (healthy) - `1`:失败 (unhealthy) -- `2`:保留值 (不使用) +- `2`:保留值(不使用) #### 常用选项 @@ -54,7 +54,7 @@ HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ |------|------|--------| | `--interval` | 两次检查的间隔 | 30s | | `--timeout` | 检查命令的超时时间 | 30s | -| `--start-period` | 启动缓冲期 (期间失败不计入次数)| 0s | +| `--start-period` | 启动缓冲期(期间失败不计入次数)| 0s | | `--retries` | 连续失败多少次标记为 unhealthy | 3 | --- @@ -107,7 +107,7 @@ HEALTHCHECK CMD ["healthcheck.sh"] ### 7.12.6 在 Compose 中使用 -可以在 `compose.yaml` (或 `docker-compose.yml`) 中覆盖或定义健康检查: +可以在 `compose.yaml`(或 `docker-compose.yml`)中覆盖或定义健康检查: ```yaml services: @@ -171,11 +171,11 @@ $ docker inspect --format '{{json .State.Health}}' mycontainer | jq #### 2. 使用轻量级工具 -优先使用镜像中已有的工具 (如 `wget`),避免为了健康检查安装庞大的依赖 (如 `curl`)。 +优先使用镜像中已有的工具(如 `wget`),避免为了健康检查安装庞大的依赖(如 `curl`)。 #### 3. 设置合理的 Start Period -应用启动可能需要时间 (如 Java 应用)。设置 `--start-period` 可以防止在启动阶段因检查失败而误判。 +应用启动可能需要时间(如 Java 应用)。设置 `--start-period` 可以防止在启动阶段因检查失败而误判。 ```docker ## 给应用 1 分钟启动时间 @@ -185,7 +185,7 @@ HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1 #### 4. 只检查核心依赖 -健康检查应主要关注 **当前服务** 是否可用,而不是检查其下游依赖 (数据库等)。下游依赖的检查应由应用逻辑处理。 +健康检查应主要关注 **当前服务** 是否可用,而不是检查其下游依赖(数据库等)。下游依赖的检查应由应用逻辑处理。 #### 5. 与容器编排平台的关系 diff --git a/07_dockerfile/7.13_onbuild.md b/07_dockerfile/7.13_onbuild.md index a83aaf0..bb7350f 100644 --- a/07_dockerfile/7.13_onbuild.md +++ b/07_dockerfile/7.13_onbuild.md @@ -5,7 +5,7 @@ ```docker ONBUILD <其它指令> ``` -`ONBUILD` 是一个特殊的指令,它后面跟的是其它指令 (如 `RUN`,`COPY` 等),这些指令 **在当前镜像构建时不会执行**,只有当以当前镜像为基础镜像去构建下一级镜像时才会被执行。 +`ONBUILD` 是一个特殊的指令,它后面跟的是其它指令(如 `RUN`,`COPY` 等),这些指令 **在当前镜像构建时不会执行**,只有当以当前镜像为基础镜像去构建下一级镜像时才会被执行。 --- @@ -101,7 +101,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/ `ONBUILD` 指令 **只会继承一次**。 -- 镜像 A (含 ONBUILD) +- 镜像 A(含 ONBUILD) - 镜像 B (FROM A) -> 触发 ONBUILD - 镜像 C (FROM B) -> **不会** 再次触发 ONBUILD @@ -115,7 +115,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/ #### 4. 可能会导致构建失败 -由于 `ONBUILD` 实际上是在子镜像中执行指令,如果子项目的上下文不满足要求 (例如缺少 `package.json`),会导致子镜像构建失败,且错误信息可能比较隐晦。 +由于 `ONBUILD` 实际上是在子镜像中执行指令,如果子项目的上下文不满足要求(例如缺少 `package.json`),会导致子镜像构建失败,且错误信息可能比较隐晦。 --- @@ -132,7 +132,7 @@ python:3.12-onbuild #### 2. 避免执行耗时操作 -尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作 (如更新系统软件),这会让子镜像构建变得缓慢且不可控。 +尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作(如更新系统软件),这会让子镜像构建变得缓慢且不可控。 #### 3. 清理工作 diff --git a/07_dockerfile/7.15_shell.md b/07_dockerfile/7.15_shell.md index d3b2c2b..9e3f6f9 100644 --- a/07_dockerfile/7.15_shell.md +++ b/07_dockerfile/7.15_shell.md @@ -10,7 +10,7 @@ SHELL ["executable", "parameters"] - **Linux 默认**:`["/bin/sh", "-c"]` - **Windows 默认**:`["cmd", "/S", "/C"]` -该指令会影响后续的 `RUN`,`CMD`,`ENTRYPOINT` 指令 (当它们使用 shell 格式时)。 +该指令会影响后续的 `RUN`,`CMD`,`ENTRYPOINT` 指令(当它们使用 shell 格式时)。 --- @@ -18,7 +18,7 @@ SHELL ["executable", "parameters"] #### 1. 使用 bash 特性 -默认的 `/bin/sh` (通常是 dash 或 alpine 的 ash) 功能有限。如果你需要使用 bash 的特有功能 (如数组、`{}` 扩展、`pipefail` 等),可以切换 shell。 +默认的 `/bin/sh`(通常是 dash 或 alpine 的 ash)功能有限。如果你需要使用 bash 的特有功能(如数组、`{}` 扩展、`pipefail` 等),可以切换 shell。 ```docker FROM ubuntu:24.04 diff --git a/07_dockerfile/7.1_run.md b/07_dockerfile/7.1_run.md index f146332..aa50a29 100644 --- a/07_dockerfile/7.1_run.md +++ b/07_dockerfile/7.1_run.md @@ -44,7 +44,7 @@ RUN ["apt-get", "update"] - **特点**:直接调用可执行文件,不经过 Shell。 - **优势**:避免 Shell 字符串解析问题,适用于参数中包含特殊字符的情况。 -- **注意**:无法使用 `$VAR` 环境变量替换 (除非显式调用 shell)。 +- **注意**:无法使用 `$VAR` 环境变量替换(除非显式调用 shell)。 --- @@ -54,14 +54,14 @@ RUN ["apt-get", "update"] 每一个 `RUN` 指令都会新建一层镜像。为了减少镜像体积和层数,应使用 `&&` 连接命令。 -**❌ 糟糕的写法** (创建 3 层): +**❌ 糟糕的写法**(创建 3 层): ```docker RUN apt-get update RUN apt-get install -y nginx RUN rm -rf /var/lib/apt/lists/* ``` -**✅ 推荐写法** (创建 1 层): +**✅ 推荐写法**(创建 1 层): ```docker RUN apt-get update && \ diff --git a/07_dockerfile/7.2_copy.md b/07_dockerfile/7.2_copy.md index 22bd032..8964343 100644 --- a/07_dockerfile/7.2_copy.md +++ b/07_dockerfile/7.2_copy.md @@ -154,7 +154,7 @@ COPY start.sh /app/ |------|------|-----| | 复制本地文件 | ✅ | ✅ | | 自动解压 tar | ❌ | ✅ | -| 支持 URL | ❌ | ✅ (不推荐)| +| 支持 URL | ❌ | ✅(不推荐)| | 推荐程度 | ✅ **推荐** | ⚠️ 特殊场景使用 | ```docker diff --git a/07_dockerfile/7.3_add.md b/07_dockerfile/7.3_add.md index f0d5e56..d82d79c 100644 --- a/07_dockerfile/7.3_add.md +++ b/07_dockerfile/7.3_add.md @@ -30,7 +30,7 @@ ADD [选项] ["<源路径>", ... "<目标路径>"] |------|------|-----| | 复制本地文件 | ✅ | ✅ | | 自动解压 tar | ❌ | ✅ | -| 支持 URL | ❌ | ✅ (公开 artifact 可配合校验使用)| +| 支持 URL | ❌ | ✅(公开 artifact 可配合校验使用)| | 行为可预测性 | ✅ 高 | ⚠️ 低 | | 推荐程度 | ✅ **普通复制优先使用** | 解压、本地 Git/公开远程 artifact | diff --git a/07_dockerfile/7.4_cmd.md b/07_dockerfile/7.4_cmd.md index cfd5081..a149d58 100644 --- a/07_dockerfile/7.4_cmd.md +++ b/07_dockerfile/7.4_cmd.md @@ -45,7 +45,7 @@ CMD ["node", "server.js"] **优点**: - 直接执行指定程序,是容器的 PID 1 -- 正确接收信号 (如 SIGTERM) +- 正确接收信号(如 SIGTERM) - 无需 shell 解析 #### shell 格式 diff --git a/07_dockerfile/7.5_entrypoint.md b/07_dockerfile/7.5_entrypoint.md index d9b7978..09ad9c4 100644 --- a/07_dockerfile/7.5_entrypoint.md +++ b/07_dockerfile/7.5_entrypoint.md @@ -159,7 +159,7 @@ curl -s http://myip.ipip.net -i #### 需求 -在启动主服务前执行初始化脚本 (如数据库迁移、权限设置)。 +在启动主服务前执行初始化脚本(如数据库迁移、权限设置)。 #### 实现方式 @@ -210,7 +210,7 @@ docker-entrypoint.sh redis-server docker-entrypoint.sh bash 1. **exec “$@”**:用传入的参数替换当前进程,确保信号正确传递 2. **条件判断**:根据 CMD 不同执行不同逻辑 -3. **用户切换**:使用 `gosu` 切换用户 (比 `su` 更适合容器) +3. **用户切换**:使用 `gosu` 切换用户(比 `su` 更适合容器) --- @@ -272,11 +272,11 @@ $ docker run --entrypoint /bin/cat myimage /etc/os-release | ENTRYPOINT | CMD | 最终执行命令 | |------------|-----|-------------| -| 无 | 无 | 无 (容器无法启动)| +| 无 | 无 | 无(容器无法启动)| | 无 | `["cmd", "p1"]` | `cmd p1` | | `["ep", "p1"]` | 无 | `ep p1` | | `["ep", "p1"]` | `["cmd", "p2"]` | `ep p1 cmd p2` | -| `ep p1` (shell)| `["cmd", "p2"]` | `/bin/sh -c "ep p1"` (CMD 被忽略)| +| `ep p1` (shell)| `["cmd", "p2"]` | `/bin/sh -c "ep p1"`(CMD 被忽略)| > ⚠️ **注意**:shell 格式的 ENTRYPOINT 会忽略 CMD! diff --git a/07_dockerfile/7.6_env.md b/07_dockerfile/7.6_env.md index d97aa1b..0fcb656 100644 --- a/07_dockerfile/7.6_env.md +++ b/07_dockerfile/7.6_env.md @@ -133,7 +133,7 @@ DATABASE_URL=postgres://localhost/mydb | **生效时间** | 构建时 + 运行时 | 仅构建时 | | **持久性** | 写入镜像,运行时可用 | 构建后消失 | | **覆盖方式** | `docker run -e` | `docker build --build-arg` | -| **适用场景** | 应用配置 | 构建参数 (如版本号)| +| **适用场景** | 应用配置 | 构建参数(如版本号)| #### 组合使用 diff --git a/07_dockerfile/7.7_arg.md b/07_dockerfile/7.7_arg.md index 498fd4c..b1ab0b8 100644 --- a/07_dockerfile/7.7_arg.md +++ b/07_dockerfile/7.7_arg.md @@ -16,7 +16,7 @@ ARG <参数名>[=<默认值>] | **生效时间** | 仅构建时 | 构建时 + 运行时 | | **持久性** | 构建后消失 | 写入镜像 | | **覆盖方式** | `docker build --build-arg` | `docker run -e` | -| **适用场景** | 构建参数 (版本号等)| 应用配置 | +| **适用场景** | 构建参数(版本号等)| 应用配置 | | **可见性** | `docker history` 可见 | `docker inspect` 可见 | ```dockerfile diff --git a/07_dockerfile/7.8_volume.md b/07_dockerfile/7.8_volume.md index ead25bf..d127162 100644 --- a/07_dockerfile/7.8_volume.md +++ b/07_dockerfile/7.8_volume.md @@ -162,7 +162,7 @@ $ docker inspect mycontainer --format '{{json .Mounts}}' | jq |------|-------------------|---------------| | **定义时机** | 镜像构建时 | 容器运行时 | | **默认行为** | 创建匿名卷 | 可指定命名卷或路径 | -| **灵活性** | 低 (固定路径)| 高 (可任意指定)| +| **灵活性** | 低(固定路径)| 高(可任意指定)| | **适用场景** | 定义必须持久化的路径 | 灵活的数据管理 | --- diff --git a/07_dockerfile/7.9_expose.md b/07_dockerfile/7.9_expose.md index 549a4e2..82599fa 100644 --- a/07_dockerfile/7.9_expose.md +++ b/07_dockerfile/7.9_expose.md @@ -67,7 +67,7 @@ $ docker port $(docker ps -q) |------|--------|-----| | **位置** | Dockerfile | docker run 命令 | | **作用** | 声明/文档 | 实际端口映射 | -| **是否必需** | 否 | 是 (外部访问时)| +| **是否必需** | 否 | 是(外部访问时)| | **映射发生时** | 不发生 | 运行时发生 | ```mermaid diff --git a/07_dockerfile/README.md b/07_dockerfile/README.md index 0755591..738041c 100644 --- a/07_dockerfile/README.md +++ b/07_dockerfile/README.md @@ -10,7 +10,7 @@ Dockerfile 是一个文本文件,其内包含了一条条的 **指令 (Instruc * **自动化**:可以通过 `docker build` 命令自动构建镜像。 * **可重复性**:由于 Dockerfile 是文本文件,可以确保每次构建的结果一致。 -* **版本控制**:Dockerfile 可以纳入版本控制系统 (如 Git),便于追踪变更。 +* **版本控制**:Dockerfile 可以纳入版本控制系统(如 Git),便于追踪变更。 * **透明性**:任何人都可以通过阅读 Dockerfile 了解镜像的构建过程。 ## Dockerfile 编写哲学 diff --git a/08_data/8.1_volume.md b/08_data/8.1_volume.md index 7c3ccdf..0992f68 100644 --- a/08_data/8.1_volume.md +++ b/08_data/8.1_volume.md @@ -96,7 +96,7 @@ $ docker volume inspect my-vol **关键字段**: - `Mountpoint`:数据卷在宿主机上的实际存储位置 -- `Driver`:存储驱动 (默认 local,也可以用第三方驱动) +- `Driver`:存储驱动(默认 local,也可以用第三方驱动) --- @@ -114,7 +114,7 @@ $ docker run -d \ | 参数 | 说明 | |------|------| -| `source` | 数据卷名称 (不存在会自动创建)| +| `source` | 数据卷名称(不存在会自动创建)| | `target` | 容器内挂载路径 | | `readonly` | 可选,只读挂载 | @@ -135,7 +135,7 @@ $ docker run -d \ | 语法 | 键值对,更清晰 | 冒号分隔,更简洁 | | **数据卷 (Volume)** 挂载行为 | 卷不存在会自动创建,与 `-v` 结果一致 | 卷不存在会自动创建 | | **绑定挂载 (Bind Mount)** 行为 | ⭐**宿主机路径不存在会报错**,不会自动创建 | 宿主机路径不存在会 **自动创建为目录** | -| 推荐程度 | ✅ 推荐 (更明确安全,避免误创建)| 常用 (更简洁)| +| 推荐程度 | ✅ 推荐(更明确安全,避免误创建)| 常用(更简洁)| > **提示**:官方更推荐使用 `--mount`。除了语法格式可读性更好之外,最重要的行为差异发生在 **绑定挂载 (Bind Mount)** 时:如果挂载的宿主机源路径尚未存在,`-v` 会擅自将其自动创建为一个空目录;而 `--mount` 则会严格检查并直接报错。这能有效避免因路径拼写错误而在宿主机上留下垃圾目录(以及导致的容器访问空目录问题)。而对于本节的 **数据卷 (Volume)** 挂载而言,两者在目标指定的卷不存在时皆会自动创建卷,产生的结果是 **完全一致** 的。 diff --git a/08_data/8.2_bind-mounts.md b/08_data/8.2_bind-mounts.md index 4c1fa22..4a97cb6 100644 --- a/08_data/8.2_bind-mounts.md +++ b/08_data/8.2_bind-mounts.md @@ -2,7 +2,7 @@ ### 8.2.1 什么是绑定挂载 -Bind Mount (绑定挂载) 将 **Docker daemon 所在主机** 上的目录或文件直接挂载到容器中。容器可以读写这台主机上的文件系统。 +Bind Mount(绑定挂载)将 **Docker daemon 所在主机** 上的目录或文件直接挂载到容器中。容器可以读写这台主机上的文件系统。 ```mermaid flowchart LR @@ -31,7 +31,7 @@ flowchart LR |------|------------|--------| | **数据位置** | 宿主机任意路径 | Docker 管理的目录 | | **路径指定** | 必须是绝对路径 | 卷名 | -| **可移植性** | 依赖宿主机路径 | 更好 (Docker 管理)| +| **可移植性** | 依赖宿主机路径 | 更好(Docker 管理)| | **性能** | 依赖宿主机文件系统 | 优化的存储驱动 | | **适用场景** | 开发环境、配置文件 | 生产数据持久化 | | **备份** | 直接访问文件 | 需要通过 Docker | @@ -44,7 +44,7 @@ flowchart LR | 持久化数据库数据 | Volume | | 共享配置文件 | Bind Mount | | 容器间共享数据 | Volume | -| 备份方便 | Bind Mount (直接访问)| +| 备份方便 | Bind Mount(直接访问)| | 生产环境 | Volume | --- @@ -173,7 +173,7 @@ $ docker run -d \ --mount type=bind,source=/path/to/my.cnf,target=/etc/mysql/my.cnf \ mysql ``` -> ⚠️ **注意**:挂载单个文件时,如果宿主机上的文件被编辑器替换 (而非原地修改),容器内仍是旧文件的 inode。建议重启容器或挂载目录。 +> ⚠️ **注意**:挂载单个文件时,如果宿主机上的文件被编辑器替换(而非原地修改),容器内仍是旧文件的 inode。建议重启容器或挂载目录。 --- @@ -248,7 +248,7 @@ $ docker run -v /host/path:/container/path:cached myapp |------|------| | `:cached` | 宿主机权威,容器读取可能延迟 | | `:delegated` | 容器权威,宿主机读取可能延迟 | -| `:consistent` | 默认,完全一致 (最慢)| +| `:consistent` | 默认,完全一致(最慢)| > **注意**:Docker Desktop 4.6+ 默认使用 VirtioFS 文件共享引擎,上述 `:cached`/`:delegated` 选项已被静默忽略。如需优化文件同步性能,请参考 Docker Desktop 的 [Synchronized file shares](https://docs.docker.com/desktop/features/synchronized-file-sharing/) 功能。 diff --git a/09_network/9.1_dns.md b/09_network/9.1_dns.md index 7a92863..c3d0347 100644 --- a/09_network/9.1_dns.md +++ b/09_network/9.1_dns.md @@ -9,13 +9,13 @@ Docker 1.10.0 以后,内建了一个 DNS 服务器,使得容器可以直接 Docker 容器的 DNS 配置有两种情况: 1. **默认 Bridge 网络**:继承宿主机的 DNS 配置 (`/etc/resolv.conf`)。 -2. **自定义网络**(推荐):使用 Docker 嵌入式 DNS 服务器 (Embedded DNS),支持通过 **容器名** 进行服务发现。 +2. **自定义网络**(推荐):使用 Docker 嵌入式 DNS 服务器 (Embedded DNS),支持通过 **容器名** 进行服务发现。 --- ### 9.1.2 嵌入式 DNS -这是 Docker 网络最强大的功能之一。在自定义网络中,容器可以通过 “名字” 找到彼此,而不需要知道对方的 IP (因为 IP 可能会变)。 +这是 Docker 网络最强大的功能之一。在自定义网络中,容器可以通过 “名字” 找到彼此,而不需要知道对方的 IP(因为 IP 可能会变)。 ```bash ## 1. 创建自定义网络 @@ -33,13 +33,13 @@ PING web (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.074 ms ``` **原理**: -Docker 守护进程在 `127.0.0.11` 运行了一个 DNS 服务器。容器内的 DNS 请求会被转发到这里。如果是容器名,解析为容器 IP;如果是外部域名 (如 google.com),转发给上游 DNS。 +Docker 守护进程在 `127.0.0.11` 运行了一个 DNS 服务器。容器内的 DNS 请求会被转发到这里。如果是容器名,解析为容器 IP;如果是外部域名(如 google.com),转发给上游 DNS。 --- ### 9.1.3 配置 DNS 参数 -如果你需要手动配置容器的 DNS (例如使用内网 DNS 服务器),可以在 `docker run` 中使用以下参数: +如果你需要手动配置容器的 DNS(例如使用内网 DNS 服务器),可以在 `docker run` 中使用以下参数: #### 1. --dns @@ -69,7 +69,7 @@ $ docker run -h myweb nginx ### 9.1.4 全局 DNS 配置 -如果希望所有容器都使用特定的 DNS 服务器 (而不是继承宿主机),可以修改 `/etc/docker/daemon.json`: +如果希望所有容器都使用特定的 DNS 服务器(而不是继承宿主机),可以修改 `/etc/docker/daemon.json`: ```json { @@ -91,7 +91,7 @@ $ docker run -h myweb nginx **现象**:`ping www.baidu.com` 失败,但 `ping 8.8.8.8` 成功。**解决**: -1. 宿主机的 `/etc/resolv.conf` 可能有问题 (例如使用了本地回环地址 127.0.0.53,特别是 Ubuntu 系统)。Docker 可能会尝试修复,但有时会失败。 +1. 宿主机的 `/etc/resolv.conf` 可能有问题(例如使用了本地回环地址 127.0.0.53,特别是 Ubuntu 系统)。Docker 可能会尝试修复,但有时会失败。 2. 尝试手动指定 DNS:`docker run --dns 8.8.8.8 ...` 3. 检查防火墙是否拦截了 UDP 53 端口。 @@ -99,7 +99,7 @@ $ docker run -h myweb nginx **现象**:`ping db` 提示 `bad address 'db'`。**原因**: -- 你可能在使用 **默认的 bridge 网络**。默认 bridge 网络 **不支持** 通过容器名进行 DNS 解析 (这是一个历史遗留设计)。 +- 你可能在使用 **默认的 bridge 网络**。默认 bridge 网络 **不支持** 通过容器名进行 DNS 解析(这是一个历史遗留设计)。 - **解决**:使用自定义网络 (`docker network create ...`)。 --- diff --git a/09_network/9.3_custom_network.md b/09_network/9.3_custom_network.md index c2ae68c..8a45cfe 100644 --- a/09_network/9.3_custom_network.md +++ b/09_network/9.3_custom_network.md @@ -10,7 +10,7 @@ |------|-----------------| | 只能用 IP 通信 | 支持容器名 DNS 解析 | | 所有容器在同一网络 | 更好的隔离性 | -| 需要 --link (已废弃)| 原生支持服务发现 | +| 需要 --link(已废弃)| 原生支持服务发现 | ### 9.3.2 创建自定义网络 @@ -48,7 +48,7 @@ PING db (172.18.0.3): 56 data bytes 自定义网络自动提供 DNS 服务。Docker 守护进程在 `127.0.0.11` 运行了一个嵌入式 DNS 服务器,容器内的 DNS 请求会被转发到这里: - 如果是容器名,解析为容器 IP -- 如果是外部域名 (如 google.com),转发给上游 DNS +- 如果是外部域名(如 google.com),转发给上游 DNS ```mermaid flowchart LR diff --git a/09_network/9.5_port_mapping.md b/09_network/9.5_port_mapping.md index a251f76..e9d3584 100644 --- a/09_network/9.5_port_mapping.md +++ b/09_network/9.5_port_mapping.md @@ -1,16 +1,16 @@ ## 9.5 外部访问容器 -容器运行在自己的隔离网络环境中 (通常是 Bridge 模式)。为了让外部网络访问容器内的服务,我们需要将容器的端口映射到宿主机的端口。 +容器运行在自己的隔离网络环境中(通常是 Bridge 模式)。为了让外部网络访问容器内的服务,我们需要将容器的端口映射到宿主机的端口。 ### 9.5.1 为什么要映射端口 容器的网络访问规则如下: -- **容器之间**:可以通过 IP 或容器名 (自定义网络) 互通。 +- **容器之间**:可以通过 IP 或容器名(自定义网络)互通。 - **宿主机访问容器**:原生 Linux 环境下可按网络配置访问容器 IP;Docker Desktop 上不能依赖容器 IP,应通过端口映射、容器名(容器间)或 `host.docker.internal` 等机制访问。 - **外部网络访问容器**:❌ 默认无法直接访问。 -为了让外部 (如你的浏览器、其他局域网机器) 访问容器内的服务,我们需要将容器的端口 **映射** 到宿主机的端口。 +为了让外部(如你的浏览器、其他局域网机器)访问容器内的服务,我们需要将容器的端口 **映射** 到宿主机的端口。 ```mermaid flowchart TD @@ -39,14 +39,14 @@ $ docker run -d -p 8080:80 nginx | 格式 | 含义 | 示例 | |------|------|------| -| `ip:hostPort:containerPort` | 绑定指定 IP 的特定端口 | `-p 127.0.0.1:8080:80` (仅 IPv4 本机访问) | +| `ip:hostPort:containerPort` | 绑定指定 IP 的特定端口 | `-p 127.0.0.1:8080:80`(仅 IPv4 本机访问)| | `ip::containerPort` | 绑定指定 IP 的随机端口 | `-p 127.0.0.1::80` | -| `hostPort:containerPort` | 绑定所有地址(通常包括 `0.0.0.0` 和 `[::]`)的特定端口 | `-p 8080:80` (默认) | +| `hostPort:containerPort` | 绑定所有地址(通常包括 `0.0.0.0` 和 `[::]`)的特定端口 | `-p 8080:80`(默认)| | `containerPort` | 绑定所有地址的随机端口 | `-p 80` | #### 2. 随机映射 -如果不关心宿主机使用哪个端口,可以使用随机映射。使用 `-P` (大写) 参数,Docker 会把 Dockerfile 中 `EXPOSE` 指令暴露的所有端口发布到宿主机的随机高位端口。具体落在哪个端口,取决于宿主机当前可用的临时端口范围。 +如果不关心宿主机使用哪个端口,可以使用随机映射。使用 `-P`(大写)参数,Docker 会把 Dockerfile 中 `EXPOSE` 指令暴露的所有端口发布到宿主机的随机高位端口。具体落在哪个端口,取决于宿主机当前可用的临时端口范围。 ```bash $ docker run -d -P nginx @@ -95,7 +95,7 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web 默认情况下,`-p 8080:80` 会监听所有可用地址,常见输出包括 `0.0.0.0:8080` 和 `[::]:8080`。这意味着任何人只要能连接你的宿主机 IP,就能访问该服务。 -如果不希望对外暴露 (例如数据库服务),应绑定到回环地址。IPv4 使用 `127.0.0.1`,IPv6 使用 `[::1]`: +如果不希望对外暴露(例如数据库服务),应绑定到回环地址。IPv4 使用 `127.0.0.1`,IPv6 使用 `[::1]`: ```bash ## 仅允许本机访问 @@ -115,7 +115,7 @@ $ docker run -d -p '[::1]:3306:3306' mysql #### 3. UDP 映射 -默认是 TCP 协议。如果要映射 UDP 服务 (如 DNS,Syslog): +默认是 TCP 协议。如果要映射 UDP 服务(如 DNS,Syslog): ```bash $ docker run -d -p 53:53/udp dns-server @@ -124,7 +124,7 @@ $ docker run -d -p 53:53/udp dns-server ### 9.5.5 实现原理 -Docker 使用 `docker-proxy` 进程 (用户态) 或 `iptables` DNAT 规则 (内核态) 来实现端口转发。 +Docker 使用 `docker-proxy` 进程(用户态)或 `iptables` DNAT 规则(内核态)来实现端口转发。 当流量到达宿主机端口时,iptables 规则将其目标地址修改为容器 IP 并转发: @@ -133,6 +133,6 @@ Docker 使用 `docker-proxy` 进程 (用户态) 或 `iptables` DNAT 规则 (内 iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80 ``` -这也是为什么你在容器内部看到的访问来源 IP 通常是网关 IP (如 172.17.0.1),而不是真实的外部 Client IP (除非使用 host 网络模式)。 +这也是为什么你在容器内部看到的访问来源 IP 通常是网关 IP(如 172.17.0.1),而不是真实的外部 Client IP(除非使用 host 网络模式)。 --- diff --git a/09_network/summary.md b/09_network/summary.md index 70cc04f..d7a4ac9 100644 --- a/09_network/summary.md +++ b/09_network/summary.md @@ -5,7 +5,7 @@ | 概念 | 要点 | |------|------| | **DNS 配置** | 自定义网络支持嵌入式 DNS,可通过容器名解析 | -| **网络类型** | bridge (默认)、host、none、overlay、macvlan | +| **网络类型** | bridge(默认)、host、none、overlay、macvlan | | **自定义网络** | 推荐使用,支持容器名 DNS 解析和更好的隔离 | | **容器互联** | 同一自定义网络内容器可直接通过容器名通信 | | **端口映射** | `-p 宿主机端口:容器端口` 暴露服务到外部 | diff --git a/10_buildx/10.1_buildkit.md b/10_buildx/10.1_buildkit.md index 476d3e3..0fadb43 100644 --- a/10_buildx/10.1_buildkit.md +++ b/10_buildx/10.1_buildkit.md @@ -82,15 +82,15 @@ COPY --from=builder /app/dist /app/dist |Option |Description| |---------------------|-----------| |`id` | `id` 设置一个标志,以便区分缓存。| -|`target` (必填项) | 缓存的挂载目标文件夹。| +|`target`(必填项) | 缓存的挂载目标文件夹。| |`ro`,`readonly` | 只读,缓存文件夹不能被写入。 | -|`sharing` | 有 `shared` `private` `locked` 值可供选择。`sharing` 设置当一个缓存被多次使用时的表现,由于 `BuildKit` 支持并行构建,当多个步骤使用同一缓存时 (同一 `id`) 会发生冲突。`shared` 表示多个步骤可以同时读写,`private` 表示当多个步骤使用同一缓存时,每个步骤使用不同的缓存,`locked` 表示当一个步骤完成释放缓存后,后一个步骤才能继续使用该缓存。| -|`from` | 缓存来源 (构建阶段),不填写时为空文件夹。| +|`sharing` | 有 `shared` `private` `locked` 值可供选择。`sharing` 设置当一个缓存被多次使用时的表现,由于 `BuildKit` 支持并行构建,当多个步骤使用同一缓存时(同一 `id`)会发生冲突。`shared` 表示多个步骤可以同时读写,`private` 表示当多个步骤使用同一缓存时,每个步骤使用不同的缓存,`locked` 表示当一个步骤完成释放缓存后,后一个步骤才能继续使用该缓存。| +|`from` | 缓存来源(构建阶段),不填写时为空文件夹。| |`source` | 来源的文件夹路径。| #### `RUN --mount=type=bind` -该指令可以将一个镜像 (或上一构建阶段) 的文件挂载到指定位置。 +该指令可以将一个镜像(或上一构建阶段)的文件挂载到指定位置。 ```docker # syntax=docker/dockerfile:1 @@ -112,7 +112,7 @@ RUN --mount=type=tmpfs,target=/temp \ #### `RUN --mount=type=secret` -该指令可以将一个文件 (例如密钥) 挂载到指定位置。 +该指令可以将一个文件(例如密钥)挂载到指定位置。 ```docker # syntax=docker/dockerfile:1 diff --git a/10_buildx/10.2_buildx.md b/10_buildx/10.2_buildx.md index 111f7f1..0be9cdd 100644 --- a/10_buildx/10.2_buildx.md +++ b/10_buildx/10.2_buildx.md @@ -48,7 +48,7 @@ $ docker buildx build --sbom=true -t myimage . 该命令会把 SBOM 作为构建 attestation 附加到构建结果中;BuildKit 默认使用 SPDX SBOM attestation。需要 CycloneDX 文件时,可使用 Syft、Docker Scout 等工具另行生成或转换。 > **⚠️ 注意与失败模式**: -> 要使 SBOM (或其它 attestation 元数据) 成功附着并可见,对底层的存储格式有前置要求:默认的 classic image store 不支持 manifest list/index 这种存放 attestation 的结构。 +> 要使 SBOM(或其它 attestation 元数据)成功附着并可见,对底层的存储格式有前置要求:默认的 classic image store 不支持 manifest list/index 这种存放 attestation 的结构。 > > 如果只简单运行上述命令,你可能会面临 **“命令成功执行,但本地镜像中看不到 SBOM”** 的体会落差。 > diff --git a/10_buildx/10.3_multi-arch-images.md b/10_buildx/10.3_multi-arch-images.md index 1f8797c..f540be2 100644 --- a/10_buildx/10.3_multi-arch-images.md +++ b/10_buildx/10.3_multi-arch-images.md @@ -1,6 +1,6 @@ ## 10.3 使用 buildx 构建多种系统架构支持的 Docker 镜像 -Docker 镜像可以支持多种系统架构,这意味着你可以在 `x86_64`、`arm64` 等不同架构的机器上运行同一个镜像。这是通过一个名为 “manifest list” (或称为 “fat manifest”) 的文件来实现的。 +Docker 镜像可以支持多种系统架构,这意味着你可以在 `x86_64`、`arm64` 等不同架构的机器上运行同一个镜像。这是通过一个名为 “manifest list”(或称为 “fat manifest”)的文件来实现的。 ### 10.3.1 Manifest List 是什么? diff --git a/11_compose/11.1_introduction.md b/11_compose/11.1_introduction.md index 8a5dc7a..a6099b1 100644 --- a/11_compose/11.1_introduction.md +++ b/11_compose/11.1_introduction.md @@ -8,7 +8,7 @@ 通过第一部分中的介绍,我们知道使用一个 `Dockerfile` 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。 -`Compose` 恰好满足了这样的需求。它允许用户通过一个单独的 `compose.yaml` (历史默认名也常见为 `docker-compose.yml`) 模板文件 (YAML 格式) 来定义一组相关联的应用容器为一个项目 (project)。 +`Compose` 恰好满足了这样的需求。它允许用户通过一个单独的 `compose.yaml`(历史默认名也常见为 `docker-compose.yml`)模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目 (project)。 ### 11.1.1 概述 diff --git a/11_compose/11.3_usage.md b/11_compose/11.3_usage.md index 7abedca..f717380 100644 --- a/11_compose/11.3_usage.md +++ b/11_compose/11.3_usage.md @@ -10,7 +10,7 @@ * 项目 (`project`):由一组关联的应用容器组成的一个完整业务单元。 -可见,一个项目可以由多个服务 (容器) 关联而成,`Compose` 面向项目进行管理。 +可见,一个项目可以由多个服务(容器)关联而成,`Compose` 面向项目进行管理。 ### 11.3.2 准备示例 @@ -50,7 +50,7 @@ CMD ["python", "app.py"] #### compose.yaml -编写 `compose.yaml` 文件,这是 Compose 推荐使用的主模板文件 (也兼容 `docker-compose.yml` 等历史文件名)。 +编写 `compose.yaml` 文件,这是 Compose 推荐使用的主模板文件(也兼容 `docker-compose.yml` 等历史文件名)。 ```yaml services: diff --git a/11_compose/11.4_commands.md b/11_compose/11.4_commands.md index 6b9c6ea..6982df7 100644 --- a/11_compose/11.4_commands.md +++ b/11_compose/11.4_commands.md @@ -42,11 +42,11 @@ docker compose [-f=...] [options] [COMMAND] [ARGS...] ### 11.4.2 命令选项 -* `-f, --file FILE` 指定使用的 Compose 模板文件。默认会自动识别 `compose.yaml` (也兼容 `docker-compose.yml` 等),并且可以多次指定。 +* `-f, --file FILE` 指定使用的 Compose 模板文件。默认会自动识别 `compose.yaml`(也兼容 `docker-compose.yml` 等),并且可以多次指定。 * `-p, --project-name NAME` 指定项目名称,默认将使用所在目录名称作为项目名。 -* `--verbose` 输出更多调试信息。(Compose V2 中该选项仍然生效,但已从 `--help` 中隐藏,不再是推荐用法;请改用 `docker --log-level debug compose ...`。) +* `--verbose` 输出更多调试信息。(Compose V2 中该选项仍然生效,但已从 `--help` 中隐藏,不再是推荐用法;请改用 `docker --log-level debug compose ...`。) * `-v, --version` 打印版本并退出。 @@ -56,7 +56,7 @@ docker compose [-f=...] [options] [COMMAND] [ARGS...] 格式为 `docker compose build [options] [SERVICE...]`。 -构建 (重新构建) 项目中的服务容器。 +构建(重新构建)项目中的服务容器。 服务容器一旦构建后,将会带上一个标记名,例如对于 web 项目中的一个 db 服务,构建出的镜像是 `web-db`。(Compose V1 用下划线拼接为 `web_db`,V2 起统一改为连字符,只有加 `--compatibility` 才会回到下划线。) @@ -66,7 +66,7 @@ docker compose [-f=...] [options] [COMMAND] [ARGS...] * `--force-rm` 删除构建过程中的临时容器。 -* `--no-cache` 构建镜像过程中不使用 cache (这将加长构建过程)。 +* `--no-cache` 构建镜像过程中不使用 cache(这将加长构建过程)。 * `--pull` 始终尝试通过 pull 来获取更新版本的镜像。 @@ -124,9 +124,9 @@ $ docker compose kill -s SIGINT 选项: -* `--protocol=proto` 指定端口协议,tcp (默认值) 或者 udp。 +* `--protocol=proto` 指定端口协议,tcp(默认值)或者 udp。 -* `--index=index` 如果同一服务存在多个容器,指定命令对象容器的序号 (默认为 1)。 +* `--index=index` 如果同一服务存在多个容器,指定命令对象容器的序号(默认为 1)。 #### `ps` @@ -160,13 +160,13 @@ $ docker compose kill -s SIGINT 选项: -* `-t, --timeout TIMEOUT` 指定重启前停止容器的超时 (默认为 10 秒)。 +* `-t, --timeout TIMEOUT` 指定重启前停止容器的超时(默认为 10 秒)。 #### `rm` 格式为 `docker compose rm [options] [SERVICE...]`。 -删除所有 (停止状态的) 服务容器。推荐先执行 `docker compose stop` 命令来停止容器。 +删除所有(停止状态的)服务容器。推荐先执行 `docker compose stop` 命令来停止容器。 选项: @@ -261,7 +261,7 @@ $ docker compose up -d --scale web=3 --scale db=2 选项: -* `-t, --timeout TIMEOUT` 停止容器时候的超时 (默认为 10 秒)。 +* `-t, --timeout TIMEOUT` 停止容器时候的超时(默认为 10 秒)。 #### `top` @@ -277,7 +277,7 @@ $ docker compose up -d --scale web=3 --scale db=2 格式为 `docker compose up [options] [SERVICE...]`。 -该命令十分强大,它将尝试自动完成包括构建镜像,(重新) 创建服务,启动服务,并关联服务相关容器的一系列操作。 +该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。 链接的服务都将会被自动启动,除非已经处于运行状态。 @@ -289,7 +289,7 @@ $ docker compose up -d --scale web=3 --scale db=2 如果使用 `docker compose up -d`,将会在后台启动并运行所有的容器。一般推荐生产环境下使用该选项。 -默认情况,如果服务容器已经存在,`docker compose up` 将会尝试停止容器,然后重新创建 (保持使用 `volumes-from` 挂载的卷),以保证新启动的服务匹配 Compose 文件的最新内容。如果用户不希望容器被停止并重新创建,可以使用 `docker compose up --no-recreate`。这样将只会启动处于停止状态的容器,而忽略已经运行的服务。如果用户只想重新部署某个服务,可以使用 `docker compose up --no-deps -d ` 来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。 +默认情况,如果服务容器已经存在,`docker compose up` 将会尝试停止容器,然后重新创建(保持使用 `volumes-from` 挂载的卷),以保证新启动的服务匹配 Compose 文件的最新内容。如果用户不希望容器被停止并重新创建,可以使用 `docker compose up --no-recreate`。这样将只会启动处于停止状态的容器,而忽略已经运行的服务。如果用户只想重新部署某个服务,可以使用 `docker compose up --no-deps -d ` 来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。 选项: @@ -305,7 +305,7 @@ $ docker compose up -d --scale web=3 --scale db=2 * `--no-build` 不自动构建缺失的服务镜像。 -* `-t, --timeout TIMEOUT` 停止容器时候的超时 (默认为 10 秒)。 +* `-t, --timeout TIMEOUT` 停止容器时候的超时(默认为 10 秒)。 #### `version` @@ -317,7 +317,7 @@ $ docker compose up -d --scale web=3 --scale db=2 格式为 `docker compose watch [options] [SERVICE...]`。 -启用开发模式,自动监视源代码并在文件发生变化时刷新服务。这需要项目中有 `compose.yaml` (或 `docker-compose.yml`),且定义了 `x-develop` 或 `develop` 配置段。 +启用开发模式,自动监视源代码并在文件发生变化时刷新服务。这需要项目中有 `compose.yaml`(或 `docker-compose.yml`),且定义了 `x-develop` 或 `develop` 配置段。 例如: diff --git a/11_compose/11.5_compose_file.md b/11_compose/11.5_compose_file.md index e3ffc1c..9340494 100644 --- a/11_compose/11.5_compose_file.md +++ b/11_compose/11.5_compose_file.md @@ -2,7 +2,7 @@ 模板文件是使用 `Compose` 的核心,涉及到的指令关键字也比较多。但大家不用担心,这里面大部分指令跟 `docker run` 相关参数的含义都是类似的。 -默认的模板文件名称为 `compose.yaml` (也兼容 `docker-compose.yml` 等历史文件名),格式为 YAML。 +默认的模板文件名称为 `compose.yaml`(也兼容 `docker-compose.yml` 等历史文件名),格式为 YAML。 本书同时维护一份可直接运行 `docker compose config` 校验的[完整 Compose 示例](../examples/validated/compose/compose.yaml)。下面的围栏与该文件由测试强制保持一致;需要复制完整文件时,以任一处为准。 @@ -17,15 +17,15 @@ services: - "8080:80" restart: unless-stopped ``` -注意每个服务都必须通过 `image` 指令指定镜像或 `build` 指令 (需要 Dockerfile) 等来自动构建生成镜像。 +注意每个服务都必须通过 `image` 指令指定镜像或 `build` 指令(需要 Dockerfile)等来自动构建生成镜像。 -如果使用 `build` 指令,在 `Dockerfile` 中设置的选项 (例如:`CMD`、`EXPOSE`、`VOLUME`、`ENV` 等) 将会自动被获取,无需在 Compose 文件中重复设置。 +如果使用 `build` 指令,在 `Dockerfile` 中设置的选项(例如:`CMD`、`EXPOSE`、`VOLUME`、`ENV` 等)将会自动被获取,无需在 Compose 文件中重复设置。 下面分别介绍各个指令的用法。 ### 11.5.1 `build` -指定 `Dockerfile` 所在文件夹的路径 (可以是绝对路径,或者相对 Compose 文件的路径)。`Compose` 将会利用它自动构建这个镜像,然后使用这个镜像。 +指定 `Dockerfile` 所在文件夹的路径(可以是绝对路径,或者相对 Compose 文件的路径)。`Compose` 将会利用它自动构建这个镜像,然后使用这个镜像。 ```yaml services: @@ -398,7 +398,7 @@ pid: "host" 暴露端口信息。 -使用宿主端口:容器端口 `(HOST:CONTAINER)` 格式,或者仅仅指定容器的端口 (宿主将会随机选择端口) 都可以。 +使用宿主端口:容器端口 `(HOST:CONTAINER)` 格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。 ```yaml ports: @@ -432,7 +432,7 @@ secrets: ### 11.5.28 `security_opt` -指定容器模板标签 (label) 机制的默认属性 (用户、角色、类型、级别等)。例如配置标签的用户名和角色名。 +指定容器模板标签 (label) 机制的默认属性(用户、角色、类型、级别等)。例如配置标签的用户名和角色名。 ```yaml security_opt: @@ -466,7 +466,7 @@ sysctls: 指定容器的 ulimits 限制值。 -例如,指定最大进程数为 65535,指定文件句柄数为 20000 (软限制,应用可以随时修改,不能超过硬限制) 和 40000 (系统硬限制,只能 root 用户提高)。 +例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制)和 40000(系统硬限制,只能 root 用户提高)。 ```yaml ulimits: diff --git a/11_compose/11.6_django.md b/11_compose/11.6_django.md index c27eab4..aa8efae 100644 --- a/11_compose/11.6_django.md +++ b/11_compose/11.6_django.md @@ -11,7 +11,7 @@ ### 11.6.1 架构概览 -在开始之前,先看整体架构 (如图 11-1 所示): +在开始之前,先看整体架构(如图 11-1 所示): ```mermaid flowchart TD @@ -42,7 +42,7 @@ flowchart TD - `web` 服务运行 Django 应用,对外暴露 8000 端口 - `db` 服务运行 PostgreSQL 数据库,只在内部网络可访问 - 两个服务通过 Docker Compose 自动创建的网络相互通信 -- `web` 服务可以通过服务名 `db` 访问数据库 (Docker 内置 DNS) +- `web` 服务可以通过服务名 `db` 访问数据库(Docker 内置 DNS) ### 11.6.2 准备工作 @@ -102,8 +102,8 @@ gunicorn>=21.0,<22.0 | 包名 | 作用 | |------|------| | `Django` | Web 框架 | -| `psycopg[binary]` | PostgreSQL 数据库驱动 (推荐使用 psycopg 3)| -| `gunicorn` | 生产环境 WSGI 服务器 (可选,开发时可不用)| +| `psycopg[binary]` | PostgreSQL 数据库驱动(推荐使用 psycopg 3)| +| `gunicorn` | 生产环境 WSGI 服务器(可选,开发时可不用)| ### 11.6.5 步骤 3:创建 compose.yaml @@ -255,7 +255,7 @@ $ docker compose up ``` 你会看到: -1. 首先构建 web 镜像 (第一次运行) +1. 首先构建 web 镜像(第一次运行) 2. 启动 db 服务,等待健康检查通过 3. 启动 web 服务 diff --git a/11_compose/11.7_rails.md b/11_compose/11.7_rails.md index fb7cca2..5acf6e2 100644 --- a/11_compose/11.7_rails.md +++ b/11_compose/11.7_rails.md @@ -149,7 +149,7 @@ $ docker compose run --rm web rails new . --force --database=postgresql --skip-b - `--rm`:执行后删除临时容器 - `--force`:覆盖已存在的文件 - `--database=postgresql`:配置使用 PostgreSQL -- `--skip-bundle`:暂不安装依赖 (稍后统一安装) +- `--skip-bundle`:暂不安装依赖(稍后统一安装) 生成的目录结构: @@ -278,7 +278,7 @@ $ docker compose run --rm web bundle update | 配置项 | 开发环境 | 生产环境 | |--------|---------|---------| -| Rails 服务器 | Puma (开发模式) | Puma + Nginx | +| Rails 服务器 | Puma(开发模式)| Puma + Nginx | | 代码挂载 | 使用 volumes | 代码打包进镜像 | | 静态资源 | 动态编译 | 预编译 (`rails assets:precompile`) | | 数据库密码 | 明文配置 | 使用 Secrets 管理 | diff --git a/11_compose/11.8_wordpress.md b/11_compose/11.8_wordpress.md index 067e3e5..6f360de 100644 --- a/11_compose/11.8_wordpress.md +++ b/11_compose/11.8_wordpress.md @@ -119,7 +119,7 @@ chmod 600 secrets/*.txt #### 3. PHP 配置优化 -默认的 WordPress 镜像上传文件限制较小 (通常 2MB)。创建 `uploads.ini`: +默认的 WordPress 镜像上传文件限制较小(通常 2MB)。创建 `uploads.ini`: ```ini file_uploads = On @@ -213,7 +213,7 @@ WordPress 支持 Redis 缓存以提高性能。 1. 检查 `docker compose logs wordpress` 2. 确认 `secrets/db_password.txt` 的内容正确,且与数据库初始化时使用的密码一致(改密码后需要重建 db 数据卷) -3. 确认 `WORDPRESS_DB_HOST` 也是 `db` (服务名) +3. 确认 `WORDPRESS_DB_HOST` 也是 `db`(服务名) 4. MySQL 8.4 可能需要几秒钟启动,WordPress 会自动重试,稍等片刻即可。 #### Q:无法上传大文件 diff --git a/11_compose/summary.md b/11_compose/summary.md index d98f41e..f7d2292 100644 --- a/11_compose/summary.md +++ b/11_compose/summary.md @@ -5,7 +5,7 @@ Docker Compose 是管理多容器应用的利器,通过 YAML 文件声明式 | 概念 | 要点 | |------|------| | **核心概念** | 服务 (service) 和项目 (project) | -| **配置文件** | `compose.yaml` (推荐) 或 `docker-compose.yml` | +| **配置文件** | `compose.yaml`(推荐)或 `docker-compose.yml` | | **版本** | Compose V2 为 Go 编写的 CLI 插件,通过 `docker compose` 使用 | | **启动** | `docker compose up -d` 启动所有服务 | | **停止** | `docker compose down` 停止并移除容器 | diff --git a/12_implementation/12.1_arch.md b/12_implementation/12.1_arch.md index d520276..051d3b3 100644 --- a/12_implementation/12.1_arch.md +++ b/12_implementation/12.1_arch.md @@ -4,7 +4,7 @@ Docker 的架构设计简洁而高效,主要由客户端和服务端两部分 ### 12.1.1 核心架构图 -Docker 采用了 **C/S (客户端/服务端)** 架构。Client 向 Daemon 发送请求,Daemon 负责构建、运行和分发容器。 +Docker 采用了 **C/S(客户端/服务端)** 架构。Client 向 Daemon 发送请求,Daemon 负责构建、运行和分发容器。 ```mermaid graph LR @@ -21,24 +21,24 @@ Docker 的内部架构如同洋葱一样分层,每一层专注解决特定问 #### 1. Docker CLI:客户端 -用户与 Docker 交互的主要方式。它将用户命令 (如 `docker run`) 转换为 API 请求发送给 dockerd。 +用户与 Docker 交互的主要方式。它将用户命令(如 `docker run`)转换为 API 请求发送给 dockerd。 #### 2. Dockerd:守护进程 Docker 的大脑。 - 监听 API 请求 -- 管理 Docker 对象 (镜像、容器、网络、卷) +- 管理 Docker 对象(镜像、容器、网络、卷) - 编排下层组件完成工作 #### 3. Containerd:高级运行时 -行业标准的容器运行时 (CNCF 毕业项目)。 +行业标准的容器运行时(CNCF 毕业项目)。 -- 管理容器的完整生命周期 (启动、停止) +- 管理容器的完整生命周期(启动、停止) - 镜像拉取与存储 -- **不包含** 复杂的与容器无关的功能 (如构建、API) -- Kubernetes 也可以直接使用 containerd (跳过 Docker) +- **不包含** 复杂的与容器无关的功能(如构建、API) +- Kubernetes 也可以直接使用 containerd(跳过 Docker) #### 4. Runc:低级运行时 @@ -46,7 +46,7 @@ Docker 的大脑。 - 直接与内核交互 (Namespaces,Cgroups) - 遵循 OCI (Open Container Initiative) 规范 -- **主要职责**:根据配置启动一个容器,然后退出 (将控制权交给容器进程) +- **主要职责**:根据配置启动一个容器,然后退出(将控制权交给容器进程) #### 5. Shim @@ -121,7 +121,7 @@ flowchart TD ``` - 使用轻量级虚拟机 (Apple Virtualization / WSL 2) 运行 Linux 内核 -- 文件挂载 (Bind Mount) 需要跨越 VM 边界 (这也是文件 I/O 慢的原因) +- 文件挂载 (Bind Mount) 需要跨越 VM 边界(这也是文件 I/O 慢的原因) - 网络端口需要从宿主机转发到 VM --- @@ -134,7 +134,7 @@ flowchart TD | **Dockerd** | 大管家 | API 接口,整体调度 | | **Containerd** | 经理 | 容器生命周期,镜像管理 | | **Shim** | 监工 | 保持 IO,允许无守护进程重启 | -| **Runc** | 工人 | 真正干活 (创建容器),干完就走 | +| **Runc** | 工人 | 真正干活(创建容器),干完就走 | ### 12.1.7 延伸阅读 diff --git a/12_implementation/12.2_namespace.md b/12_implementation/12.2_namespace.md index f6304a1..bb0b813 100644 --- a/12_implementation/12.2_namespace.md +++ b/12_implementation/12.2_namespace.md @@ -72,7 +72,7 @@ PID USER COMMAND - 容器内的 PID 1 进程特殊重要——它是容器的主进程,退出则容器停止 - 容器内无法看到宿主机或其他容器的进程 -- 宿主机可以看到所有容器内的进程 (但 PID 不同) +- 宿主机可以看到所有容器内的进程(但 PID 不同) --- @@ -106,7 +106,7 @@ flowchart LR #### NET 关键点 - 每个容器有独立的网卡、IP、路由表、iptables 规则 -- 多个容器可以监听相同端口 (如都监听 80) +- 多个容器可以监听相同端口(如都监听 80) - Docker 使用 veth pair 连接容器网络和宿主机网桥 --- @@ -186,7 +186,7 @@ IPC Namespace 用于隔离进程间通信资源,如 System V IPC 和 POSIX 消 #### IPC 关键点 - 同一容器内的进程可以通过 IPC 通信 -- 不同容器的进程无法通过 IPC 通信 (除非显式共享) +- 不同容器的进程无法通过 IPC 通信(除非显式共享) --- diff --git a/12_implementation/12.3_cgroups.md b/12_implementation/12.3_cgroups.md index 79cb81c..5b1b0ee 100644 --- a/12_implementation/12.3_cgroups.md +++ b/12_implementation/12.3_cgroups.md @@ -4,7 +4,7 @@ ### 12.3.1 什么是控制组 -控制组 (Control Groups,简称 cgroups) 是 Linux 内核的一个特性,用于 **限制、记录和隔离** 进程组的资源使用 (CPU、内存、磁盘 I/O、网络等)。 +控制组(Control Groups,简称 cgroups)是 Linux 内核的一个特性,用于 **限制、记录和隔离** 进程组的资源使用(CPU、内存、磁盘 I/O、网络等)。 > **核心作用**:让多个容器公平共享宿主机资源,防止单个容器耗尽系统资源。 @@ -75,10 +75,10 @@ $ docker run --memory-reservation 256m myapp ``` | 参数 | 说明 | |------|------| -| `-m` / `--memory` | 硬限制 (超过会 OOM Kill)| +| `-m` / `--memory` | 硬限制(超过会 OOM Kill)| | `--memory-swap` | 内存 + swap 总限制 | -| `--memory-reservation` | 软限制 (内存竞争时生效)| -| `--oom-kill-disable` | 禁用 OOM Killer (谨慎使用)| +| `--memory-reservation` | 软限制(内存竞争时生效)| +| `--oom-kill-disable` | 禁用 OOM Killer(谨慎使用)| #### CPU 限制 @@ -97,9 +97,9 @@ $ docker run --cpu-shares=512 myapp ``` | 参数 | 说明 | |------|------| -| `--cpus` | 限制 CPU 核心数 (如 1.5)| +| `--cpus` | 限制 CPU 核心数(如 1.5)| | `--cpuset-cpus` | 绑定到特定 CPU 核心 | -| `--cpu-shares` | CPU 时间片权重 (相对值)| +| `--cpu-shares` | CPU 时间片权重(相对值)| | `--cpu-period` / `--cpu-quota` | 精细控制 CPU 配额 | #### 磁盘 I/O 限制 @@ -190,10 +190,10 @@ $ docker run --rm --cpus=1 stress --cpu 4 | 特性 | cgroups v1 | cgroups v2 | |------|-----------|-----------| -| 层级结构 | 多层级 (每个资源单独)| 统一层级 | +| 层级结构 | 多层级(每个资源单独)| 统一层级 | | 管理复杂度 | 复杂 | 简化 | | 资源分配 | 基于层级 | 基于子树 | -| PSI (压力监控)| ❌ | ✅ | +| PSI(压力监控)| ❌ | ✅ | | rootless 容器 | 部分支持 | 完整支持 | #### Docker 对 cgroups v2 的支持 diff --git a/12_implementation/12.4_ufs.md b/12_implementation/12.4_ufs.md index 9b41a93..c96fa23 100644 --- a/12_implementation/12.4_ufs.md +++ b/12_implementation/12.4_ufs.md @@ -92,8 +92,8 @@ Docker 的存储驱动经历了从早期各式各样的机制(如 aufs, device | 存储后端 / 驱动 | 核心特性说明 | 推荐程度 | |---------|------|---------| -| **containerd image store**| (v29.x 新一代默认后端,新装默认) 基于 containerd 的 snapshotters,原生支持 OCI image index、多架构镜像与 Attestations 构建溯源元数据存储;启用 `userns-remap` 时不可用。 | ✅**强烈推荐 (现代默认)** | -| **overlay2**| (经典 Graph Driver) 传统架构下的现代 Linux 默认驱动,性能优秀,但在处理复杂溯源元数据(索引)时受限。 | ✅**推荐 (主要后备)** | +| **containerd image store**|(v29.x 新一代默认后端,新装默认)基于 containerd 的 snapshotters,原生支持 OCI image index、多架构镜像与 Attestations 构建溯源元数据存储;启用 `userns-remap` 时不可用。 | ✅**强烈推荐(现代默认)** | +| **overlay2**|(经典 Graph Driver)传统架构下的现代 Linux 默认驱动,性能优秀,但在处理复杂溯源元数据(索引)时受限。 | ✅**推荐(主要后备)** | | **aufs** | 早期默认,已从现代 Docker Engine 移除 | 历史资料 | | **btrfs**/**zfs** | 使用原生稳定文件系统快照能力 | 特定场景 | | **devicemapper** | 块设备级存储,已从现代 Docker Engine 移除 | 历史资料 | @@ -138,7 +138,7 @@ flowchart TD OverlayFS --> Lower1 ``` -- **lowerdir**:只读的镜像层 (可以有多个) +- **lowerdir**:只读的镜像层(可以有多个) - **upperdir**:可写的容器层 - **workdir**:OverlayFS 的工作目录 - **merged**:联合挂载后的视图 diff --git a/12_implementation/12.6_network.md b/12_implementation/12.6_network.md index 4e51b59..acc9ac9 100644 --- a/12_implementation/12.6_network.md +++ b/12_implementation/12.6_network.md @@ -1,15 +1,15 @@ ## 12.6 网络 -Docker 的网络实现其实就是利用了 Linux 上的网络命名空间和虚拟网络设备 (特别是 veth pair)。建议先熟悉了解这两部分的基本概念再阅读本章。 +Docker 的网络实现其实就是利用了 Linux 上的网络命名空间和虚拟网络设备(特别是 veth pair)。建议先熟悉了解这两部分的基本概念再阅读本章。 ### 12.6.1 基本原理 -首先,要实现网络通信,机器需要至少一个网络接口 (物理接口或虚拟接口) 来收发数据包;此外,如果不同子网之间要进行通信,需要路由机制。 +首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包;此外,如果不同子网之间要进行通信,需要路由机制。 Docker 中的网络接口默认都是虚拟的接口。虚拟接口的优势之一是转发效率较高。 Linux 通过在内核中进行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据包被直接复制到接收接口的接收缓存中。对于本地系统和容器内系统看来就像是一个正常的以太网卡,只是它不需要真正同外部网络设备通信,速度要快很多。 -Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通 (这样的一对接口叫做 `veth pair`)。 +Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做 `veth pair`)。 ### 12.6.2 创建网络参数 @@ -59,7 +59,7 @@ $ sudo ip link add A type veth peer name B $ sudo ip link set A master docker0 $ sudo ip link set A up ``` -将 B 放到容器的网络命名空间,命名为 eth0,启动它并配置一个可用 IP (桥接网段) 和默认网关。 +将 B 放到容器的网络命名空间,命名为 eth0,启动它并配置一个可用 IP(桥接网段)和默认网关。 ```bash $ sudo ip link set B netns $pid $ sudo ip netns exec $pid ip link set dev B name eth0 diff --git a/12_implementation/README.md b/12_implementation/README.md index 510810c..3b1de32 100644 --- a/12_implementation/README.md +++ b/12_implementation/README.md @@ -10,7 +10,7 @@ Docker 底层的核心技术包括 Linux 上的命名空间 (Namespaces)、控 要想实现虚拟化,除了要实现对内存、CPU、网络 IO、硬盘 IO、存储空间等的限制外,还要实现文件系统、网络、PID、UID、IPC 等等的相互隔离。 前者相对容易实现一些,后者则需要宿主机系统的深入支持。 -随着 Linux 系统对于命名空间功能的完善实现,程序员已经可以实现上面的所有需求,让某些进程在彼此隔离的命名空间中运行。大家虽然都共用一个内核和某些运行时环境 (例如一些系统命令和系统库),但是彼此却看不到,都以为系统中只有自己的存在。这种机制就是容器 (Container),利用命名空间来做权限的隔离控制,利用 cgroups 来做资源分配。 +随着 Linux 系统对于命名空间功能的完善实现,程序员已经可以实现上面的所有需求,让某些进程在彼此隔离的命名空间中运行。大家虽然都共用一个内核和某些运行时环境(例如一些系统命令和系统库),但是彼此却看不到,都以为系统中只有自己的存在。这种机制就是容器 (Container),利用命名空间来做权限的隔离控制,利用 cgroups 来做资源分配。 ## 本章内容 diff --git a/13_kubernetes_concepts/13.1_intro.md b/13_kubernetes_concepts/13.1_intro.md index ca6117d..bf90dd6 100644 --- a/13_kubernetes_concepts/13.1_intro.md +++ b/13_kubernetes_concepts/13.1_intro.md @@ -8,7 +8,7 @@ ### 13.1.1 什么是 Kubernetes -Kubernetes (常简称为 K8s) 是 Google 开源的容器编排引擎。如果说 Docker 解决了 “如何打包和运送集装箱” 的问题,那么 Kubernetes 解决的就是 “如何管理海量集装箱的调度、运行和维护” 的问题。 +Kubernetes(常简称为 K8s)是 Google 开源的容器编排引擎。如果说 Docker 解决了 “如何打包和运送集装箱” 的问题,那么 Kubernetes 解决的就是 “如何管理海量集装箱的调度、运行和维护” 的问题。 它不仅仅是一个编排系统,更是一个 **云原生应用操作系统**。 @@ -36,7 +36,7 @@ Kubernetes 的核心概念包括 Pod、Node、Deployment、Service 和 Namespace #### Pod:豆荚 -Kubernetes 的最小调度单位。一个 Pod 可以包含一个或多个紧密协作的容器 (共享网络和存储)。就像豌豆荚里的豌豆一样。 +Kubernetes 的最小调度单位。一个 Pod 可以包含一个或多个紧密协作的容器(共享网络和存储)。就像豌豆荚里的豌豆一样。 #### Node:节点 @@ -44,7 +44,7 @@ Kubernetes 的最小调度单位。一个 Pod 可以包含一个或多个紧密 #### Deployment:部署 -定义应用的期望状态 (如:需要 3 个副本,镜像版本为 v1)。K8s 会持续确保当前状态符合期望状态。 +定义应用的期望状态(如:需要 3 个副本,镜像版本为 v1)。K8s 会持续确保当前状态符合期望状态。 #### Service:服务 @@ -71,7 +71,7 @@ Kubernetes 的最小调度单位。一个 Pod 可以包含一个或多个紧密 ### 13.1.5 架构 -Kubernetes 也是 C/S 架构,由 **Control Plane (控制平面)** 和 **Worker Node (工作节点)** 组成: +Kubernetes 也是 C/S 架构,由 **Control Plane(控制平面)** 和 **Worker Node(工作节点)** 组成: - **Control Plane**:负责决策 (API Server,Scheduler,Controller Manager,etcd) - **Worker Node**:负责干活 (Kubelet,Kube-proxy,Container Runtime) diff --git a/13_kubernetes_concepts/13.2_concepts.md b/13_kubernetes_concepts/13.2_concepts.md index a93aeff..1b036bd 100644 --- a/13_kubernetes_concepts/13.2_concepts.md +++ b/13_kubernetes_concepts/13.2_concepts.md @@ -96,7 +96,7 @@ Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理 在一个容器组中,容器都使用相同的网络地址和端口,可以通过本地网络来相互通信。每个容器组都有独立的 IP,可以通过网络来和其他物理主机或者容器通信。 -容器组可以挂载一组存储卷 (挂载点)。卷不只用于持久化,也可用于 `emptyDir` 临时交换、ConfigMap/Secret 投射、日志旁路收集等场景。真正需要跨 Pod 生命周期保留的数据,应使用 PersistentVolume / PersistentVolumeClaim 等持久化机制。 +容器组可以挂载一组存储卷(挂载点)。卷不只用于持久化,也可用于 `emptyDir` 临时交换、ConfigMap/Secret 投射、日志旁路收集等场景。真正需要跨 Pod 生命周期保留的数据,应使用 PersistentVolume / PersistentVolumeClaim 等持久化机制。 #### 容器组管理 @@ -137,7 +137,7 @@ Pod 的重启策略 (`restartPolicy`) 决定了容器退出后的行为: | 重启策略 | 容器正常退出 | 容器异常退出 | |---------|------------|------------| -| **Always** (默认) | 重启容器 | 重启容器 | +| **Always**(默认)| 重启容器 | 重启容器 | | **OnFailure** | 不重启 | 重启容器 | | **Never** | 不重启 | 不重启 | diff --git a/13_kubernetes_concepts/13.3_design.md b/13_kubernetes_concepts/13.3_design.md index c112cc4..461cf6d 100644 --- a/13_kubernetes_concepts/13.3_design.md +++ b/13_kubernetes_concepts/13.3_design.md @@ -27,7 +27,7 @@ ### 13.3.3 控制平面 -控制平面 (Control Plane) 是 Kubernetes 集群的大脑,负责做出全局决策 (如调度) 以及检测和响应集群事件。 +控制平面 (Control Plane) 是 Kubernetes 集群的大脑,负责做出全局决策(如调度)以及检测和响应集群事件。 #### 主节点服务 @@ -35,7 +35,7 @@ * `apiserver` 是整个系统的对外接口,提供一套 RESTful 的 [Kubernetes API](https://kubernetes.io/zh-cn/docs/concepts/overview/kubernetes-api/),供客户端和其它组件调用; * `scheduler` 负责对资源进行调度,分配某个 pod 到某个节点上。是 pluggable 的,意味着很容易选择其它实现方式; -* `controller-manager` 负责管理控制器,包括 endpoint-controller (刷新服务和 pod 的关联信息) 和 replication-controller (维护某个 pod 的复制为配置的数值)。 +* `controller-manager` 负责管理控制器,包括 endpoint-controller(刷新服务和 pod 的关联信息)和 replication-controller(维护某个 pod 的复制为配置的数值)。 #### Etcd @@ -48,7 +48,7 @@ ### 13.3.4 工作节点 * kubelet 是工作节点执行操作的 agent,负责具体的容器生命周期管理,根据从数据库中获取的信息来管理容器,并上报 pod 运行状态等; -* kube-proxy 是一个简单的网络访问代理,同时也是一个 Load Balancer。它负责将访问到某个服务的请求具体分配给工作节点上的 Pod (同一类标签)。 +* kube-proxy 是一个简单的网络访问代理,同时也是一个 Load Balancer。它负责将访问到某个服务的请求具体分配给工作节点上的 Pod(同一类标签)。 ![Proxy 代理对服务的请求](./_images/kube-proxy.png) diff --git a/13_kubernetes_concepts/13.4_advanced.md b/13_kubernetes_concepts/13.4_advanced.md index a046969..ff247fd 100644 --- a/13_kubernetes_concepts/13.4_advanced.md +++ b/13_kubernetes_concepts/13.4_advanced.md @@ -4,7 +4,7 @@ ### 13.4.1 Helm - 包管理工具 -[Helm](https://helm.sh/) 被称为 Kubernetes 的包管理器 (类似于 Linux 的 apt/yum)。它将一组 Kubernetes 资源定义文件打包为一个 **Chart**。 +[Helm](https://helm.sh/) 被称为 Kubernetes 的包管理器(类似于 Linux 的 apt/yum)。它将一组 Kubernetes 资源定义文件打包为一个 **Chart**。 * **安装应用**:`helm install my-release bitnami/mysql` * **版本管理**:轻松回滚应用的发布版本。 @@ -57,16 +57,16 @@ Ingress 资源仍可正常使用,但建议新项目直接采用 Gateway API。 ### 13.4.3 Persistent Volume 与 StorageClass -容器内的文件是临时的。对于有状态应用 (如数据库),需要持久化存储。 +容器内的文件是临时的。对于有状态应用(如数据库),需要持久化存储。 * **PVC (Persistent Volume Claim)**:用户申请存储的声明。 -* **PV (Persistent Volume)**:实际的存储资源 (NFS,AWS EBS,Ceph 等)。 +* **PV (Persistent Volume)**:实际的存储资源(NFS,AWS EBS,Ceph 等)。 * **StorageClass**:定义存储类,支持动态创建 PV。 * **VolumeAttributesClass**:Kubernetes 1.34 起 GA,用于在 CSI 驱动支持 `ModifyVolume` 时动态调整卷属性,例如性能等级或服务质量参数。 ### 13.4.4 Horizontal Pod Autoscaling -HPA 根据 CPU 利用率或其他指标 (如内存、自定义指标) 自动扩缩 Deployment 或 ReplicaSet 中的 Pod 数量。 +HPA 根据 CPU 利用率或其他指标(如内存、自定义指标)自动扩缩 Deployment 或 ReplicaSet 中的 Pod 数量。 ```yaml apiVersion: autoscaling/v2 @@ -91,8 +91,8 @@ spec: ### 13.4.5 ConfigMap 与 Secret -* **ConfigMap**:存储非机密的配置数据 (配置文件、环境变量)。 -* **Secret**:存储机密数据 (密码、Token、证书)。Secret 值默认只是 Base64 编码并存入 etcd;生产环境应显式启用 etcd 静态加密或 KMS。 +* **ConfigMap**:存储非机密的配置数据(配置文件、环境变量)。 +* **Secret**:存储机密数据(密码、Token、证书)。Secret 值默认只是 Base64 编码并存入 etcd;生产环境应显式启用 etcd 静态加密或 KMS。 通过将配置与镜像分离,保证了容器的可移植性。 diff --git a/14_kubernetes_setup/14.1_kubeadm.md b/14_kubernetes_setup/14.1_kubeadm.md index b24abcf..4825727 100644 --- a/14_kubernetes_setup/14.1_kubeadm.md +++ b/14_kubernetes_setup/14.1_kubeadm.md @@ -2,7 +2,7 @@ `kubeadm` 提供了 `kubeadm init` 以及 `kubeadm join` 这两个命令,作为快速创建 `Kubernetes` 集群的常用工具。 -> **版本说明**:Kubernetes 版本更新较快 (约每 4 个月一个新版本),本文档基于 Kubernetes 1.36 编写。更完整的安装和兼容性说明请以 [Kubernetes 官方 kubeadm 文档](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/) 和 [containerd 官方文档](https://containerd.io/docs/) 为准。 +> **版本说明**:Kubernetes 版本更新较快(约每 4 个月一个新版本),本文档基于 Kubernetes 1.36 编写。更完整的安装和兼容性说明请以 [Kubernetes 官方 kubeadm 文档](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/) 和 [containerd 官方文档](https://containerd.io/docs/) 为准。 ### 14.1.1 安装 containerd @@ -239,7 +239,7 @@ CONTAINER_RUNTIME_ENDPOINT=unix:///run/containerd/containerd.sock crictl ps -a * `scheduler` 负责对资源进行调度,分配某个 pod 到某个节点上; -* `controller-manager` 负责管理控制器,包括 endpoint-controller (刷新服务和 pod 的关联信息) 和 replication-controller (维护某个 pod 的复制为配置的数值)。 +* `controller-manager` 负责管理控制器,包括 endpoint-controller(刷新服务和 pod 的关联信息)和 replication-controller(维护某个 pod 的复制为配置的数值)。 #### 工作节点服务 diff --git a/14_kubernetes_setup/14.2_kubeadm-docker.md b/14_kubernetes_setup/14.2_kubeadm-docker.md index 81a7e58..52193f6 100644 --- a/14_kubernetes_setup/14.2_kubeadm-docker.md +++ b/14_kubernetes_setup/14.2_kubeadm-docker.md @@ -8,7 +8,7 @@ > > 自 Kubernetes v1.24 起,内置的 `dockershim` 组件已被正式移除。这意味着 **Kubernetes 不再将 Docker Engine 作为默认内置的容器运行时**。虽然 Docker 仍然是你本地构建、管理镜像的绝佳工具,但它已不再是 kubelet 的默认运行时选项。 > -> 因此,**强烈推荐** 读者直接参考同目录下的《[使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)](14.1_kubeadm.md)》作为主要的部署路线。 +> 因此,**强烈推荐** 读者直接参考同目录下的《[使用 kubeadm 部署 Kubernetes(CRI 使用 containerd)](14.1_kubeadm.md)》作为主要的部署路线。 > > 本文档保留,主要用于历史环境维护或特殊需求场景:如果你必须在较新的 Kubernetes 集群中继续使用 Docker Engine 作为底层运行时,你必须理解 CRI 层机制,额外部署并配置第三方兼容层 `cri-dockerd`,同时在部署时手动补充 `--cri-socket` 等参数约束。 @@ -257,7 +257,7 @@ $ kubeadm join :6443 --token \ * `scheduler` 负责对资源进行调度,分配某个 pod 到某个节点上; -* `controller-manager` 负责管理控制器,包括 endpoint-controller (刷新服务和 pod 的关联信息) 和 replication-controller (维护某个 pod 的复制为配置的数值)。 +* `controller-manager` 负责管理控制器,包括 endpoint-controller(刷新服务和 pod 的关联信息)和 replication-controller(维护某个 pod 的复制为配置的数值)。 #### 工作节点服务 diff --git a/14_kubernetes_setup/14.4_kind.md b/14_kubernetes_setup/14.4_kind.md index 8f51b5e..679709c 100644 --- a/14_kubernetes_setup/14.4_kind.md +++ b/14_kubernetes_setup/14.4_kind.md @@ -6,12 +6,12 @@ ### 14.4.1 为什么选择 Kind -Kind 相比其他本地集群方案 (如 Minikube) 有以下显著优势: +Kind 相比其他本地集群方案(如 Minikube)有以下显著优势: * **轻量便捷**:只要有 Docker 环境即可,无需额外虚拟机。 * **多集群支持**:可以轻松在本地启动多个集群。 * **多版本支持**:支持指定 Kubernetes 版本进行测试。 -* **HA 支持**:支持模拟高可用集群 (多 Control Plane)。 +* **HA 支持**:支持模拟高可用集群(多 Control Plane)。 ### 14.4.2 安装 Kind diff --git a/14_kubernetes_setup/14.5_k3s.md b/14_kubernetes_setup/14.5_k3s.md index 1fb8e26..6abea23 100644 --- a/14_kubernetes_setup/14.5_k3s.md +++ b/14_kubernetes_setup/14.5_k3s.md @@ -6,7 +6,7 @@ ### 14.5.1 核心特性 -* **轻量级**:移除过时的、非必须的 Kubernetes 功能 (如传统的云提供商插件),使用 SQLite 作为默认数据存储 (也支持 Etcd/MySQL/Postgres)。 +* **轻量级**:移除过时的、非必须的 Kubernetes 功能(如传统的云提供商插件),使用 SQLite 作为默认数据存储(也支持 Etcd/MySQL/Postgres)。 * **单一二进制**:所有组件 (API Server,Controller Manager,Scheduler,Kubelet,Kube-proxy) 打包在一个进程中运行。 * **开箱即用**:内置 Helm Controller、Traefik Ingress controller、ServiceLB、Local-Path-Provisioner。 * **安全**:默认启用安全配置,基于 TLS 通信。 @@ -39,7 +39,7 @@ k3s-master Ready control-plane,master 1m v1.36.0+k3s1 ### 14.5.3 快速使用 -K3s 内置了 `kubectl` 命令 (通过 `k3s kubectl` 调用),为了方便,通常会建立别名或配置 `KUBECONFIG`。 +K3s 内置了 `kubectl` 命令(通过 `k3s kubectl` 调用),为了方便,通常会建立别名或配置 `KUBECONFIG`。 ```bash ## 读取 K3s 的配置文件 diff --git a/14_kubernetes_setup/README.md b/14_kubernetes_setup/README.md index 4d70a9e..b5e314d 100644 --- a/14_kubernetes_setup/README.md +++ b/14_kubernetes_setup/README.md @@ -1,12 +1,12 @@ # 第十四章 部署 Kubernetes -目前,Kubernetes 支持在多种环境下使用,包括本地主机 (Ubuntu、Debian、CentOS、Fedora 等)、云服务 ([腾讯云 TKE](https://cloud.tencent.com/product/tke)、[阿里云 ACK](https://cn.aliyun.com/product/ack)、[百度云](https://cloud.baidu.com/product/cce.html)等)。 +目前,Kubernetes 支持在多种环境下使用,包括本地主机(Ubuntu、Debian、CentOS、Fedora 等)、云服务([腾讯云 TKE](https://cloud.tencent.com/product/tke)、[阿里云 ACK](https://cn.aliyun.com/product/ack)、[百度云](https://cloud.baidu.com/product/cce.html)等)。 你可以使用以下几种方式部署 Kubernetes,接下来的小节会对各种方式进行详细介绍。 -* [使用 kubeadm 部署 (CRI 使用 containerd)](14.1_kubeadm.md) +* [使用 kubeadm 部署(CRI 使用 containerd)](14.1_kubeadm.md) * Kubernetes 也支持 CRI-O 等符合 CRI 的运行时;本文以 containerd 为主线。 -* [使用 kubeadm 部署 (使用 Docker)](14.2_kubeadm-docker.md) +* [使用 kubeadm 部署(使用 Docker)](14.2_kubeadm-docker.md) * [在 Docker Desktop 使用](14.3_docker-desktop.md) * [Kind - Kubernetes IN Docker](14.4_kind.md) * [K3s - 轻量级 Kubernetes](14.5_k3s.md) diff --git a/15_etcd/15.2_install.md b/15_etcd/15.2_install.md index 5b85641..84462b2 100644 --- a/15_etcd/15.2_install.md +++ b/15_etcd/15.2_install.md @@ -29,7 +29,7 @@ Documentation README-etcdctl.md README.md READMEv2-etcdctl.md etcd etcdctl ``` 其中 `etcd` 是服务主文件,`etcdctl` 是提供给用户的命令客户端,其他文件是支持文档。 -下面将 `etcd` `etcdctl` 文件放到系统可执行目录 (例如 `/usr/local/bin/`)。 +下面将 `etcd` `etcdctl` 文件放到系统可执行目录(例如 `/usr/local/bin/`)。 ```bash $ sudo cp etcd* /usr/local/bin/ diff --git a/15_etcd/15.3_cluster.md b/15_etcd/15.3_cluster.md index 6c5e34b..fbb86a8 100644 --- a/15_etcd/15.3_cluster.md +++ b/15_etcd/15.3_cluster.md @@ -4,7 +4,7 @@ 下面我们使用 [Docker Compose](../11_compose/README.md) 模拟启动一个 3 节点的 `etcd` 集群。 -编辑 `compose.yaml` (或 `docker-compose.yml`) 文件 +编辑 `compose.yaml`(或 `docker-compose.yml`)文件 ```yaml services: diff --git a/15_etcd/15.4_etcdctl.md b/15_etcd/15.4_etcdctl.md index 09109ab..e0efe37 100644 --- a/15_etcd/15.4_etcdctl.md +++ b/15_etcd/15.4_etcdctl.md @@ -87,7 +87,7 @@ OPTIONS: 数据库操作围绕键值和目录的增删改查(CRUD),覆盖其完整生命周期管理。 -etcd 在键的组织上采用了层次化的空间结构 (类似于文件系统中目录的概念),用户指定的键可以为单独的名字,如 `testkey`,此时实际上放在根目录 `/` 下面,也可以为指定目录结构,如 `cluster1/node2/testkey`,则将创建相应的目录结构。 +etcd 在键的组织上采用了层次化的空间结构(类似于文件系统中目录的概念),用户指定的键可以为单独的名字,如 `testkey`,此时实际上放在根目录 `/` 下面,也可以为指定目录结构,如 `cluster1/node2/testkey`,则将创建相应的目录结构。 > 注:CRUD 即 Create,Read,Update,Delete,是符合 REST 风格的一套 API 操作。 diff --git a/15_etcd/summary.md b/15_etcd/summary.md index 7fdc9fb..7cdfae3 100644 --- a/15_etcd/summary.md +++ b/15_etcd/summary.md @@ -7,7 +7,7 @@ etcd 是 Kubernetes 的核心存储组件,为分布式系统提供可靠的键 | **定位** | 分布式键值存储系统,用于配置管理和服务发现 | | **协议** | 基于 Raft 一致性算法,保证数据强一致 | | **API** | 提供 gRPC 和 HTTP API | -| **集群** | 建议使用奇数节点 (3 或 5 个) 部署 | +| **集群** | 建议使用奇数节点(3 或 5 个)部署 | | **etcdctl** | 命令行管理工具,支持 put/get/del/watch 等操作 | | **安全** | 支持 TLS 加密通信和 RBAC 访问控制 | diff --git a/16_cloud/16.1_intro.md b/16_cloud/16.1_intro.md index e44da2b..8e80f17 100644 --- a/16_cloud/16.1_intro.md +++ b/16_cloud/16.1_intro.md @@ -6,7 +6,7 @@ ### 16.1.1 容器编排托管服务 -这是目前最主流的形式。云厂商托管 Kubernetes 的控制平面 (Master 节点),用户只需管理工作节点 (Worker Node)。 +这是目前最主流的形式。云厂商托管 Kubernetes 的控制平面(Master 节点),用户只需管理工作节点 (Worker Node)。 * **优势**:降低了 Kubernetes 集群的维护成本,高可用性由厂商保证。 * **典型服务**:AWS EKS,Azure AKS,Google GKE,阿里云 ACK,腾讯云 TKE。 diff --git a/16_cloud/16.5_multicloud.md b/16_cloud/16.5_multicloud.md index 6602f13..d808631 100644 --- a/16_cloud/16.5_multicloud.md +++ b/16_cloud/16.5_multicloud.md @@ -9,7 +9,7 @@ | **版本更新** | 最快,通常是 K8s 新特性的首发地 | 相对保守,注重稳定性 | 跟随社区,更新速度适中 | | **控制平面管理** | 全托管,自动升级,$0.10/h(有 Free Tier 抵扣)| 托管,$0.10/h | 全托管;Free 层适合开发/测试,Standard/Premium 层默认包含 Uptime SLA | | **节点管理** | GKE Autopilot 模式完全托管节点 | Managed Node Groups 简化管理 | Virtual Machine Scale Sets | -| **网络模型** | VPC-native, 性能优秀 | AWS VPC CNI, Pod 直接获取 VPC IP | Azure CNI (消耗 IP 多) 或 Kubenet | +| **网络模型** | VPC-native, 性能优秀 | AWS VPC CNI, Pod 直接获取 VPC IP | Azure CNI(消耗 IP 多)或 Kubenet | | **集成度** | 与 GCP 数据分析、AI 服务集成紧密 | 与 AWS IAM, ALB, CloudWatch 集成深度高 | 与 Active Directory, Azure DevOps 集成好 | ### 16.5.2 多云部署策略 @@ -18,7 +18,7 @@ #### 1. 跨云灾备:Active-Passive -主要业务运行在一个云 (如 AWS),数据实时复制到另一个云 (如阿里云)。当主云发生故障时,流量切换到备云。 +主要业务运行在一个云(如 AWS),数据实时复制到另一个云(如阿里云)。当主云发生故障时,流量切换到备云。 * **优点**:架构相对简单,数据一致性好控制。 * **缺点**:资源闲置浪费,切换可能有 RTO。 diff --git a/17_ecosystem/17.1_coreos_intro.md b/17_ecosystem/17.1_coreos_intro.md index a23fd88..c09b25c 100644 --- a/17_ecosystem/17.1_coreos_intro.md +++ b/17_ecosystem/17.1_coreos_intro.md @@ -8,13 +8,13 @@ #### 一个最小化操作系统 -FCOS 被设计成一个基于容器的最小化的现代操作系统。它比现有的 Linux 安装平均节省 40% 的 RAM (大约 114M) 并允许从 PXE 或 iPXE 非常快速的启动。 +FCOS 被设计成一个基于容器的最小化的现代操作系统。它比现有的 Linux 安装平均节省 40% 的 RAM(大约 114M)并允许从 PXE 或 iPXE 非常快速的启动。 #### 系统初始化 -Ignition 是一种配置实用程序,可读取配置文件 (JSON 格式) 并根据该配置配置 FCOS 系统。可配置的组件包括存储,文件系统,systemd 和用户。 +Ignition 是一种配置实用程序,可读取配置文件(JSON 格式)并根据该配置配置 FCOS 系统。可配置的组件包括存储,文件系统,systemd 和用户。 -Ignition 在系统首次启动期间 (在 initramfs 中) 仅运行一次。由于 Ignition 在启动过程中的早期运行,因此它可以在用户空间开始启动之前重新对磁盘分区,格式化文件系统,创建用户并写入文件。当 systemd 启动时,systemd 服务已被写入磁盘,从而加快了启动时间。 +Ignition 在系统首次启动期间(在 initramfs 中)仅运行一次。由于 Ignition 在启动过程中的早期运行,因此它可以在用户空间开始启动之前重新对磁盘分区,格式化文件系统,创建用户并写入文件。当 systemd 启动时,systemd 服务已被写入磁盘,从而加快了启动时间。 #### 自动更新 diff --git a/17_ecosystem/17.2_coreos_install.md b/17_ecosystem/17.2_coreos_install.md index cbdf441..541854b 100644 --- a/17_ecosystem/17.2_coreos_install.md +++ b/17_ecosystem/17.2_coreos_install.md @@ -19,7 +19,7 @@ passwd: ssh_authorized_keys: - ssh-rsa AAAA... ``` -将 `ssh-rsa AAAA...` 替换为自己的 SSH 公钥 (位于 `~/.ssh/id_rsa.pub`)。 +将 `ssh-rsa AAAA...` 替换为自己的 SSH 公钥(位于 `~/.ssh/id_rsa.pub`)。 ### 17.2.3 转换 Butane 配置为 Ignition diff --git a/17_ecosystem/17.3_podman.md b/17_ecosystem/17.3_podman.md index 9385682..6db7ce7 100644 --- a/17_ecosystem/17.3_podman.md +++ b/17_ecosystem/17.3_podman.md @@ -11,7 +11,7 @@ Podman 和 Docker 在设计理念上存在显著差异,主要体现在架构 | 特性 | Docker | Podman | | :--- | :--- | :--- | | **架构** | C/S 架构,依赖守护进程 (`dockerd`) | 无守护进程 (Daemonless) | -| **权限** | 默认需要 root 权限 (虽有 Rootless 模式) | 默认支持 Rootless (非 root 用户运行) | +| **权限** | 默认需要 root 权限(虽有 Rootless 模式)| 默认支持 Rootless(非 root 用户运行)| | **生态** | 完整的生态系统 (Compose, Swarm) | 专注单机容器,配合 Kubernetes 使用 | | **镜像构建** | `docker build` | `podman build` 或 `buildah` | @@ -61,7 +61,7 @@ $ podman build -t myimage . ### 17.3.4 Pods 的概念 -与 Docker 不同,Podman 支持“Pod”的概念 (类似于 Kubernetes 的 Pod),允许你在同一个网络命名空间中运行多个容器。 +与 Docker 不同,Podman 支持“Pod”的概念(类似于 Kubernetes 的 Pod),允许你在同一个网络命名空间中运行多个容器。 ```bash ## 创建一个 Pod diff --git a/17_ecosystem/17.7_secure_runtime.md b/17_ecosystem/17.7_secure_runtime.md index 5a81203..7f6bcb6 100644 --- a/17_ecosystem/17.7_secure_runtime.md +++ b/17_ecosystem/17.7_secure_runtime.md @@ -44,7 +44,7 @@ gVisor 的核心组件是一个名为 **Sentry** 的用户空间进程。Sentry | 特性 | 标准 Linux 容器 (runc) | Kata Containers | gVisor (runsc) | | :--- | :--- | :--- | :--- | -| **隔离技术** | Namespace & Cgroups | 轻量级虚拟机 (独立内核) | 用户态内核 (系统调用拦截) | +| **隔离技术** | Namespace & Cgroups | 轻量级虚拟机(独立内核)| 用户态内核(系统调用拦截)| | **安全性** | 较低(共享宿主机内核) | 极高(硬件级虚拟化隔离) | 高(减少内核攻击面) | | **性能开销** | 极小(原生进程) | 中等(因轻量化而优于传统 VM) | 中等到较高(取决于系统调用频率开销) | | **启动速度** | 极快(毫秒/秒级) | 快(秒级之内) | 快(接近原生容器) | diff --git a/17_ecosystem/17.8_wasm.md b/17_ecosystem/17.8_wasm.md index 7f6c6e9..bbdc326 100644 --- a/17_ecosystem/17.8_wasm.md +++ b/17_ecosystem/17.8_wasm.md @@ -2,7 +2,7 @@ > **版本说明**:WebAssembly 和相关的 Wasm 运行时(如 WasmEdge、Spin)处于快速演进阶段。建议查阅 [WebAssembly 官方文档](https://webassembly.org/)、[WasmEdge](https://wasmedge.org/) 和 [Spin](https://spinframework.dev/) 官方文档获取最新信息。 -本节介绍 WebAssembly (简写为 Wasm) 以及它为何成为现代容器生态中备受瞩目的前沿技术路线。 +本节介绍 WebAssembly(简写为 Wasm)以及它为何成为现代容器生态中备受瞩目的前沿技术路线。 ### 17.8.1 什么是 WebAssembly? diff --git a/18_security/18.1_kernel_ns.md b/18_security/18.1_kernel_ns.md index 4457970..c306645 100644 --- a/18_security/18.1_kernel_ns.md +++ b/18_security/18.1_kernel_ns.md @@ -28,7 +28,7 @@ Docker 守护进程在启动容器时,会在后台为容器创建一套独立 在默认情况下,容器内的 `root` 用户(UID=0)就是宿主机上的 `root` 用户。如果攻击者设法突破了容器的其他隔离机制获取了宿主机的访问权限,他将拥有宿主机的最高系统权限。 -通过启用 **User Namespace Remapping (用户命名空间映射)**,我们可以将容器内的 `root` 用户映射到宿主机上的一个无特权普通用户。 +通过启用 **User Namespace Remapping(用户命名空间映射)**,我们可以将容器内的 `root` 用户映射到宿主机上的一个无特权普通用户。 #### 如何配置 User Namespace @@ -80,4 +80,4 @@ $ ps aux | grep sleep ### 18.1.4 总结 -内核命名空间从 Linux 2.6.15 版本 (2006 年) 被引入,十余年间,这些机制的可靠性在诸多大型生产系统中被实践验证。通过合理利用命名空间(尤其是 User Namespace),可以极大地收窄攻击面,显著提升容器部署的安全性。 +内核命名空间从 Linux 2.6.15 版本(2006 年)被引入,十余年间,这些机制的可靠性在诸多大型生产系统中被实践验证。通过合理利用命名空间(尤其是 User Namespace),可以极大地收窄攻击面,显著提升容器部署的安全性。 diff --git a/18_security/18.5_other_feature.md b/18_security/18.5_other_feature.md index 2d69054..01772d3 100644 --- a/18_security/18.5_other_feature.md +++ b/18_security/18.5_other_feature.md @@ -40,7 +40,7 @@ chmod: /etc/passwd: Operation not permitted ### 18.5.2 强制访问控制:AppArmor / SELinux -传统的 Linux 模型遵循 DAC(自主访问控制),这意味着如果一个文件被赋予了全员读写权限(`777`),普通隔离下任何人便都能修改。但 **MAC(强制访问控制)** 技术,诸如 `AppArmor` (常用于 Ubuntu/Debian) 或 `SELinux` (常用于 CentOS/RHEL),可以制定比“文件所有权”更宏观且优先的策略控制模块。 +传统的 Linux 模型遵循 DAC(自主访问控制),这意味着如果一个文件被赋予了全员读写权限(`777`),普通隔离下任何人便都能修改。但 **MAC(强制访问控制)** 技术,诸如 `AppArmor`(常用于 Ubuntu/Debian)或 `SELinux`(常用于 CentOS/RHEL),可以制定比“文件所有权”更宏观且优先的策略控制模块。 在开启了上述机制的机器上: diff --git a/19_observability/19.1_prometheus.md b/19_observability/19.1_prometheus.md index 7eb07ae..e880c0f 100644 --- a/19_observability/19.1_prometheus.md +++ b/19_observability/19.1_prometheus.md @@ -9,7 +9,7 @@ Prometheus 和 Grafana 是目前最流行的开源监控组合,前者负责数 Prometheus 的主要组件包括: * **Prometheus Server**:核心组件,负责收集和存储时间序列数据。 -* **Exporters**:负责向 Prometheus 暴露监控数据 (如 Node Exporter,cAdvisor)。 +* **Exporters**:负责向 Prometheus 暴露监控数据(如 Node Exporter,cAdvisor)。 * **Alertmanager**:处理报警发送。 * **Pushgateway**:用于支持短生命周期的 Job 推送数据。 @@ -19,8 +19,8 @@ Prometheus 的主要组件包括: 本节示例使用了: -* `node-exporter`:采集宿主机指标 (CPU、内存、磁盘、网络等)。 -* `cAdvisor`:采集容器指标 (容器 CPU/内存/网络 IO、文件系统等)。 +* `node-exporter`:采集宿主机指标(CPU、内存、磁盘、网络等)。 +* `cAdvisor`:采集容器指标(容器 CPU/内存/网络 IO、文件系统等)。 在生产环境中,建议将 Prometheus 的数据目录做持久化,并显式配置数据保留周期。 @@ -51,7 +51,7 @@ rule_files: #### 2. 编写 Docker Compose 文件 -创建 `compose.yaml` (或 `docker-compose.yml`)。下面示例使用的是相对较新的稳定版本。**镜像版本提示**:本示例中 Prometheus、Grafana、node-exporter、cAdvisor 的版本号仅为参考。生产环境部署前,请查阅以下官方资源确认最新推荐版本: +创建 `compose.yaml`(或 `docker-compose.yml`)。下面示例使用的是相对较新的稳定版本。**镜像版本提示**:本示例中 Prometheus、Grafana、node-exporter、cAdvisor 的版本号仅为参考。生产环境部署前,请查阅以下官方资源确认最新推荐版本: - [Prometheus 官方文档](https://prometheus.io/docs/prometheus/latest/installation/) - [Grafana 官方发布](https://grafana.com/grafana/download) - [node-exporter 发布页](https://github.com/prometheus/node_exporter/releases) @@ -119,7 +119,7 @@ $ docker compose up -d 启动后,访问以下地址: * Prometheus: `http://localhost:9090` -* Grafana:`http://localhost:3000` (账号为 `admin`,密码来自 `GRAFANA_ADMIN_PASSWORD`) +* Grafana:`http://localhost:3000`(账号为 `admin`,密码来自 `GRAFANA_ADMIN_PASSWORD`) > 安全提示:cAdvisor 需要读取宿主机 `/sys`、`/var/run`、Docker 数据目录等路径才能采集容器指标;即使是只读挂载,也会暴露宿主机和容器元数据。只在受控监控节点使用,并把 Prometheus、Grafana、cAdvisor 端口绑定到本机或受保护网络。 @@ -171,7 +171,7 @@ $ docker compose up -d 当 **Status -> Targets** 出现 `DOWN` 时,建议按以下顺序排查: -1. **网络连通性**:Prometheus 容器是否能解析并访问目标 (同一 Docker network、DNS、端口)。 +1. **网络连通性**:Prometheus 容器是否能解析并访问目标(同一 Docker network、DNS、端口)。 2. **端口/路径**:确认 exporter 监听端口与 Prometheus 配置一致;必要时在 Prometheus 容器内 `curl http://node-exporter:9100/metrics`。 3. **权限/挂载**:cAdvisor 需要访问宿主机 `/sys`、`/var/lib/docker` 等挂载路径,缺失会导致指标不全或报错。 4. **时间问题**:宿主机与容器时间偏差过大可能导致“数据看起来断档”,需要检查 NTP/时区配置。 @@ -255,7 +255,7 @@ receivers: networks: - monitoring ``` -生产环境中,建议将告警发送到可追踪的渠道 (如 IM 机器人、事件平台、工单系统),并在告警中附带 Dashboard 链接与排障入口,避免告警成为噪声。 +生产环境中,建议将告警发送到可追踪的渠道(如 IM 机器人、事件平台、工单系统),并在告警中附带 Dashboard 链接与排障入口,避免告警成为噪声。 #### 建议的文件清单 diff --git a/19_observability/19.2_elk.md b/19_observability/19.2_elk.md index 548cd15..1405e8a 100644 --- a/19_observability/19.2_elk.md +++ b/19_observability/19.2_elk.md @@ -17,7 +17,7 @@ ELK (Elasticsearch,Logstash,Kibana) 是目前业界最流行的开源日志 #### 1. 编写 Compose 文件 -1. 编写 `compose.yaml` (或 `docker-compose.yml`) 配置如下。**版本提示**:本示例使用 Elasticsearch 9.x、Kibana 9.x、Fluentd 等组件的特定版本号,仅作为参考。生产环境部署前,请查阅 [Elastic 官方文档](https://www.elastic.co/docs/) 和 [Fluentd 官方文档](https://docs.fluentd.org/) 确认最新版本与配置兼容性。 +1. 编写 `compose.yaml`(或 `docker-compose.yml`)配置如下。**版本提示**:本示例使用 Elasticsearch 9.x、Kibana 9.x、Fluentd 等组件的特定版本号,仅作为参考。生产环境部署前,请查阅 [Elastic 官方文档](https://www.elastic.co/docs/) 和 [Fluentd 官方文档](https://docs.fluentd.org/) 确认最新版本与配置兼容性。 ```yaml services: @@ -117,7 +117,7 @@ docker run -d \ 1. 访问 `http://localhost:5601`。 2. 进入 **Management**->**Kibana**->**Index Patterns**。 -3. 创建新的 Index Pattern,输入 `docker-*` (我们在 fluent.conf 中配置的前缀)。 +3. 创建新的 Index Pattern,输入 `docker-*`(我们在 fluent.conf 中配置的前缀)。 4. 选择 `@timestamp` 作为时间字段。 5. 去 **Discover** 页面,你就能看到 Nginx 容器的日志了。 @@ -152,7 +152,7 @@ docker run -d \ 如果 Elasticsearch 中已经有文档,但 Kibana 仍然为空,常见原因是: -* Index Pattern 没匹配到索引 (例如写成了 `docker-*` 但实际索引前缀不同)。 +* Index Pattern 没匹配到索引(例如写成了 `docker-*` 但实际索引前缀不同)。 * 时间字段没选对或时区不一致,导致 Discover 时间窗口内看不到数据。 ### 19.2.3 总结 @@ -166,7 +166,7 @@ docker run -d \ * **容量规划**:日志增长速度与磁盘占用直接相关。建议设置日志保留周期与索引生命周期策略 (ILM),避免 Elasticsearch 因磁盘水位触发只读或不可用。 * **资源配置**:Elasticsearch 对 JVM Heap 较敏感。除示例中的 `ES_JAVA_OPTS` 外,生产环境需要结合节点内存、分片规模、查询压力做评估。 * **链路可靠性**:采集端到存储端要考虑网络抖动、背压与重试策略;当 Elasticsearch 写入变慢时,采集端的缓冲与落盘策略决定了是否会丢日志。 -* **日志格式**:推荐应用输出结构化日志 (JSON) 并包含关键字段 (如 `trace_id`、`request_id`、`service`、`env`),以便快速过滤与关联分析。 +* **日志格式**:推荐应用输出结构化日志 (JSON) 并包含关键字段(如 `trace_id`、`request_id`、`service`、`env`),以便快速过滤与关联分析。 #### 索引与保留策略的落地建议 @@ -189,7 +189,7 @@ docker run -d \ #### 最小可用的“过期索引清理”示例 -如果你采用按天滚动索引 (例如 `docker-YYYY.MM.DD`),可以通过 Elasticsearch API 定期清理过期索引。 +如果你采用按天滚动索引(例如 `docker-YYYY.MM.DD`),可以通过 Elasticsearch API 定期清理过期索引。 下面示例仅用于演示思路:获取所有 `docker-` 前缀索引并删除指定索引。生产环境建议基于日期计算、灰度验证与权限控制后再执行自动化清理。 @@ -199,7 +199,7 @@ docker run -d \ curl -s http://localhost:9200/_cat/indices/docker-*?v ``` -2. 删除某个过期索引 (示例): +2. 删除某个过期索引(示例): ```bash curl -X DELETE http://localhost:9200/docker-2026.02.01 diff --git a/19_observability/README.md b/19_observability/README.md index 5cee76a..cc71d2d 100644 --- a/19_observability/README.md +++ b/19_observability/README.md @@ -2,7 +2,7 @@ 在生产环境中,容器化应用部署完成后,实时掌握容器的运行状态以及应用日志非常重要。本章将以 Docker/Compose 的场景为主,介绍容器监控与日志管理的落地思路与最小实践闭环。 -对于 Kubernetes 场景,可观测性链路与组件选择通常会有所不同 (例如使用 Prometheus Operator、日志采集 DaemonSet 等)。本章会在关键点给出迁移提示,但不会展开为完整的 Kubernetes 教程。 +对于 Kubernetes 场景,可观测性链路与组件选择通常会有所不同(例如使用 Prometheus Operator、日志采集 DaemonSet 等)。本章会在关键点给出迁移提示,但不会展开为完整的 Kubernetes 教程。 我们将重点探讨以下内容: @@ -13,7 +13,7 @@ * 关键指标与日志的验证方法 * 常见故障排查路径 -* 最小告警闭环 (Prometheus -> Alertmanager -> 接收端) +* 最小告警闭环(Prometheus -> Alertmanager -> 接收端) * 日志容量治理的最小实践 ## 本章内容 diff --git a/19_observability/summary.md b/19_observability/summary.md index 52b6abe..8838d61 100644 --- a/19_observability/summary.md +++ b/19_observability/summary.md @@ -18,7 +18,7 @@ Docker 提供了多种日志驱动 (Log Driver),用于将容器标准输出的 * `syslog`:将日志转发到 syslog 服务器。 * `journald`:将日志写入 systemd journal。 * `fluentd`:将日志转发到 fluentd 收集器。 -* `gelf`:支持 GELF 协议的日志后端 (如 Graylog)。 +* `gelf`:支持 GELF 协议的日志后端(如 Graylog)。 * `awslogs`:发送到 Amazon CloudWatch Logs。 生产建议:无论采用哪种驱动,都要明确日志的保留周期、容量上限与传输可靠性,避免“日志把磁盘写满”或“链路抖动导致丢日志”。 @@ -42,7 +42,7 @@ Docker 提供了多种日志驱动 (Log Driver),用于将容器标准输出的 你可以用下面的清单快速检查“是否具备最小生产可用性”: * Prometheus 数据目录已持久化,并设置了合理的保留周期。 -* Prometheus Targets 全部为 `UP`,并且关键查询 (CPU/内存/容器指标) 有数据。 +* Prometheus Targets 全部为 `UP`,并且关键查询(CPU/内存/容器指标)有数据。 * Grafana 已导入面板并能定位到具体实例/容器;默认账号密码已修改。 * 至少有一条关键告警已打通 Alertmanager 的接收链路,并验证告警能被正确发送与抑制。 * Elasticsearch 数据目录已持久化,并有明确的日志保留周期与容量上限策略。 diff --git a/20_cases_os/20.1_busybox.md b/20_cases_os/20.1_busybox.md index 6d4991a..8273f94 100644 --- a/20_cases_os/20.1_busybox.md +++ b/20_cases_os/20.1_busybox.md @@ -7,9 +7,9 @@ ![Busybox - Linux 瑞士军刀](../_images/busybox-logo.png) -`BusyBox` 是一个集成了一百多个最常用 Linux 命令和工具 (如 `cat`、`echo`、`grep`、`mount`、`telnet` 等) 的精简工具箱,它只需要几 MB 的大小,很方便进行各种快速验证,被誉为 “Linux 系统的瑞士军刀”。 +`BusyBox` 是一个集成了一百多个最常用 Linux 命令和工具(如 `cat`、`echo`、`grep`、`mount`、`telnet` 等)的精简工具箱,它只需要几 MB 的大小,很方便进行各种快速验证,被誉为 “Linux 系统的瑞士军刀”。 -`BusyBox` 可运行于多款 `POSIX` 环境的操作系统中,如 `Linux` (包括 `Android`)、`Hurd`、`FreeBSD` 等。 +`BusyBox` 可运行于多款 `POSIX` 环境的操作系统中,如 `Linux`(包括 `Android`)、`Hurd`、`FreeBSD` 等。 ### 20.1.2 获取官方镜像 diff --git a/20_cases_os/20.3_debian.md b/20_cases_os/20.3_debian.md index 8b82251..96d5471 100644 --- a/20_cases_os/20.3_debian.md +++ b/20_cases_os/20.3_debian.md @@ -36,7 +36,7 @@ Debian GNU/Linux 13 ![Ubuntu 操作系统](../_images/ubuntu-logo.jpg) -`Ubuntu` 是一个以桌面应用为主的 `GNU/Linux` 操作系统,其名称来自非洲南部祖鲁语或豪萨语的 “ubuntu” 一词 (官方译名 “友帮拓”,另有 “吾帮托”、“乌班图”、“有奔头” 或 “乌斑兔” 等译名)。`Ubuntu` 意思是 “人性” 以及 “我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的 “仁爱” 思想。`Ubuntu` 基于 `Debian` 发行版和 `GNOME/Unity` 桌面环境,与 `Debian` 的不同在于它每 6 个月会发布一个新版本,每 2 年推出一个长期支持 **(Long Term Support,LTS)** 版本;LTS 版本通常提供 5 年标准安全维护,Ubuntu Pro/ESM 可进一步延长安全覆盖。 +`Ubuntu` 是一个以桌面应用为主的 `GNU/Linux` 操作系统,其名称来自非洲南部祖鲁语或豪萨语的 “ubuntu” 一词(官方译名 “友帮拓”,另有 “吾帮托”、“乌班图”、“有奔头” 或 “乌斑兔” 等译名)。`Ubuntu` 意思是 “人性” 以及 “我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的 “仁爱” 思想。`Ubuntu` 基于 `Debian` 发行版和 `GNOME/Unity` 桌面环境,与 `Debian` 的不同在于它每 6 个月会发布一个新版本,每 2 年推出一个长期支持 **(Long Term Support,LTS)** 版本;LTS 版本通常提供 5 年标准安全维护,Ubuntu Pro/ESM 可进一步延长安全覆盖。 #### 使用 Ubuntu 官方镜像 diff --git a/20_cases_os/20.4_centos.md b/20_cases_os/20.4_centos.md index 9e49f07..b200199 100644 --- a/20_cases_os/20.4_centos.md +++ b/20_cases_os/20.4_centos.md @@ -7,7 +7,7 @@ ![CentOS 操作系统](../_images/centos-logo.png) -CentOS (Community Enterprise Operating System,中文意思是:社区企业操作系统),它是基于 `Red Hat Enterprise Linux` 源代码编译而成。由于 `CentOS` 与 `Redhat Linux` 源于相同的代码基础,所以很多成本敏感且需要高稳定性的公司就使用 `CentOS` 来替代商业版 `Red Hat Enterprise Linux`。`CentOS` 自身不包含闭源软件。 +CentOS(Community Enterprise Operating System,中文意思是:社区企业操作系统),它是基于 `Red Hat Enterprise Linux` 源代码编译而成。由于 `CentOS` 与 `Redhat Linux` 源于相同的代码基础,所以很多成本敏感且需要高稳定性的公司就使用 `CentOS` 来替代商业版 `Red Hat Enterprise Linux`。`CentOS` 自身不包含闭源软件。 #### 使用 CentOS 官方镜像 diff --git a/20_cases_os/README.md b/20_cases_os/README.md index 2e35b6c..376c5b2 100644 --- a/20_cases_os/README.md +++ b/20_cases_os/README.md @@ -2,7 +2,7 @@ ## 章节概述 -本章将介绍 Docker 在不同操作系统镜像场景下的实战案例。当你构建容器化应用时,选择合适的基础镜像至关重要。不同的操作系统镜像在大小、功能和性能方面各有特点,适用于不同的使用场景。本章通过具体的案例,详细讲解如何在 Docker 中使用主流操作系统镜像,包括轻量级镜像 (Busybox、Alpine) 和完整功能镜像 (Debian、Ubuntu、CentOS 等)。 +本章将介绍 Docker 在不同操作系统镜像场景下的实战案例。当你构建容器化应用时,选择合适的基础镜像至关重要。不同的操作系统镜像在大小、功能和性能方面各有特点,适用于不同的使用场景。本章通过具体的案例,详细讲解如何在 Docker 中使用主流操作系统镜像,包括轻量级镜像 (Busybox、Alpine) 和完整功能镜像(Debian、Ubuntu、CentOS 等)。 ## 版本说明 diff --git a/21_case_devops/21.1_devops_workflow.md b/21_case_devops/21.1_devops_workflow.md index a43107d..2f4f34c 100644 --- a/21_case_devops/21.1_devops_workflow.md +++ b/21_case_devops/21.1_devops_workflow.md @@ -82,9 +82,9 @@ deploy_staging: 1. **不可变基础设施**:一旦镜像构建完成,在各个环境(Dev、Staging、Prod)中都应该使用同一个镜像 tag(通常是 commit hash),而不是重新构建。 2. **配置分离**:使用 ConfigMap 和 Secret 管理环境特定的配置,不要打包进镜像。 3. **应对 Docker Hub 限额 (Rate Limits)**: - - Docker Hub 对匿名拉取实施了严格的限制 (6 小时内约 100 次)。若在 CI/CD 中频繁构建,极易触发 `toomanyrequests` 错误。 + - Docker Hub 对匿名拉取实施了严格的限制(6 小时内约 100 次)。若在 CI/CD 中频繁构建,极易触发 `toomanyrequests` 错误。 - **最佳策略**: - - 在流水线开头始终执行安全的身份认证 (使用 PAT,而非密码)。 + - 在流水线开头始终执行安全的身份认证(使用 PAT,而非密码)。 - 将常用的基础镜像缓存到自建的 Harbor/Nexus,使用 Pull-Through Cache。 - 开启 Docker 构建引擎 (BuildKit) 的 inline 或 registry 缓存功能,以降低全量拉取频率。 4. **GitOps**:考虑引入 ArgoCD,将部署配置也作为代码存储在 Git 中,实现 Git 驱动的部署同步。 diff --git a/21_case_devops/README.md b/21_case_devops/README.md index 810618e..2ada856 100644 --- a/21_case_devops/README.md +++ b/21_case_devops/README.md @@ -4,10 +4,10 @@ 本章示例中使用的镜像版本遵循以下原则: -- **GitHub Actions** (`actions/checkout@v7` 等) 采用大版本标签,代表最新的功能版本与稳定性的平衡 -- **编程语言镜像** (`golang:1.26-alpine`、`rust:1.95-alpine` 等) 采用次版本标签,确保 API 稳定性同时获得安全更新 -- **数据库镜像** (`postgres:16-alpine`、`redis:8-alpine` 等) 采用大版本标签,便于获得修复和改进 -- **基础镜像** (`alpine:3.21`、`debian:12` 等) 采用大版本或次版本标签,避免 `latest` 以确保可再现性 +- **GitHub Actions**(`actions/checkout@v7` 等)采用大版本标签,代表最新的功能版本与稳定性的平衡 +- **编程语言镜像**(`golang:1.26-alpine`、`rust:1.95-alpine` 等)采用次版本标签,确保 API 稳定性同时获得安全更新 +- **数据库镜像**(`postgres:16-alpine`、`redis:8-alpine` 等)采用大版本标签,便于获得修复和改进 +- **基础镜像**(`alpine:3.21`、`debian:12` 等)采用大版本或次版本标签,避免 `latest` 以确保可再现性 - 实际项目中应根据需求调整版本,生产环境建议定期更新以获取安全补丁 ## DevOps 背景介绍 diff --git a/README.md b/README.md index 5e87e66..cba2112 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,9 @@ ## 内容特色 -* **入门基础**:第 1 ~ 6 章为基础内容,帮助深入理解 Docker 的基本概念 (镜像、容器、仓库) 和核心操作。 +* **入门基础**:第 1 ~ 6 章为基础内容,帮助深入理解 Docker 的基本概念(镜像、容器、仓库)和核心操作。 * **进阶应用**:第 7 ~ 11 章涵盖 Dockerfile 指令详解、数据与网络管理、Buildx、Compose 等高级配置和管理操作。 -* **深入原理**:第 12 ~ 17 章介绍其底层实现技术,深入探讨容器编排体系 (Kubernetes、Etcd),并延伸涉及容器与云计算及其它关键生态项目 (Fedora CoreOS、Podman 等)。 +* **深入原理**:第 12 ~ 17 章介绍其底层实现技术,深入探讨容器编排体系 (Kubernetes、Etcd),并延伸涉及容器与云计算及其它关键生态项目(Fedora CoreOS、Podman 等)。 * **实战扩展**:第 18 ~ 21 章重点讨论容器安全防护机制、监控与日志聚合系统 (Prometheus、ELK),并展示操作系统、CI/CD 自动化构建等典型实践案例。 ## 五分钟快速上手 diff --git a/appendix/best_practices.md b/appendix/best_practices.md index 3854f61..67c7fc8 100644 --- a/appendix/best_practices.md +++ b/appendix/best_practices.md @@ -6,7 +6,7 @@ #### 容器应该是短暂的 -通过 `Dockerfile` 构建的镜像所启动的容器应该尽可能短暂 (生命周期短)。“短暂” 意味着可以停止和销毁容器,并且创建一个新容器并部署好所需的设置和配置工作量应该是极小的。 +通过 `Dockerfile` 构建的镜像所启动的容器应该尽可能短暂(生命周期短)。“短暂” 意味着可以停止和销毁容器,并且创建一个新容器并部署好所需的设置和配置工作量应该是极小的。 #### 使用 `.dockerignore` 文件 @@ -28,11 +28,11 @@ #### 镜像层数尽可能少 -你需要在 `Dockerfile` 可读性 (也包括长期的可维护性) 和减少层数之间做一个平衡。 +你需要在 `Dockerfile` 可读性(也包括长期的可维护性)和减少层数之间做一个平衡。 #### 将多行参数排序 -将多行参数按字母顺序排序 (比如要安装多个包时)。这可以帮助你避免重复包含同一个包,更新包列表时也更容易。也便于 `PRs` 阅读和审查。建议在反斜杠符号 `\` 之前添加一个空格,以增加可读性。 +将多行参数按字母顺序排序(比如要安装多个包时)。这可以帮助你避免重复包含同一个包,更新包列表时也更容易。也便于 `PRs` 阅读和审查。建议在反斜杠符号 `\` 之前添加一个空格,以增加可读性。 下面是来自 `buildpack-deps` 镜像的例子: @@ -51,7 +51,7 @@ RUN apt-get update && apt-get install -y \ 但是,如果你想在构建的过程中使用缓存,你得明白什么时候会,什么时候不会找到匹配的镜像,遵循的基本规则如下: -* 从一个基础镜像开始 (`FROM` 指令指定),下一条指令将和该基础镜像的所有子镜像进行匹配,检查这些子镜像被创建时使用的指令是否和被检查的指令完全一样。如果不是,则缓存失效。 +* 从一个基础镜像开始(`FROM` 指令指定),下一条指令将和该基础镜像的所有子镜像进行匹配,检查这些子镜像被创建时使用的指令是否和被检查的指令完全一样。如果不是,则缓存失效。 * 在大多数情况下,只需要简单地对比 `Dockerfile` 中的指令和子镜像。然而,有些指令需要更多的检查和解释。 * 对于 `ADD` 和 `COPY` 指令,镜像中对应文件的内容也会被检查,每个文件都会计算出一个校验和。文件的最后修改时间和最后访问时间不会纳入校验。在缓存的查找过程中,会将这些校验和与已存在镜像中的文件校验和进行对比。如果文件有任何改变,比如内容和元数据,则缓存失效。 * 除了 `ADD` 和 `COPY` 指令,缓存匹配过程不会查看临时容器中的文件来决定缓存是否匹配。例如,当执行完 `RUN apt-get -y update` 指令后,容器中一些文件被更新,但 Docker 不会检查这些文件。这种情况下,只有指令字符串本身被用来匹配缓存。 @@ -64,7 +64,7 @@ RUN apt-get update && apt-get install -y \ #### FROM -尽可能使用当前官方仓库作为你构建镜像的基础。推荐使用 [Alpine](https://hub.docker.com/_/alpine/) 镜像,因为它被严格控制并保持最小尺寸 (目前小于 5 MB),但它仍然是一个完整的发行版。 +尽可能使用当前官方仓库作为你构建镜像的基础。推荐使用 [Alpine](https://hub.docker.com/_/alpine/) 镜像,因为它被严格控制并保持最小尺寸(目前小于 5 MB),但它仍然是一个完整的发行版。 #### LABEL @@ -167,11 +167,11 @@ RUN apt-get update && apt-get install -y \ #### CMD -`CMD` 指令用于执行目标镜像中包含的软件,可以包含参数。`CMD` 大多数情况下都应该以 `CMD ["executable", "param1", "param2"...]` 的形式使用。因此,如果创建镜像的目的是为了部署某个服务 (比如 `Apache`),你可能会执行类似于 `CMD ["apache2", "-DFOREGROUND"]` 形式的命令。我们建议任何服务镜像都使用这种形式的命令。 +`CMD` 指令用于执行目标镜像中包含的软件,可以包含参数。`CMD` 大多数情况下都应该以 `CMD ["executable", "param1", "param2"...]` 的形式使用。因此,如果创建镜像的目的是为了部署某个服务(比如 `Apache`),你可能会执行类似于 `CMD ["apache2", "-DFOREGROUND"]` 形式的命令。我们建议任何服务镜像都使用这种形式的命令。 > 注意:exec 形式是 JSON 数组,**必须用双引号**。写成 `CMD ['apache2', '-DFOREGROUND']` 并不会报错,但 Docker 解析不出 JSON,会退回 shell 形式执行整串字符,导致启动失败。参见 [7.4 CMD](../07_dockerfile/7.4_cmd.md)。 -多数情况下,`CMD` 都需要一个交互式的 `shell` (bash,Python,perl 等),例如 `CMD ["perl", "-de0"]`,或者 `CMD ["php", "-a"]`。使用这种形式意味着,当你执行类似 `docker run -it python` 时,你会进入一个准备好的 `shell` 中。`CMD` 应该在极少的情况下才能以 `CMD ["param", "param"]` 的形式与 `ENTRYPOINT` 协同使用,除非你和你的镜像使用者都对 `ENTRYPOINT` 的工作方式十分熟悉。 +多数情况下,`CMD` 都需要一个交互式的 `shell`(bash,Python,perl 等),例如 `CMD ["perl", "-de0"]`,或者 `CMD ["php", "-a"]`。使用这种形式意味着,当你执行类似 `docker run -it python` 时,你会进入一个准备好的 `shell` 中。`CMD` 应该在极少的情况下才能以 `CMD ["param", "param"]` 的形式与 `ENTRYPOINT` 协同使用,除非你和你的镜像使用者都对 `ENTRYPOINT` 的工作方式十分熟悉。 #### EXPOSE @@ -200,7 +200,7 @@ ENV PATH=/usr/local/postgres-$PG_MAJOR/bin:$PATH #### ADD 和 COPY -虽然 `ADD` 和 `COPY` 功能类似,但一般优先使用 `COPY`。因为它比 `ADD` 更透明。`COPY` 只支持简单将本地文件拷贝到容器中,而 `ADD` 有一些并不明显的功能 (比如本地 tar 提取和远程 URL 支持)。因此,`ADD` 的最佳用例是将本地 tar 文件自动提取到镜像中,例如 `ADD rootfs.tar.xz`。 +虽然 `ADD` 和 `COPY` 功能类似,但一般优先使用 `COPY`。因为它比 `ADD` 更透明。`COPY` 只支持简单将本地文件拷贝到容器中,而 `ADD` 有一些并不明显的功能(比如本地 tar 提取和远程 URL 支持)。因此,`ADD` 的最佳用例是将本地 tar 文件自动提取到镜像中,例如 `ADD rootfs.tar.xz`。 如果你的 `Dockerfile` 有多个步骤需要使用上下文中不同的文件。单独 `COPY` 每个文件,而不是一次性的 `COPY` 所有文件,这将保证每个步骤的构建缓存只在特定的文件变化时失效。例如: @@ -236,7 +236,7 @@ RUN mkdir -p /usr/src/things \ #### ENTRYPOINT -`ENTRYPOINT` 的最佳用处是设置镜像的主命令,允许将镜像当成命令本身来运行 (用 `CMD` 提供默认选项)。 +`ENTRYPOINT` 的最佳用处是设置镜像的主命令,允许将镜像当成命令本身来运行(用 `CMD` 提供默认选项)。 例如,下面的示例镜像提供了命令行工具 `s3cmd`: @@ -314,7 +314,7 @@ $ docker run --rm -it postgres bash > 注意:在镜像中,用户和用户组每次被分配的 UID/GID 都是不确定的,下次重新构建镜像时被分配到的 UID/GID 可能会不一样。如果要依赖确定的 UID/GID,你应该显式的指定一个 UID/GID。 -你应该避免使用 `sudo`,因为它不可预期的 TTY 和信号转发行为可能造成的问题比它能解决的问题还多。如果你真的需要和 `sudo` 类似的功能 (例如,以 root 权限初始化某个守护进程,以非 root 权限执行它),你可以使用 [gosu](https://github.com/tianon/gosu)。 +你应该避免使用 `sudo`,因为它不可预期的 TTY 和信号转发行为可能造成的问题比它能解决的问题还多。如果你真的需要和 `sudo` 类似的功能(例如,以 root 权限初始化某个守护进程,以非 root 权限执行它),你可以使用 [gosu](https://github.com/tianon/gosu)。 最后,为了减少层数和复杂度,避免频繁地使用 `USER` 来回切换用户。 diff --git a/appendix/command/docker.md b/appendix/command/docker.md index c118623..f77c5fd 100644 --- a/appendix/command/docker.md +++ b/appendix/command/docker.md @@ -20,10 +20,10 @@ * `attach`:依附到一个正在运行的容器中; * `build`:从一个 Dockerfile 创建一个镜像; * `builder`:管理构建器与构建缓存,包括查看、清理等; -* `buildx`:扩展构建能力 (BuildKit),支持多平台构建、构建缓存导入导出等 (CLI 插件,详见第 10 章); -* `checkpoint`:管理容器检查点,用于保存和恢复容器运行状态 (实验特性); +* `buildx`:扩展构建能力 (BuildKit),支持多平台构建、构建缓存导入导出等(CLI 插件,详见第 10 章); +* `checkpoint`:管理容器检查点,用于保存和恢复容器运行状态(实验特性); * `commit`:从一个容器的修改中创建一个新的镜像; -* `compose`:定义并运行多容器应用 (CLI 插件,详见第 11 章); +* `compose`:定义并运行多容器应用(CLI 插件,详见第 11 章); * `config`:管理 swarm 集群中的配置项,包括创建、查看、删除等; * `container`:管理容器,`run`、`ps`、`exec` 等均是其子命令的快捷形式; * `context`:管理连接上下文,在多个 Docker 守护进程之间切换; @@ -36,11 +36,11 @@ * `history`:显示一个镜像的历史信息; * `image`:管理镜像,`images`、`pull`、`build` 等均是其子命令的快捷形式; * `images`:列出存在的镜像; -* `import`:导入一个文件 (典型为 `tar` 包) 路径或目录来创建一个本地镜像; +* `import`:导入一个文件(典型为 `tar` 包)路径或目录来创建一个本地镜像; * `info`:显示一些相关的系统信息; -* `init`:为项目生成 Dockerfile、compose.yaml 等初始文件 (CLI 插件); +* `init`:为项目生成 Dockerfile、compose.yaml 等初始文件(CLI 插件); * `inspect`:显示一个容器的具体配置信息; -* `kill`:关闭一个运行中的容器 (包括进程和所有相关资源); +* `kill`:关闭一个运行中的容器(包括进程和所有相关资源); * `load`:从一个 tar 包中加载一个镜像; * `login`:注册或登录到一个 Docker 的仓库服务器; * `logout`:从 Docker 的仓库服务器登出; @@ -60,13 +60,13 @@ * `rmi`:删除给定的若干个镜像; * `run`:创建一个新容器,并在其中运行给定命令; * `save`:保存一个镜像为 tar 包文件; -* `scout`:分析镜像的软件成分与已知漏洞 (CLI 插件); +* `scout`:分析镜像的软件成分与已知漏洞(CLI 插件); * `search`:在 Docker Hub 中搜索镜像; * `secret`:管理 swarm 集群中的密钥,包括创建、查看、删除等; * `service`:管理 Docker 所启动的应用服务,包括创建、更新、删除等; * `stack`:管理 swarm 集群中的应用栈,包括部署、查看、删除等; * `start`:启动一个容器; -* `stats`:输出 (一个或多个) 容器的资源使用统计信息; +* `stats`:输出(一个或多个)容器的资源使用统计信息; * `stop`:终止一个运行中的容器; * `swarm`:管理 Docker swarm 集群,包括创建、加入、退出、更新等; * `system`:管理 Docker 本身,包括查看磁盘占用、清理无用数据、订阅事件等; diff --git a/appendix/command/dockerd.md b/appendix/command/dockerd.md index 91ecc3a..59cf34f 100644 --- a/appendix/command/dockerd.md +++ b/appendix/command/dockerd.md @@ -7,13 +7,13 @@ ### 常用选项:Docker Engine 29.x * `--config-file="/etc/docker/daemon.json"`:指定 daemon 配置文件路径; -* `--data-root=""`:Docker 数据目录 (默认 `/var/lib/docker`); +* `--data-root=""`:Docker 数据目录(默认 `/var/lib/docker`); * `-H, --host=[]`:指定 daemon 监听地址 (Unix socket / TCP); * `-D, --debug`:开启调试日志; * `-l, --log-level="debug|info|warn|error|fatal"`:日志级别; -* `--group=""`:Unix socket 所属用户组 (默认 `docker`); +* `--group=""`:Unix socket 所属用户组(默认 `docker`); * `--containerd=""`:指定 containerd socket; -* `--exec-opt=[]`:运行时执行选项 (如 cgroup 驱动); +* `--exec-opt=[]`:运行时执行选项(如 cgroup 驱动); * `--default-ulimit=[]`:设置容器默认 ulimit; * `--dns=[]` / `--dns-search=[]` / `--dns-opt=[]`:DNS 配置; * `--registry-mirror=[]`:镜像加速地址; @@ -23,7 +23,7 @@ * `--storage-driver=""` / `--storage-opt=[]`:存储驱动及参数; * `--log-driver=""` / `--log-opt=[]`:容器日志驱动与参数; * `--authorization-plugin=[]`:鉴权插件; -* `--selinux-enabled=true|false`:启用 SELinux 集成 (依赖发行版策略); +* `--selinux-enabled=true|false`:启用 SELinux 集成(依赖发行版策略); * `--userns-remap=...`:用户命名空间映射; * `--tls` / `--tlscacert` / `--tlscert` / `--tlskey` / `--tlsverify`:TLS 安全配置。 diff --git a/appendix/debug.md b/appendix/debug.md index eecee49..2f1605b 100644 --- a/appendix/debug.md +++ b/appendix/debug.md @@ -2,7 +2,7 @@ ### 开启 Debug 模式 -在 dockerd 配置文件 daemon.json (默认位于 /etc/docker/) 中添加 +在 dockerd 配置文件 daemon.json(默认位于 /etc/docker/)中添加 ```json { @@ -69,11 +69,11 @@ $ sudo systemctl start docker 1. 检查 Docker DNS 配置 (`/etc/docker/daemon.json`)。 2. 检查宿主机防火墙 (iptables/firewalld) 是否拦截了转发。 -3. 容器内测试:`ping 8.8.8.8` (测试连通性),`nslookup google.com` (测试 DNS)。 +3. 容器内测试:`ping 8.8.8.8`(测试连通性),`nslookup google.com`(测试 DNS)。 ##### 端口映射不通 -1. 检查容器端口是否正确监听:`netstat -tunlp` (宿主机) 或 `docker exec netstat -tunlp`。 +1. 检查容器端口是否正确监听:`netstat -tunlp`(宿主机)或 `docker exec netstat -tunlp`。 2. 确认应用监听地址是 `0.0.0.0` 而不是 `127.0.0.1`。 * 如果应用监听在 `127.0.0.1`,只有容器内部能访问,映射到宿主机外部也无法被外部请求访问。 diff --git a/appendix/faq/README.md b/appendix/faq/README.md index 497f94c..7d5c6a2 100644 --- a/appendix/faq/README.md +++ b/appendix/faq/README.md @@ -107,7 +107,7 @@ $ docker run --network=my-net --ip=172.25.3.3 -itd --name=my-container busybox ### Docker 的配置文件放在哪里,如何修改配置? -答:使用 `systemd` 的系统 (如 Ubuntu 22.04+、Debian 12+、Rocky/Alma/CentOS Stream 9+) 的配置文件在 `/etc/docker/daemon.json`。 +答:使用 `systemd` 的系统(如 Ubuntu 22.04+、Debian 12+、Rocky/Alma/CentOS Stream 9+)的配置文件在 `/etc/docker/daemon.json`。 ### 如何更改 Docker 的默认存储位置? @@ -136,7 +136,7 @@ lrwxrwxrwx. 1 root root 15 11月 17 13:43 docker -> /storage/docker 答:如果遇到 `WARNING: Your kernel does not support cgroup swap limit` 等警告,这是因为系统默认没有开启对内存和 swap 使用的统计功能,引入该功能会带来性能的下降。要开启该功能,可以采取如下操作: -* 编辑 `/etc/default/grub` 文件 (Ubuntu 系统为例),配置 `GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"` +* 编辑 `/etc/default/grub` 文件(Ubuntu 系统为例),配置 `GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"` * 更新 grub:`$ sudo update-grub` * 重启系统,即可。 @@ -150,13 +150,13 @@ lrwxrwxrwx. 1 root root 15 11月 17 13:43 docker -> /storage/docker * 镜像系统:基于 OverlayFS 的镜像系统为容器的分发带来了很多的便利,同时共同的镜像层只需要存储一份,实现高效率的存储; * 版本管理:类似于 Git 的版本管理理念,用户可以更方便的创建、管理镜像文件; * 仓库系统:仓库系统大大降低了镜像的分发和管理的成本; -* 周边工具:各种现有工具 (配置管理、云平台) 对 Docker 的支持,以及基于 Docker 的 PaaS、CI 等系统,让 Docker 的应用更加方便和多样化。 +* 周边工具:各种现有工具(配置管理、云平台)对 Docker 的支持,以及基于 Docker 的 PaaS、CI 等系统,让 Docker 的应用更加方便和多样化。 ### Docker 与 Vagrant 有何不同? 答:两者的定位完全不同。 -* Vagrant 类似 Boot2Docker (一款运行 Docker 的最小内核),是一套虚拟机的管理环境。Vagrant 可以在多种系统上和虚拟机软件中运行,可以在 Windows,Mac 等非 Linux 平台上为 Docker 提供支持,自身具有较好的包装性和移植性。 +* Vagrant 类似 Boot2Docker(一款运行 Docker 的最小内核),是一套虚拟机的管理环境。Vagrant 可以在多种系统上和虚拟机软件中运行,可以在 Windows,Mac 等非 Linux 平台上为 Docker 提供支持,自身具有较好的包装性和移植性。 * 原生的 Docker 自身只能运行在 Linux 平台上,但启动和运行的性能都比虚拟机要快,往往更适合快速开发和部署应用的场景。 简单说:Vagrant 适合用来管理虚拟机,而 Docker 适合用来管理应用环境。 diff --git a/appendix/faq/errors.md b/appendix/faq/errors.md index 606dee2..bd53c79 100644 --- a/appendix/faq/errors.md +++ b/appendix/faq/errors.md @@ -7,7 +7,7 @@ | `manifest for ... not found: manifest unknown` | 镜像 tag 不存在 | 检查 Docker Hub 该镜像是否存在该 tag,或拼写是否正确 | | `connection refused` (pull image) | 网络不通或镜像源无法访问 | 检查网络,配置[镜像加速器](../../03_install/3.9_mirror.md) | | `Bind for 0.0.0.0:8080 failed: port is already allocated` | 端口被占用 | 检查占用端口的进程 (`lsof -i:8080`) 并杀掉,或换个端口映射 (`-p 8081:80`) | -| `exec user process caused "exec format error"` | 架构不匹配 (如在 x86 上跑 ARM 镜像) | 使用 `docker buildx` 构建多架构镜像,或拉取对应架构的镜像 | -| `standard_init_linux.go:211: exec user process caused "no such file or directory"` | 找不到解释器或依赖库 | 检查 `ENTRYPOINT`/`CMD` 脚本开头的 shebang (`#!/bin/sh` vs `#!/bin/bash`),或确认二进制文件是否依赖缺失 (Alpine 常见缺少 glibc) | +| `exec user process caused "exec format error"` | 架构不匹配(如在 x86 上跑 ARM 镜像)| 使用 `docker buildx` 构建多架构镜像,或拉取对应架构的镜像 | +| `standard_init_linux.go:211: exec user process caused "no such file or directory"` | 找不到解释器或依赖库 | 检查 `ENTRYPOINT`/`CMD` 脚本开头的 shebang (`#!/bin/sh` vs `#!/bin/bash`),或确认二进制文件是否依赖缺失(Alpine 常见缺少 glibc)| | `iptables: No chain/target/match by that name` | 防火墙规则缺失或冲突 | 重启 Docker 服务重置 iptables 链: `sudo systemctl restart docker` | | 容器内无法访问外网 | DNS 配置或转发问题 | 检查 `/etc/docker/daemon.json` 中的 DNS 配置 | diff --git a/appendix/glossary.md b/appendix/glossary.md index b29b153..694e467 100644 --- a/appendix/glossary.md +++ b/appendix/glossary.md @@ -9,21 +9,21 @@ ## B -* **Base Image (基础镜像)**:没有父镜像的镜像,通常是操作系统的最小安装集合(如 `ubuntu` 或 `alpine`)。 +* **Base Image(基础镜像)**:没有父镜像的镜像,通常是操作系统的最小安装集合(如 `ubuntu` 或 `alpine`)。 * **BuildKit**:Docker 下一代的构建引擎,提供了更高的构建性能、更好的缓存处理和并发构建支持。 * **Buildx**:Docker CLI 的一个插件,扩展了构建功能,支持 BuildKit 的所有高级特性,例如多系统架构镜像构建。 ## C * **Cgroups (Control Groups)**:控制组,Linux 内核特性,用于限制、记录、隔离进程组使用的物理资源(如 CPU、内存、磁盘 I/O 等)。 -* **Cluster (集群)**:一组协同工作的节点(如主机、虚拟机等),在容器领域常指 Kubernetes 集群。 +* **Cluster(集群)**:一组协同工作的节点(如主机、虚拟机等),在容器领域常指 Kubernetes 集群。 * **Compose (Docker Compose)**:用于定义和运行多容器 Docker 应用程序的工具,通过 YAML 文件配置应用服务。 -* **Container (容器)**:镜像的运行实例,带有额外的可写文件层,具有独立性。 +* **Container(容器)**:镜像的运行实例,带有额外的可写文件层,具有独立性。 * **Containerd**:行业标准的容器运行时,核心功能是管理宿主机上容器的生命周期(创建、启动、停止、销毁)。 ## D -* **Daemon (守护进程)**:Docker 的后台守护进程,负责接收和处理 Docker API 请求,并管理镜像、容器、网络和数据卷等对象。 +* **Daemon(守护进程)**:Docker 的后台守护进程,负责接收和处理 Docker API 请求,并管理镜像、容器、网络和数据卷等对象。 * **Docker**:开源的应用容器引擎,让开发者可以打包应用程序及其依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 或 Windows 机器上。 * **Docker Desktop**:包含 Docker Engine、Docker CLI 客户端、Docker Compose 和 Kubernetes 等的桌面应用程序,适用于 macOS 和 Windows。 * **Docker Hub**:Docker 官方的公共镜像仓库服务,提供容器镜像的存储和分发。 @@ -35,7 +35,7 @@ ## I -* **Image (镜像)**:Docker 镜像是一个只读模板,带有创建 Docker 容器的说明。 +* **Image(镜像)**:Docker 镜像是一个只读模板,带有创建 Docker 容器的说明。 ## K @@ -43,21 +43,21 @@ ## L -* **Layer (镜像层)**:Docker 镜像由多个只读层叠合而成,每一层通常代表 Dockerfile 中的一条指令的操作结果,通过联合文件系统(UFS)叠加在一起形成完整的文件系统。 +* **Layer(镜像层)**:Docker 镜像由多个只读层叠合而成,每一层通常代表 Dockerfile 中的一条指令的操作结果,通过联合文件系统(UFS)叠加在一起形成完整的文件系统。 ## M -* **Multistage Build (多阶段构建)**:Dockerfile 中的特性,允许在同一个 Dockerfile 中使用多个 `FROM` 语句,从一个阶段复制所需的构建产物到另一个阶段,从而大幅减小最终镜像的体积。 +* **Multistage Build(多阶段构建)**:Dockerfile 中的特性,允许在同一个 Dockerfile 中使用多个 `FROM` 语句,从一个阶段复制所需的构建产物到另一个阶段,从而大幅减小最终镜像的体积。 ## N -* **Namespace (命名空间)**:Linux 内核特性,用于隔离各种系统资源,如进程、网络、挂载点等,使容器看起来就像是一个独立的操作系统。 -* **Node (节点)**:容器集群(如 Kubernetes)中的一台工作机器,可以是物理机或虚拟机。 +* **Namespace(命名空间)**:Linux 内核特性,用于隔离各种系统资源,如进程、网络、挂载点等,使容器看起来就像是一个独立的操作系统。 +* **Node(节点)**:容器集群(如 Kubernetes)中的一台工作机器,可以是物理机或虚拟机。 ## O * **OCI (Open Container Initiative)**:开放容器规范,由多家行业领头企业共同制定的容器运行时和镜像格式的行业标准。 -* **Orchestration (编排)**:自动化部署、管理、扩展和网络配置容器的系统和技术(如 Kubernetes)。 +* **Orchestration(编排)**:自动化部署、管理、扩展和网络配置容器的系统和技术(如 Kubernetes)。 ## P @@ -66,8 +66,8 @@ ## R -* **Registry (注册服务器)**:提供 Docker 镜像下载和上传等存储分发服务的服务器。 -* **Repository (仓库)**:集中存放某个应用的所有镜像的地方,通常由镜像名定义。一个 Registry 中可以包含多个 Repository。 +* **Registry(注册服务器)**:提供 Docker 镜像下载和上传等存储分发服务的服务器。 +* **Repository(仓库)**:集中存放某个应用的所有镜像的地方,通常由镜像名定义。一个 Registry 中可以包含多个 Repository。 ## S @@ -79,4 +79,4 @@ ## V -* **Volume (数据卷)**:专为绕过联合文件系统而设计的特殊目录,用于实现容器数据的持久化,或在多个容器之间提供文件共享。 +* **Volume(数据卷)**:专为绕过联合文件系统而设计的特殊目录,用于实现容器数据的持久化,或在多个容器之间提供文件共享。 diff --git a/appendix/repo/centos.md b/appendix/repo/centos.md index 2385260..80540d8 100644 --- a/appendix/repo/centos.md +++ b/appendix/repo/centos.md @@ -9,18 +9,18 @@ > 2026 年了,对于任何新项目,**强烈建议** 使用以下生产级替代方案: > - [Rocky Linux](https://hub.docker.com/r/rockylinux/rockylinux):CentOS 原创始人发起的社区驱动项目,目前主流为 Rocky Linux 9。 > - [AlmaLinux](https://hub.docker.com/_/almalinux):由 CloudLinux 支持的企业级发行版,提供长期支持。 -> - [CentOS Stream](https://quay.io/repository/centos/centos):RHEL 的上游开发分支,镜像已迁移至 Quay.io (适合开发测试,不建议用于生产环境)。 +> - [CentOS Stream](https://quay.io/repository/centos/centos):RHEL 的上游开发分支,镜像已迁移至 Quay.io(适合开发测试,不建议用于生产环境)。 该仓库位于 [Docker Hub 的 CentOS 官方镜像页](https://hub.docker.com/_/centos),提供了 CentOS 从 5 ~ 8 各个版本的镜像(仅作为历史归档,不再更新)。 ### 使用方法 -使用 Rocky Linux 9 替代 (**推荐**): +使用 Rocky Linux 9 替代(**推荐**): ```bash $ docker run --name rocky -it rockylinux/rockylinux:9 bash ``` -使用旧版 CentOS 7 (**仅用于维护旧项目,不推荐**): +使用旧版 CentOS 7(**仅用于维护旧项目,不推荐**): ```bash $ docker run --name centos -it centos:7 bash diff --git a/appendix/repo/minio.md b/appendix/repo/minio.md index d727ad3..fab144e 100644 --- a/appendix/repo/minio.md +++ b/appendix/repo/minio.md @@ -40,7 +40,7 @@ $ docker load -i minio.tar - 把 `/mnt/data` 改成要替换的数据目录 - 替换 `MINIO_ROOT_USER` 的值 - 替换 `MINIO_ROOT_PASSWORD` 的值 -- 替换 name,minio1 (可选) +- 替换 name,minio1(可选) - 如果 9000、9090 端口冲突,替换端口前面的如 `9009:9000` ```bash diff --git a/appendix/repo/php.md b/appendix/repo/php.md index 2d7e5ba..1094df2 100644 --- a/appendix/repo/php.md +++ b/appendix/repo/php.md @@ -2,7 +2,7 @@ ### 基本信息 -[PHP](https://en.wikipedia.org/wiki/Php) (Hypertext Preprocessor 超文本预处理器的字母缩写) 是一种被广泛应用的开放源代码的多用途脚本语言,它可嵌入到 HTML 中,尤其适合 web 开发。 +[PHP](https://en.wikipedia.org/wiki/Php)(Hypertext Preprocessor 超文本预处理器的字母缩写)是一种被广泛应用的开放源代码的多用途脚本语言,它可嵌入到 HTML 中,尤其适合 web 开发。 该仓库位于 [Docker Hub 的 PHP 官方镜像页](https://hub.docker.com/_/php/)。具体可用版本以 Docker Hub 上的 tags 列表为准。