diff --git a/01_introduction/1.1_quickstart.md b/01_introduction/1.1_quickstart.md index 18eac7e..426d392 100644 --- a/01_introduction/1.1_quickstart.md +++ b/01_introduction/1.1_quickstart.md @@ -2,7 +2,7 @@ 本节将通过一个简单的 Web 应用例子,带你快速体验 Docker 的核心流程:构建镜像、运行容器。 -### 1. 准备代码 +### 1。准备代码 创建一个名为 `hello-docker` 的文件夹,并在其中创建一个 `index.html` 文件: @@ -10,7 +10,7 @@

Hello, Docker!

``` -### 2. 编写 Dockerfile +### 2。编写 Dockerfile 在同级目录下创建一个名为 `Dockerfile` (无后缀) 的文件: @@ -19,7 +19,7 @@ FROM nginx:alpine COPY index.html /usr/share/nginx/html/index.html ``` -### 3. 构建镜像 +### 3。构建镜像 打开终端,进入该目录,执行构建命令: @@ -27,11 +27,11 @@ COPY index.html /usr/share/nginx/html/index.html $ docker build -t my-hello-world . ``` -* `docker build`: 构建命令 -* `-t my-hello-world`: 给镜像起个名字(标签) -* `.`: 指定上下文路径为当前目录 +* `docker build`:构建命令 +* `-t my-hello-world`:给镜像起个名字 (标签) +* `.`:指定上下文路径为当前目录 -### 4. 运行容器 +### 4。运行容器 使用刚才构建的镜像启动一个容器: @@ -39,15 +39,15 @@ $ docker build -t my-hello-world . $ docker run -d -p 8080:80 my-hello-world ``` -* `docker run`: 运行命令 -* `-d`: 后台运行 -* `-p 8080:80`: 将宿主机的 8080 端口映射到容器的 80 端口 +* `docker run`:运行命令 +* `-d`:后台运行 +* `-p 8080:80`:将宿主机的 8080 端口映射到容器的 80 端口 -### 5. 访问测试 +### 5。访问测试 -打开浏览器访问 [http://localhost:8080](http://localhost:8080),你应该能看到 "Hello, Docker!"。 +打开浏览器访问 [http://localhost:8080](http://localhost:8080),你应该能看到 “Hello,Docker!”。 -### 6. 清理 +### 6。清理 停止并删除容器: @@ -65,4 +65,4 @@ $ docker stop $ docker rm ``` -恭喜!你已经完成了第一次 Docker 实战。接下来请阅读 [Docker 核心概念](../02_basic_concept/README.md) 做深入了解。 +恭喜!你已经完成了第一次 Docker 实战。接下来请阅读 [Docker 核心概念](../02_basic_concept/README.md)做深入了解。 diff --git a/01_introduction/1.2_what.md b/01_introduction/1.2_what.md index cb0121f..3b22e07 100644 --- a/01_introduction/1.2_what.md +++ b/01_introduction/1.2_what.md @@ -12,7 +12,7 @@ Docker 做的事情类似:无论你的应用是用 Python、Java、Node.js 还 ### Docker 的核心价值 -笔者认为,Docker 解决的是软件开发中最古老的问题之一:**"在我机器上明明能跑啊!"** +笔者认为,Docker 解决的是软件开发中最古老的问题之一:**“在我机器上明明能跑啊!”** ```mermaid flowchart LR @@ -44,7 +44,7 @@ flowchart LR ### Docker vs 虚拟机 -很多人第一次接触 Docker 时会问:**"这不就是虚拟机吗?"**答案是:**不是,而且差别很大。** +很多人第一次接触 Docker 时会问:**“这不就是虚拟机吗?”**答案是:**不是,而且差别很大。** #### 传统虚拟机 @@ -68,18 +68,22 @@ flowchart LR | **隔离级别** | 进程级隔离 | 完全隔离 | | **单机数量** | 可运行上千个 | 通常几十个 | -> 笔者经常用这个类比来解释:虚拟机像是每个应用都住在一栋独立的房子里(有自己的地基、水电系统),而容器像是大家住在同一栋公寓楼里的不同房间(共享地基和水电系统,但各自独立)。 +> 笔者经常用这个类比来解释:虚拟机像是每个应用都住在一栋独立的房子里 (有自己的地基、水电系统),而容器像是大家住在同一栋公寓楼里的不同房间 (共享地基和水电系统,但各自独立)。 ### Docker 的技术基础 -Docker 使用 [Go 语言](https://golang.google.cn/) 开发,基于 Linux 内核的以下技术: +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) > 如果你对这些底层技术感兴趣,可以阅读本书的[底层实现](../14_implementation/README.md)章节。 +#### 概述 + +总体概述了以下内容。 + #### Docker 架构演进 Docker 的底层实现经历了多次演进: @@ -95,14 +99,14 @@ flowchart LR end ``` -- **LXC**(2013):Docker 最初基于 Linux Containers -- **libcontainer**(2014,v0.7):Docker 自研的容器运行时 -- **runC**(2015,v1.11):捐献给 OCI 的标准容器运行时 +- **LXC** (2013):Docker 最初基于 Linux Containers +- **libcontainer** (2014,v0.7):Docker 自研的容器运行时 +- **runC** (2015,v1.11):捐献给 OCI 的标准容器运行时 - **containerd**:高级容器运行时,管理容器生命周期 ![Docker 架构](../_images/docker-on-linux.png) -> `runc` 是一个 Linux 命令行工具,用于根据 [OCI 容器运行时规范](https://github.com/opencontainers/runtime-spec) 创建和运行容器。 +> `runc` 是一个 Linux 命令行工具,用于根据 [OCI 容器运行时规范](https://github.com/opencontainers/runtime-spec)创建和运行容器。 > `containerd` 是一个守护程序,它管理容器生命周期,提供了在一个节点上执行容器和管理镜像的最小功能集。 @@ -113,8 +117,8 @@ flowchart LR Docker 的发展历程: - **2013 年 3 月**:开源发布 -- **2013 年底**:dotCloud 公司改名为 Docker, Inc. -- **2015 年**:成立 [开放容器联盟(OCI)](https://opencontainers.org/),推动容器标准化 -- **至今**:[GitHub 项目](https://github.com/moby/moby) 超过 7 万星标 +- **2013 年底**:dotCloud 公司改名为 Docker,Inc。 +- **2015 年**:成立[开放容器联盟 (OCI)](https://opencontainers.org/),推动容器标准化 +- **至今**:[GitHub 项目](https://github.com/moby/moby)超过 7 万星标 Docker 的成功推动了整个容器生态的发展,催生了 Kubernetes、Podman 等众多相关项目。笔者认为,Docker 最大的贡献不仅是技术本身,更是它**让容器技术从系统管理员的工具变成了每个开发者都能使用的标准工具**。 diff --git a/01_introduction/1.3_why.md b/01_introduction/1.3_why.md index c764168..7decc08 100644 --- a/01_introduction/1.3_why.md +++ b/01_introduction/1.3_why.md @@ -1,12 +1,12 @@ ## 1.3 为什么要使用 Docker? -在回答"为什么用 Docker"之前,笔者想先问一个问题:**你有没有经历过这些场景?** +在回答 “为什么用 Docker” 之前,笔者想先问一个问题:**你有没有经历过这些场景?** ### 没有 Docker 的世界 在 Docker 出现之前,软件开发和运维面临着诸多棘手的问题。我们先来看看以下三个典型的痛点场景。 -#### 场景一:"在我电脑上明明能跑" +#### 场景一:“在我电脑上明明能跑” 具体内容如下: @@ -20,10 +20,10 @@ 笔者统计过,这个问题通常由以下原因导致: - Python/Node/Java 版本不一致 -- 依赖库版本不一致 +- 依赖库版本不一致 - 操作系统配置不一致 - 某些环境变量没有设置 -- "哦,忘了说我本地装了个 XXX" +- “哦,忘了说我本地装了个 XXX” #### 场景二:环境配置的噩梦 @@ -51,7 +51,11 @@ ### Docker 如何解决这些问题 -Docker 的出现为上述问题提供了完美的解决方案。它通过"一次构建,到处运行"的核心理念,从根本上改变了软件交付的方式。 +Docker 的出现为上述问题提供了完美的解决方案。它通过 “一次构建,到处运行” 的核心理念,从根本上改变了软件交付的方式。 + +#### 概述 + +总体概述了以下内容。 #### 核心理念:一次构建,到处运行 @@ -74,12 +78,12 @@ flowchart TD 除了解决上述痛点,Docker 还拥有诸多显著的技术优势,包括环境一致性、秒级启动、高效的资源利用等。 -#### 1. 环境一致性 +#### 1。环境一致性 Docker 镜像包含了应用运行所需的**一切**:代码、运行时、系统工具、库、配置。这意味着: - ✅ 开发环境和生产环境完全一致 -- ✅ 不会再有"在我机器上能跑"的问题 +- ✅ 不会再有 “在我机器上能跑” 的问题 - ✅ 新人入职,一条命令就能启动开发环境 ```bash @@ -92,9 +96,9 @@ $ docker compose up ... ``` -#### 2. 秒级启动 +#### 2。秒级启动 -传统虚拟机启动需要几分钟(引导操作系统),而 Docker 容器启动通常只需要**几秒甚至几百毫秒**。 +传统虚拟机启动需要几分钟 (引导操作系统),而 Docker 容器启动通常只需要**几秒甚至几百毫秒**。 笔者实测数据: @@ -109,7 +113,7 @@ $ docker compose up - **弹性扩容**:流量高峰时能快速启动更多实例 - **开发体验**:快速重启服务进行调试 -#### 3. 资源效率 +#### 3。资源效率 Docker 容器共享宿主机内核,无需为每个应用运行完整的操作系统。 @@ -140,7 +144,7 @@ flowchart TD end ``` -#### 4. 持续交付和部署 +#### 4。持续交付和部署 Docker 完美契合 DevOps 的工作流程: @@ -156,17 +160,17 @@ flowchart LR - 任何人都能从代码重建完全相同的镜像 - 配合 [GitHub Actions](../15_cases/ci/actions/README.md) 等 CI 系统实现自动化 -#### 5. 轻松迁移 +#### 5。轻松迁移 Docker 可以在几乎任何平台上运行: -- ✅ 本地开发机(macOS、Windows、Linux) -- ✅ 公有云(AWS、Azure、GCP、阿里云、腾讯云) +- ✅ 本地开发机 (macOS、Windows、Linux) +- ✅ 公有云 (AWS、Azure、GCP、阿里云、腾讯云) - ✅ 私有云和自建数据中心 - ✅ 边缘设备和 IoT -**同一个镜像,在任何地方运行结果都一致。** 这让应用迁移变得前所未有的简单。 +**同一个镜像,在任何地方运行结果都一致。**这让应用迁移变得前所未有的简单。 -#### 6. 微服务架构的基石 +#### 6。微服务架构的基石 现代微服务架构几乎都依赖容器技术。Docker 让你可以: @@ -200,19 +204,19 @@ flowchart TD 笔者认为,技术选型要客观。Docker 并非银弹,以下场景可能不太适合: -#### 1. 需要完全隔离的场景 +#### 1。需要完全隔离的场景 容器共享宿主机内核,隔离性不如虚拟机。如果你需要运行不受信任的代码,虚拟机可能更安全。 -#### 2. 需要特殊内核的场景 +#### 2。需要特殊内核的场景 容器使用宿主机内核。如果应用需要特定版本的内核或内核模块,可能需要虚拟机。 -#### 3. Windows 原生应用 +#### 3。Windows 原生应用 虽然 Docker 支持 Windows 容器,但生态不如 Linux 容器成熟。传统 Windows 应用的容器化仍有挑战。 -#### 4. 桌面应用 +#### 4。桌面应用 Docker 主要面向服务端应用。桌面 GUI 应用的容器化虽然可行,但通常得不偿失。 diff --git a/01_introduction/README.md b/01_introduction/README.md index 58dfb39..9cef954 100644 --- a/01_introduction/README.md +++ b/01_introduction/README.md @@ -8,7 +8,7 @@ * 通过一个简单的 Web 应用例子,带你快速体验 Docker 的核心流程:构建镜像、运行容器。 * [什么是 Docker](1.2_what.md) - * 介绍 Docker 的起源、发展历程以及其背后的核心技术(Cgroups, Namespaces, UnionFS)。 + * 介绍 Docker 的起源、发展历程以及其背后的核心技术 (Cgroups,Namespaces,UnionFS)。 * 了解 Docker 是如何改变软件交付方式的。 * [为什么要用 Docker](1.3_why.md) diff --git a/01_introduction/summary.md b/01_introduction/summary.md index 3d99dca..e20f400 100644 --- a/01_introduction/summary.md +++ b/01_introduction/summary.md @@ -3,6 +3,6 @@ - Docker 是一种轻量级虚拟化技术,核心价值是**环境一致性** - 与虚拟机相比,Docker 更轻量、更快速、资源利用率更高 - Docker 基于 Linux 内核的 Namespace、Cgroups 和 Union FS 技术 -- Docker 推动了容器技术的标准化(OCI)和生态发展 +- Docker 推动了容器技术的标准化 (OCI) 和生态发展 -Docker 的核心价值可以用一句话概括:**让应用的开发、测试、部署保持一致,同时极大提高资源利用效率。**笔者认为,对于现代软件开发者来说,Docker 已经不是"要不要学"的问题,而是**必备技能**。无论你是前端、后端、运维还是全栈开发者,掌握 Docker 都能让你的工作更高效。 +Docker 的核心价值可以用一句话概括:**让应用的开发、测试、部署保持一致,同时极大提高资源利用效率。**笔者认为,对于现代软件开发者来说,Docker 已经不是 “要不要学” 的问题,而是**必备技能**。无论你是前端、后端、运维还是全栈开发者,掌握 Docker 都能让你的工作更高效。 diff --git a/02_basic_concept/2.1_image.md b/02_basic_concept/2.1_image.md index 4ef814f..887b6f8 100644 --- a/02_basic_concept/2.1_image.md +++ b/02_basic_concept/2.1_image.md @@ -27,7 +27,7 @@ flowchart TD 对于 Linux 而言,内核启动后会挂载 `root` 文件系统来提供用户空间支持。**Docker 镜像**本质上就是一个 `root` 文件系统。 -例如,官方镜像 `ubuntu:24.04` 包含了一套完整的 Ubuntu 24.04 最小系统的 root 文件系统——但**不包含 Linux 内核**(因为容器共享宿主机的内核)。 +例如,官方镜像 `ubuntu:24.04` 包含了一套完整的 Ubuntu 24.04 最小系统的 root 文件系统——但**不包含 Linux 内核** (因为容器共享宿主机的内核)。 ### 镜像包含什么? @@ -107,7 +107,7 @@ flowchart TD - **可共享**:多个镜像可以共享相同的层 - **有缓存**:未变化的层不会重新构建 -#### 分层存储的"陷阱" +#### 分层存储的 “陷阱” > ⚠️ **笔者特别提醒**:理解这一点可以帮你避免构建出臃肿的镜像。**关键原理**:每一层的文件变化会被记录,但**删除操作只是标记,不会真正减小镜像体积**。 @@ -159,7 +159,7 @@ a6bd71f48f68 2 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B Docker 镜像有多种标识方式: -#### 1. 镜像名称和标签 +#### 1。镜像名称和标签 格式:`[仓库地址/]仓库名[:标签]` @@ -178,7 +178,7 @@ ubuntu:24.04 nginx # 等同于 nginx:latest ``` -#### 2. 镜像 ID(Content-Addressable) +#### 2。镜像 ID (Content-Addressable) 每个镜像有一个基于内容计算的唯一 ID: @@ -189,7 +189,7 @@ nginx latest a6bd71f48f68 2 weeks ago 187MB ubuntu 24.04 ca2b0f26964c 3 weeks ago 78.1MB ``` -#### 3. 镜像摘要(Digest) +#### 3。镜像摘要 更精确的标识,基于镜像内容的 SHA256 哈希: diff --git a/02_basic_concept/2.2_container.md b/02_basic_concept/2.2_container.md index ea61aba..67de7cb 100644 --- a/02_basic_concept/2.2_container.md +++ b/02_basic_concept/2.2_container.md @@ -4,7 +4,7 @@ ### 一句话理解容器 -> **容器是镜像的运行实例。如果把镜像比作程序,那么容器就是进程。**用面向对象编程的术语来说:**镜像是类(Class),容器是对象(Instance)**。 +> **容器是镜像的运行实例。如果把镜像比作程序,那么容器就是进程。**用面向对象编程的术语来说:**镜像是类 (Class),容器是对象 (Instance)**。 - 一个镜像可以创建多个容器 - 每个容器相互独立,互不影响 @@ -78,7 +78,7 @@ flowchart TD #### 镜像层 + 容器层 -当容器运行时,Docker 会在镜像的只读层之上创建一个**可写层**(容器存储层): +当容器运行时,Docker 会在镜像的只读层之上创建一个**可写层** (容器存储层): ```mermaid flowchart TD @@ -91,7 +91,7 @@ flowchart TD ContainerLayer --> ImageLayerN --> ImageLayerN1 --> Dots --> ImageLayer1 ``` -#### Copy-on-Write(写时复制) +#### Copy-on-Write (写时复制) 当容器需要修改镜像层中的文件时: @@ -166,6 +166,10 @@ stateDiagram-v2 图 2-1 容器生命周期状态流转图 +#### 概述 + +总体概述了以下内容。 + #### 常用生命周期命令 运行以下命令: @@ -198,7 +202,7 @@ $ docker rm -f abc123 # 强制删除运行中的容器 ### 容器与进程的关系 -> **核心概念**:容器的生命周期 = 主进程(PID 1)的生命周期 +> **核心概念**:容器的生命周期 = 主进程 (PID 1) 的生命周期 ```bash ## 主进程运行,容器运行 diff --git a/02_basic_concept/2.3_repository.md b/02_basic_concept/2.3_repository.md index 6da2d77..63a354a 100644 --- a/02_basic_concept/2.3_repository.md +++ b/02_basic_concept/2.3_repository.md @@ -10,7 +10,7 @@ Docker Registry 是镜像分发和管理的核心组件。本节将介绍 Regist ### 核心概念 -要熟练使用 Docker Registry,首先需要理清它与仓库(Repository)、标签(Tag)之间的关系。 +要熟练使用 Docker Registry,首先需要理清它与仓库 (Repository)、标签 (Tag) 之间的关系。 #### Registry、仓库、标签的关系 @@ -43,6 +43,8 @@ flowchart TB 图 2-2 Registry、Repository 与 Tag 的层级关系 +相关基本概念具体如下: + | 概念 | 说明 | 示例 | |------|------|------| | **Registry** | 存储镜像的服务 | Docker Hub、ghcr.io | @@ -51,7 +53,7 @@ flowchart TB #### 镜像的完整名称 -一个完整的 Docker 镜像名称由 Registry 地址、用户名/组织名、仓库名和标签组成。了解其结构有助于我们更准确地定位镜像。 +一个完整的 Docker 镜像名称由 Registry 地址、用户名/组织名、仓库名和标签组成。了解其结构有助于我们更准确地定位镜像。基本格式如下: ``` [registry地址/][用户名/]仓库名[:标签] @@ -90,12 +92,13 @@ gcr.io/google-containers/pause:3.6 公共 Registry 服务为开发者提供了便捷的镜像获取途径。其中最著名的是 Docker Hub。 -#### Docker Hub(默认) +#### 默认的 Docker Hub [Docker Hub](https://hub.docker.com/) 是最大的公共 Registry,也是 Docker 的默认 Registry。 **特点**: -- 拥有大量[官方镜像](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 等) - 免费账户可以创建公开仓库 - 付费账户支持私有仓库 @@ -113,6 +116,8 @@ $ docker push username/myapp:v1.0 #### 其他公共 Registry +除了 Docker Hub,还有以下几个常见的公共 Registry: + | Registry | 地址 | 说明 | |----------|------|------| | **GitHub Container Registry** | ghcr.io | GitHub 提供,与 GitHub Actions 集成好 | @@ -123,7 +128,7 @@ $ docker push username/myapp:v1.0 ### 镜像加速器 -由于网络原因,在国内直接访问 Docker Hub 可能会很慢。可以配置**镜像加速器**(Registry Mirror)来加速下载。 +由于网络原因,在国内直接访问 Docker Hub 可能会很慢。可以配置**镜像加速器** (Registry Mirror) 来加速下载。配置示例如下: ```json // /etc/docker/daemon.json @@ -172,13 +177,14 @@ $ docker pull localhost:5000/myapp:v1.0 | **云厂商服务** | 阿里云 ACR、腾讯云 TCR、AWS ECR 等 | 笔者建议: + - 小团队:可以先用官方 Registry,够用即可 - 中大型团队:推荐 Harbor,功能完善且开源免费 - 已使用云服务:直接用云厂商的 Registry 服务更省心 ### 镜像的推送和拉取 -掌握镜像的推送(Push)和拉取(Pull)是使用 Docker Registry 的基本功。 +掌握镜像的推送 (Push) 和拉取 (Pull) 是使用 Docker Registry 的基本功。 #### 完整工作流程 @@ -235,7 +241,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 20bbf46..fea3145 100644 --- a/02_basic_concept/README.md +++ b/02_basic_concept/README.md @@ -1,9 +1,9 @@ -# 第二章 基本概念 +# 第二章基本概念 **Docker** 包括三个基本概念: -* **镜像**(`Image`):Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。 -* **容器**(`Container`):镜像(`Image`)和容器(`Container`)的关系,就像是面向对象程序设计中的 `类` 和 `实例` 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。 -* **仓库**(`Repository`):镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。 +* **镜像** (`Image`):Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数 (如匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后也不会被改变。 +* **容器** (`Container`):镜像 (`Image`) 和容器 (`Container`) 的关系,就像是面向对象程序设计中的 `类` 和 `实例` 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。 +* **仓库** (`Repository`):镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。 理解了这三个概念,就理解了 **Docker** 的整个生命周期。 diff --git a/02_basic_concept/summary.md b/02_basic_concept/summary.md index 4543148..be87c8d 100644 --- a/02_basic_concept/summary.md +++ b/02_basic_concept/summary.md @@ -29,7 +29,7 @@ ### 延伸阅读 - [启动容器](../05_container/5.1_run.md):详细的容器启动选项 -- [后台运行](../05_container/5.2_daemon.md):理解容器为什么会"立即退出" +- [后台运行](../05_container/5.2_daemon.md):理解容器为什么会 “立即退出” - [进入容器](../05_container/5.4_attach_exec.md):如何操作运行中的容器 - [数据管理](../08_data_network/README.md):Volume 和数据持久化详解 diff --git a/03_install/3.10_experimental.md b/03_install/3.10_experimental.md index b03eab7..32481b8 100644 --- a/03_install/3.10_experimental.md +++ b/03_install/3.10_experimental.md @@ -1,6 +1,6 @@ ## 3.10 开启实验特性 -一些 docker 命令或功能仅当 **实验特性** 开启时才能使用,请按照以下方法进行设置。 +一些 docker 命令或功能仅当**实验特性**开启时才能使用,请按照以下方法进行设置。 ### Docker CLI 的实验特性 diff --git a/03_install/3.1_ubuntu.md b/03_install/3.1_ubuntu.md index 96c21e2..a1ddc34 100644 --- a/03_install/3.1_ubuntu.md +++ b/03_install/3.1_ubuntu.md @@ -2,7 +2,7 @@ Ubuntu 是 Docker 最常用的运行环境之一。本节将介绍如何在 Ubuntu 系统上安装 Docker,并配置国内镜像加速。 ->警告:切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker. +>警告:切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker。 ### 准备工作 @@ -10,7 +10,7 @@ Ubuntu 是 Docker 最常用的运行环境之一。本节将介绍如何在 Ubun #### 系统要求 -Docker 支持诸多版本的 [Ubuntu](https://ubuntu.com/server) 操作系统。但是较旧的版本上将不会有 Docker 新版本的持续更新,以截至 2026 年初的几个 Ubuntu LTS(Long Term Support,长期支持)版本为例: +Docker 支持诸多版本的 [Ubuntu](https://ubuntu.com/server) 操作系统。但是较旧的版本上将不会有 Docker 新版本的持续更新,以截至 2026 年初的几个 Ubuntu LTS (Long Term Support,长期支持) 版本为例: * Ubuntu Noble 24.04 (LTS),Docker v29.x @@ -86,6 +86,10 @@ $ echo \ >以上命令会添加稳定版本的 Docker APT 镜像源,如果需要测试版本的 Docker 请将 stable 改为 test。 +#### 概述 + +总体概述了以下内容。 + #### 安装 Docker 更新 apt 软件包缓存,并安装 `docker-ce`: @@ -100,7 +104,7 @@ $ sudo apt install docker-ce docker-ce-cli containerd.io 在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Ubuntu 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装: -> 若你想安装测试版的 Docker, 请从 test.docker.com 获取脚本 +> 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash ## $ curl -fsSL test.docker.com -o get-docker.sh @@ -111,7 +115,7 @@ $ sudo sh get-docker.sh --mirror Aliyun ``` -执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中。 +执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定 (stable) 版本安装在系统中。 ### 启动 Docker diff --git a/03_install/3.2_debian.md b/03_install/3.2_debian.md index 0999627..0d3f773 100644 --- a/03_install/3.2_debian.md +++ b/03_install/3.2_debian.md @@ -2,7 +2,7 @@ Debian 以其稳定性著称,是 Docker 的理想宿主系统。本节将指导你在 Debian 上完成 Docker 的安装。 ->警告:切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker. +>警告:切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker。 ### 准备工作 @@ -57,7 +57,7 @@ $ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg -- 然后,我们需要向 `sources.list` 中添加 Docker 软件源: -> 在一些基于 Debian 的 Linux 发行版中 `$(lsb_release -cs)` 可能不会返回 Debian 的版本代号,例如 [Kali Linux](https://www.kali.org/docs/policy/kali-linux-relationship-with-debian/)、 [BunsenLabs Linux](https://www.bunsenlabs.org/)。在这些发行版中我们需要将下面命令中的 `$(lsb_release -cs)` 替换为 https://mirrors.aliyun.com/docker-ce/linux/debian/dists/ 中支持的 Debian 版本代号,例如 `buster`。 +> 在一些基于 Debian 的 Linux 发行版中 `$(lsb_release -cs)` 可能不会返回 Debian 的版本代号,例如 [Kali Linux](https://www.kali.org/docs/policy/kali-linux-relationship-with-debian/)、[BunsenLabs Linux](https://www.bunsenlabs.org/)。在这些发行版中我们需要将下面命令中的 `$(lsb_release -cs)` 替换为 https://mirrors.aliyun.com/docker-ce/linux/debian/dists/ 中支持的 Debian 版本代号,例如 `buster`。 ```bash $ echo \ @@ -75,7 +75,11 @@ $ echo \ ``` ->以上命令会添加稳定版本的 Docker APT 源,如果需要测试版本的 Docker 请将 stable 改为 test。 Debian11可能不使用`/etc/apt/keyrings/`, 如gpg错误可以考虑更换为`/etc/apt/trusted.gpg.d`, 见[issue 15727](https://github.com/docker/docs/issues/15727)。 +>以上命令会添加稳定版本的 Docker APT 源,如果需要测试版本的 Docker 请将 stable 改为 test。Debian11 可能不使用 `/etc/apt/keyrings/`,如 gpg 错误可以考虑更换为 `/etc/apt/trusted.gpg.d`,见 [issue 15727](https://github.com/docker/docs/issues/15727)。 + +#### 概述 + +总体概述了以下内容。 #### 安装 Docker @@ -91,7 +95,7 @@ $ sudo apt-get install docker-ce docker-ce-cli containerd.io 在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Debian 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装: -> 若你想安装测试版的 Docker, 请从 test.docker.com 获取脚本 +> 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash ## $ curl -fsSL test.docker.com -o get-docker.sh @@ -102,7 +106,7 @@ $ sudo sh get-docker.sh --mirror Aliyun ``` -执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中。 +执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定 (stable) 版本安装在系统中。 ### 启动 Docker diff --git a/03_install/3.3_fedora.md b/03_install/3.3_fedora.md index 7115e38..9b7f641 100644 --- a/03_install/3.3_fedora.md +++ b/03_install/3.3_fedora.md @@ -2,7 +2,7 @@ Fedora 作为技术前沿的 Linux 发行版,对 Docker 有着良好的支持。本节介绍在 Fedora 上的安装步骤。 ->警告:切勿在没有配置 Docker dnf 源的情况下直接使用 dnf 命令安装 Docker. +>警告:切勿在没有配置 Docker dnf 源的情况下直接使用 dnf 命令安装 Docker。 ### 准备工作 @@ -76,6 +76,10 @@ $ sudo dnf config-manager --set-enabled docker-ce-test $ sudo dnf config-manager --set-disabled docker-ce-test ``` +#### 概述 + +总体概述了以下内容。 + #### 安装 Docker 更新 `dnf` 软件源缓存,并安装 `docker-ce`。 @@ -99,7 +103,7 @@ $ sudo dnf -y install docker-ce-18.06.1.ce 在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Fedora 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装: -> 若你想安装测试版的 Docker, 请从 test.docker.com 获取脚本 +> 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash ## $ curl -fsSL test.docker.com -o get-docker.sh @@ -110,7 +114,7 @@ $ sudo sh get-docker.sh --mirror Aliyun ``` -执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 最新稳定(stable)版本安装在系统中。 +执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 最新稳定 (stable) 版本安装在系统中。 ### 启动 Docker diff --git a/03_install/3.4_centos.md b/03_install/3.4_centos.md index ff52e13..42cb937 100644 --- a/03_install/3.4_centos.md +++ b/03_install/3.4_centos.md @@ -1,8 +1,8 @@ ## 3.4 CentOS 安装 Docker -CentOS(及其替代品 Rocky Linux、AlmaLinux)是企业级服务器常用的操作系统。本节介绍在这些系统上安装 Docker 的步骤。 +CentOS (及其替代品 Rocky Linux、AlmaLinux) 是企业级服务器常用的操作系统。本节介绍在这些系统上安装 Docker 的步骤。 ->警告:切勿在没有配置 Docker YUM 源的情况下直接使用 yum 命令安装 Docker. +>警告:切勿在没有配置 Docker YUM 源的情况下直接使用 yum 命令安装 Docker。 ### 准备工作 @@ -10,7 +10,7 @@ CentOS(及其替代品 Rocky Linux、AlmaLinux)是企业级服务器常用 #### 系统要求 -> ⚠️ **重要提示**:CentOS 8 已于 2021 年 12 月 31 日停止维护,CentOS 7 已于 2024 年 6 月 30 日结束支持。建议新项目使用**Rocky Linux**或**AlmaLinux** 作为替代。 +> ⚠️ **重要提示**:CentOS 8 已于 2021 年 12 月 31 日停止维护,CentOS 7 已于 2024 年 6 月 30 日结束支持。建议新项目使用 **Rocky Linux** 或 **AlmaLinux** 作为替代。 Docker 支持 64 位版本 CentOS Stream 9、Rocky Linux 8/9、AlmaLinux 8/9,并且要求内核版本不低于 3.10。 @@ -72,6 +72,10 @@ $ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.r $ sudo dnf config-manager --set-enabled docker-ce-test ``` +#### 概述 + +总体概述了以下内容。 + #### 安装 Docker 更新 `dnf` 软件源缓存,并安装 `docker-ce`。 @@ -104,7 +108,7 @@ $ firewall-cmd --reload 在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,CentOS 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装: -> 若你想安装测试版的 Docker, 请从 test.docker.com 获取脚本 +> 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash ## $ curl -fsSL test.docker.com -o get-docker.sh @@ -115,7 +119,7 @@ $ sudo sh get-docker.sh --mirror Aliyun ``` -执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中。 +执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定 (stable) 版本安装在系统中。 ### 启动 Docker diff --git a/03_install/3.5_raspberry-pi.md b/03_install/3.5_raspberry-pi.md index 1bb3cae..2234d72 100644 --- a/03_install/3.5_raspberry-pi.md +++ b/03_install/3.5_raspberry-pi.md @@ -2,7 +2,7 @@ 树莓派等 ARM 架构设备在物联网和边缘计算领域应用广泛。本节介绍如何在树莓派上安装 Docker。 ->警告:切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker. +>警告:切勿在没有配置 Docker APT 源的情况下直接使用 apt 命令安装 Docker。 ### 系统要求 @@ -16,7 +16,7 @@ Docker 支持以下版本的 [Raspberry Pi OS](https://www.raspberrypi.org/softw * Raspberry Pi OS Bookworm * Raspberry Pi OS Bullseye -*注:* `Raspberry Pi OS` 由树莓派的开发与维护机构 [树莓派基金会](https://www.raspberrypi.org/) 官方支持,并推荐用作树莓派的首选系统,其基于 `Debian`。 +*注:*`Raspberry Pi OS` 由树莓派的开发与维护机构[树莓派基金会](https://www.raspberrypi.org/)官方支持,并推荐用作树莓派的首选系统,其基于 `Debian`。 ### 使用 APT 安装 @@ -77,7 +77,7 @@ $ echo \ #### 报错解决办法 -在 `Raspberry Pi OS Bullseye/Bookworm` 中,如果你使用 `add-apt-repository` 添加源,可能会出现如下报错(推荐改用上面的 `tee` 方式来写入 `/etc/apt/sources.list.d/docker.list`,可避免此问题): +在 `Raspberry Pi OS Bullseye/Bookworm` 中,如果你使用 `add-apt-repository` 添加源,可能会出现如下报错 (推荐改用上面的 `tee` 方式来写入 `/etc/apt/sources.list.d/docker.list`,可避免此问题): ```bash Traceback (most recent call last): @@ -92,7 +92,7 @@ Traceback (most recent call last): aptsources.distro.NoDistroTemplateException: Error: could not find a distribution template for Raspbian/bullseye ``` -通过以下命令手动添加镜像源到 `/etc/apt/sources.list` 文件中即可解决: +通过以下命令手动添加镜像源到 `/etc/apt/sources.list` 文件中即可解决: ```bash $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirrors.aliyun.com/docker-ce/linux/raspbian $(lsb_release -cs) stable" | sudo tee -a /etc/apt/sources.list @@ -118,7 +118,7 @@ $ sudo apt-get install docker-ce 在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Raspberry Pi OS 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装: -> 若你想安装测试版的 Docker, 请从 test.docker.com 获取脚本 +> 若你想安装测试版的 Docker,请从 test.docker.com 获取脚本 ```bash ## $ curl -fsSL test.docker.com -o get-docker.sh @@ -129,7 +129,7 @@ $ sudo sh get-docker.sh --mirror Aliyun ``` -执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定(stable)版本安装在系统中。 +执行这个命令后,脚本就会自动的将一切准备工作做好,并且把 Docker 的稳定 (stable) 版本安装在系统中。 ### 启动 Docker @@ -195,7 +195,7 @@ For more examples and ideas, visit: 若能正常输出以上信息,则说明安装成功。 -*注意:* ARM 平台不能使用 `x86` 镜像,查看 Raspberry Pi OS 可使用镜像请访问 [arm32v7](https://hub.docker.com/u/arm32v7/) 或者 [arm64v8](https://hub.docker.com/u/arm64v8/)。 +*注意:*ARM 平台不能使用 `x86` 镜像,查看 Raspberry Pi OS 可使用镜像请访问 [arm32v7](https://hub.docker.com/u/arm32v7/) 或者 [arm64v8](https://hub.docker.com/u/arm64v8/)。 ### 镜像加速 diff --git a/03_install/3.6_offline.md b/03_install/3.6_offline.md index e6418ed..2fc3469 100644 --- a/03_install/3.6_offline.md +++ b/03_install/3.6_offline.md @@ -2,23 +2,27 @@ \[TOC] -生产环境中一般都是没有公网资源的,本文介绍如何在生产服务器上离线部署`Docker` +生产环境中一般都是没有公网资源的,本文介绍如何在生产服务器上离线部署 `Docker` 括号内的字母表示该操作需要在哪些服务器上执行 ![Docker-offile-install-top](../_images/image-20200412202617411.png) -### CentOS/Rocky/AlmaLinux 离线安装Docker +### 概述 + +总体概述了以下内容。 + +### CentOS/Rocky/AlmaLinux 离线安装 Docker 在无法连接外网的安全环境中,离线安装是唯一的选择。本节介绍如何在 RHEL 系发行版中进行离线安装。 > 注意:以下命令以 CentOS 7 为例。对于 CentOS Stream 9、Rocky Linux 9 或 AlmaLinux 9,请将 `yum` 替换为 `dnf`,并将软件包后缀 `el7` 替换为 `el9`。 -#### YUM本地文件安装(推荐) +#### YUM 本地文件安装 (推荐) 推荐这种方式,是因为在生产环境种一般会选定某个指定的文档软件版本使用。 -##### 查询可用的软件版本(A) +##### 查询可用的软件版本 运行以下命令: @@ -47,7 +51,7 @@ docker-ce.x86_64 3:19.03.1-3.el7 docker-ce-stable .... ``` -##### 下载到指定文件夹(A) +##### 下载到指定文件夹 运行以下命令: @@ -84,15 +88,15 @@ Total exiting because "Download Only" specified ``` -##### 复制到目标服务器之后进入文件夹安装(C-N) +##### 复制到目标服务器之后进入文件夹安装 (C-N) -* 离线安装时,必须使用rpm命令不检查依赖的方式安装 +* 离线安装时,必须使用 rpm 命令不检查依赖的方式安装 ```bash rpm -Uvh *.rpm --nodeps --force ``` -##### 锁定软件版本(C-N) +##### 锁定软件版本 (C-N) **下载锁定版本软件** @@ -149,9 +153,11 @@ versionlock deleted: 1 sudo yum versionlock delete all ``` -#### YUM 本地源服务器搭建安装Docker +#### YUM 本地源服务器搭建安装 Docker -##### 挂载 ISO 镜像搭建本地 File 源(AB) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +##### 挂载 ISO 镜像搭建本地 File 源 运行以下命令: @@ -184,7 +190,7 @@ yum clean all yum install createrepo -y ``` -##### 根据本地文件搭建BASE网络源(B) +##### 根据本地文件搭建 BASE 网络源 运行以下命令: @@ -206,9 +212,9 @@ systemctl enable httpd systemctl start httpd ``` -##### 下载Docker-CE 镜像仓库(A) +##### 下载 Docker-CE 镜像仓库 -在有网络的服务器上下载Docker-ce镜像 +在有网络的服务器上下载 Docker-ce 镜像 ```bash ## 下载清华的镜像源文件 @@ -226,7 +232,7 @@ mkdir /tmp/docker-ce/ reposync -r docker-ce-stable -p /tmp/docker-ce/ ``` -##### 创建仓库索引(B) +##### 创建仓库索引 把下载的 docker-ce 文件夹复制到离线的服务器 @@ -238,7 +244,7 @@ reposync -r docker-ce-stable -p /tmp/docker-ce/ createrepo /var/www/html/docker-ce/ ``` -##### YUM 客户端设置(C...N) +##### YUM 客户端设置 (C...N) 运行以下命令: @@ -265,7 +271,7 @@ EOF ``` -##### Docker 安装(C...N) +##### Docker 安装 (C...N) 运行以下命令: diff --git a/03_install/3.7_mac.md b/03_install/3.7_mac.md index 76660ff..f603112 100644 --- a/03_install/3.7_mac.md +++ b/03_install/3.7_mac.md @@ -1,5 +1,7 @@ ## 3.7 macOS +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 系统要求 [Docker Desktop for Mac](https://docs.docker.com/docker-for-mac/) 要求系统最低为 macOS Sonora 14.0 或更高版本,建议升级到最新版本的 macOS。 @@ -18,11 +20,11 @@ $ brew install --cask docker #### 手动下载安装 -如果需要手动下载,请点击以下 [链接](https://desktop.docker.com/mac/main/amd64/Docker.dmg) 下载 Docker Desktop for Mac。 +如果需要手动下载,请点击以下[链接](https://desktop.docker.com/mac/main/amd64/Docker.dmg)下载 Docker Desktop for Mac。 -> 如果你的电脑搭载的是 Apple Silicon 芯片(`arm64` 架构),请点击以下 [链接](https://desktop.docker.com/mac/main/arm64/Docker.dmg) 下载 Docker Desktop for Mac。你可以在 [官方文档](https://docs.docker.com/docker-for-mac/apple-silicon/) 查阅已知的问题。 +> 如果你的电脑搭载的是 Apple Silicon 芯片 (`arm64` 架构),请点击以下[链接](https://desktop.docker.com/mac/main/arm64/Docker.dmg)下载 Docker Desktop for Mac。你可以在[官方文档](https://docs.docker.com/docker-for-mac/apple-silicon/)查阅已知的问题。 -如同 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.png) @@ -53,7 +55,7 @@ Docker version 26.1.1, build 4cf5afa $ docker run -d -p 80:80 --name webserver nginx ``` -服务运行后,可以访问 [http://localhost](http://localhost),如果看到了 "Welcome to nginx!",就说明 Docker Desktop for Mac 安装成功了。 +服务运行后,可以访问 [http://localhost](http://localhost),如果看到了 “Welcome to nginx!”,就说明 Docker Desktop for Mac 安装成功了。 ![](../_images/install-mac-example-nginx.png) diff --git a/03_install/3.8_windows.md b/03_install/3.8_windows.md index 69a9099..430a255 100644 --- a/03_install/3.8_windows.md +++ b/03_install/3.8_windows.md @@ -4,17 +4,17 @@ ### 系统要求 -[Docker Desktop for Windows](https://docs.docker.com/desktop/setup/install/windows-install/) 支持 64 位版本的 Windows 11 或 Windows 10(需开启 Hyper-V),推荐使用 Windows 11。 +[Docker Desktop for Windows](https://docs.docker.com/desktop/setup/install/windows-install/) 支持 64 位版本的 Windows 11 或 Windows 10 (需开启 Hyper-V),推荐使用 Windows 11。 ### 安装 **手动下载安装** -点击以下 [链接](https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe) 下载 Docker Desktop for Windows。 +点击以下[链接](https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe)下载 Docker Desktop for Windows。 下载好之后双击 `Docker Desktop Installer.exe` 开始安装。 -**使用**[**winget**](https://docs.microsoft.com/zh-cn/windows/package-manager/)**安装** +**使用** [**winget**](https://docs.microsoft.com/zh-cn/windows/package-manager/) **安装** ```powershell $ winget install Docker.DockerDesktop @@ -26,7 +26,7 @@ $ winget install Docker.DockerDesktop ### 运行 -在 Windows 搜索栏输入 **Docker**点击**Docker Desktop** 开始运行。 +在 Windows 搜索栏输入 **Docker** 点击 **Docker Desktop** 开始运行。 ![](../_images/install-win-docker-app-search.png) diff --git a/03_install/3.9_mirror.md b/03_install/3.9_mirror.md index 5d500ea..16884d3 100644 --- a/03_install/3.9_mirror.md +++ b/03_install/3.9_mirror.md @@ -8,13 +8,13 @@ 针对不同的使用场景,我们推荐以下几种镜像加速配置方案,以确保最佳的拉取速度。 -1. **云服务器用户**:优先使用所在云平台提供的内部加速器(见本页末尾) +1. **云服务器用户**:优先使用所在云平台提供的内部加速器 (见本页末尾) 2. **本地开发用户**:使用阿里云个人加速器或其他可用的公共加速器 3. **代理方案**:如有条件,可配置 HTTP 代理直接访问 Docker Hub -* [阿里云加速器](https://cr.console.aliyun.com/cn-hangzhou/instances)(需登录获取个人加速地址) +* [阿里云加速器](https://cr.console.aliyun.com/cn-hangzhou/instances) (需登录获取个人加速地址) -本节以 [AtomHub 可信镜像中心](https://hub.atomgit.com/) 镜像服务 `https://hub.atomgit.com` 为例进行介绍。 +本节以 [AtomHub 可信镜像中心](https://hub.atomgit.com/)镜像服务 `https://hub.atomgit.com` 为例进行介绍。 > `hub.atomgit.com` 仅包含部分官方镜像,可以满足初学者的使用。 @@ -30,7 +30,7 @@ $ systemctl cat docker | grep '\-\-registry\-mirror' 如果该命令有输出,那么请执行 `$ systemctl cat docker` 查看 `ExecStart=` 出现的位置,修改对应的文件内容去掉 `--registry-mirror` 参数及其值,并按接下来的步骤进行配置。 -如果以上命令没有任何输出,那么就可以在 `/etc/docker/daemon.json` 中写入如下内容(如果文件不存在请新建该文件): +如果以上命令没有任何输出,那么就可以在 `/etc/docker/daemon.json` 中写入如下内容 (如果文件不存在请新建该文件): ```json { @@ -84,7 +84,7 @@ Registry Mirrors: ### Kubernetes 官方镜像地址迁移 -可以登录 [阿里云 容器镜像服务](https://www.aliyun.com/product/acr?source=5176.11533457&userCode=8lx5zmtu&type=copy) **镜像中心**->**镜像搜索** 查找。 +可以登录[阿里云容器镜像服务](https://www.aliyun.com/product/acr?source=5176.11533457&userCode=8lx5zmtu&type=copy)**镜像中心**->**镜像搜索**查找。 Kubernetes 社区已将官方镜像地址从 `k8s.gcr.io` 迁移到 `registry.k8s.io`。建议优先使用新地址。 @@ -108,10 +108,10 @@ $ docker pull registry.k8s.io/xxx * https://hub-mirror.c.163.com * https://mirror.baidubce.com -建议 **watch(页面右上角)** [镜像测试](https://github.com/docker-practice/docker-registry-cn-mirror-test) 这个 GitHub 仓库,我们会在此更新各个镜像地址的状态。 +建议 **watch (页面右上角)** [镜像测试](https://github.com/docker-practice/docker-registry-cn-mirror-test)这个 GitHub 仓库,我们会在此更新各个镜像地址的状态。 ### 云服务商 -某些云服务商提供了 **仅供内部** 访问的镜像服务,当您的 Docker 运行在云平台时可以选择它们。 +某些云服务商提供了**仅供内部**访问的镜像服务,当您的 Docker 运行在云平台时可以选择它们。 * [腾讯云 `https://mirror.ccs.tencentyun.com`](https://cloud.tencent.com/act/cps/redirect?redirect=10058&cps_key=3a5255852d5db99dcd5da4c72f05df61) diff --git a/03_install/README.md b/03_install/README.md index 4e895f2..5213d76 100644 --- a/03_install/README.md +++ b/03_install/README.md @@ -1,8 +1,12 @@ -# 第三章 安装 Docker +# 第三章安装 Docker Docker 分为 `stable` `test` 和 `nightly` 三个更新频道。 -官方网站上有各种环境下的 [安装指南](https://docs.docker.com/get-docker/),这里主要介绍 Docker 在 `Linux` 、`Windows 10` 和 `macOS` 上的安装。 +官方网站上有各种环境下的[安装指南](https://docs.docker.com/get-docker/),这里主要介绍 Docker 在 `Linux`、`Windows 10` 和 `macOS` 上的安装。 + +## 概述 + +总体概述了以下内容。 ## 详细安装指南 diff --git a/04_image/4.1_pull.md b/04_image/4.1_pull.md index 9968eb1..80c300e 100644 --- a/04_image/4.1_pull.md +++ b/04_image/4.1_pull.md @@ -116,6 +116,10 @@ flowchart TD | `--platform` | 指定平台架构 | `docker pull --platform linux/arm64 nginx` | | `--quiet, -q` | 静默模式 | `docker pull -q nginx` | +#### 概述 + +总体概述了以下内容。 + #### 指定平台 在 Apple Silicon Mac 上拉取 x86 镜像: @@ -180,13 +184,13 @@ $ sudo systemctl restart docker # Linux ``` -详见 [镜像加速器](../03_install/3.9_mirror.md) 章节。 +详见[镜像加速器](../03_install/3.9_mirror.md)章节。 --- ### 验证镜像完整性 -为了确保下载的镜像没有被篡改且内容一致,我们可以校验镜像的摘要(Digest)。 +为了确保下载的镜像没有被篡改且内容一致,我们可以校验镜像的摘要 (Digest)。 #### 查看镜像摘要 @@ -214,13 +218,13 @@ $ docker pull ubuntu@sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9 在使用 `docker pull` 过程中,可能会遇到下载速度慢、镜像不存在或磁盘空间不足等问题。以下是一些常见问题的排查思路。 -#### Q: 下载速度很慢 +#### Q:下载速度很慢 1. 配置镜像加速器 2. 检查网络连接 -3. 尝试拉取更小的镜像版本(如 `alpine` 变体) +3. 尝试拉取更小的镜像版本 (如 `alpine` 变体) -#### Q: 提示镜像不存在 +#### Q:提示镜像不存在 运行以下命令: @@ -230,10 +234,10 @@ Error: pull access denied, repository does not exist 可能原因: - 镜像名拼写错误 -- 私有镜像未登录(需要 `docker login`) +- 私有镜像未登录 (需要 `docker login`) - 镜像确实不存在 -#### Q: 磁盘空间不足 +#### Q:磁盘空间不足 运行以下命令: diff --git a/04_image/4.2_list.md b/04_image/4.2_list.md index b36983d..5ec3c97 100644 --- a/04_image/4.2_list.md +++ b/04_image/4.2_list.md @@ -31,6 +31,10 @@ ubuntu noble 329ed837d508 3 days ago 78MB | **CREATED** | 创建时间 | | **SIZE** | 本地占用空间 | +#### 概述 + +总体概述了以下内容。 + #### 同一镜像多个标签 注意上面的 `ubuntu:24.04` 和 `ubuntu:noble` 拥有相同的 IMAGE ID——它们是同一个镜像的不同标签,只占用一份存储空间。 @@ -131,7 +135,7 @@ $ docker images -f label=maintainer=example@email.com --- -### 虚悬镜像(Dangling Images) +### 虚悬镜像 在镜像列表里,你可能会看到一些仓库名和标签都为 `` 的镜像,这类镜像被称为虚悬镜像。 @@ -170,7 +174,11 @@ $ docker image prune 除了虚悬镜像,`docker image ls` 默认列出的只是顶层镜像。还有一种镜像是为了加速镜像构建、重复利用资源而存在的中间层镜像。 -#### 查看所有镜像(包含中间层) +#### 概述 + +总体概述了以下内容。 + +#### 查看所有镜像 (包含中间层) 运行以下命令: diff --git a/04_image/4.3_rm.md b/04_image/4.3_rm.md index 06350aa..2477908 100644 --- a/04_image/4.3_rm.md +++ b/04_image/4.3_rm.md @@ -74,7 +74,7 @@ $ docker rmi nginx@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b1 执行删除命令后,Docker 会输出一系列的操作记录,理解这些信息有助于我们掌握镜像删除的机制。 -删除镜像时会看到两类信息:**Untagged**和**Deleted** +删除镜像时会看到两类信息:**Untagged** 和 **Deleted** ```bash $ docker rmi redis:alpine @@ -126,7 +126,7 @@ flowchart TD #### 删除所有虚悬镜像 -虚悬镜像(dangling):没有标签的镜像,通常是旧版本被新版本覆盖后产生的 +虚悬镜像 (dangling):没有标签的镜像,通常是旧版本被新版本覆盖后产生的 ```bash ## 查看虚悬镜像 @@ -221,7 +221,7 @@ Untagged: ubuntu:24.04 ``` -#### 原因三:被其他镜像依赖(中间层) +#### 原因三:被其他镜像依赖 (中间层) 运行以下命令: @@ -248,7 +248,7 @@ Error: image has dependent child images ### 清理策略 -针对不同的环境(开发环境 vs 生产环境),我们应该采用不同的镜像清理策略。 +针对不同的环境 (开发环境 vs 生产环境),我们应该采用不同的镜像清理策略。 #### 开发环境 diff --git a/04_image/4.4_commit.md b/04_image/4.4_commit.md index 6cb2e37..b9ca304 100644 --- a/04_image/4.4_commit.md +++ b/04_image/4.4_commit.md @@ -1,8 +1,8 @@ ## 4.4 利用 commit 理解镜像构成 -> 注意:如果您是初学者,您可以暂时跳过后面的内容,直接学习 [容器](../05_container/) 一节。 +> 注意:如果您是初学者,您可以暂时跳过后面的内容,直接学习[容器](../05_container/)一节。 -注意: `docker commit` 命令除了学习之外,还有一些特殊的应用场合,比如被入侵后保存现场等。但是,不要使用 `docker commit` 定制镜像,定制镜像应该使用 `Dockerfile` 来完成。如果你想要定制镜像请查看下一小节。 +注意:`docker commit` 命令除了学习之外,还有一些特殊的应用场合,比如被入侵后保存现场等。但是,不要使用 `docker commit` 定制镜像,定制镜像应该使用 `Dockerfile` 来完成。如果你想要定制镜像请查看下一小节。 镜像是容器的基础,每次执行 `docker run` 的时候都会指定哪个镜像作为容器运行的基础。在之前的例子中,我们所使用的都是来自于 Docker Hub 的镜像。直接使用这些镜像是可以满足一定的需求,而当这些镜像无法直接满足需求时,我们就需要定制这些镜像。接下来的几节就将讲解如何定制镜像。 @@ -16,7 +16,7 @@ $ docker run --name webserver -d -p 80:80 nginx 这条命令会用 `nginx` 镜像启动一个容器,命名为 `webserver`,并且映射了 80 端口,这样我们可以用浏览器去访问这个 `nginx` 服务器。 -如果是在本机运行的 Docker,那么可以直接访问:`http://localhost` ,如果是在虚拟机、云服务器上安装的 Docker,则需要将 `localhost` 换为虚拟机地址或者实际云服务器地址。 +如果是在本机运行的 Docker,那么可以直接访问:`http://localhost`,如果是在虚拟机、云服务器上安装的 Docker,则需要将 `localhost` 换为虚拟机地址或者实际云服务器地址。 直接用浏览器访问的话,我们会看到默认的 Nginx 欢迎页面。 @@ -63,7 +63,7 @@ A /var/cache/nginx/uwsgi_temp 现在我们定制好了变化,我们希望能将其保存下来形成镜像。 -要知道,当我们运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里。而 Docker 提供了一个 `docker commit` 命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。 +要知道,当我们运行一个容器的时候 (如果不使用卷的话),我们做的任何文件修改都会被记录于容器存储层里。而 Docker 提供了一个 `docker commit` 命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,再叠加上容器的存储层,并构成新的镜像。以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。 `docker commit` 的语法格式为: @@ -120,12 +120,16 @@ docker run --name web2 -d -p 81:80 nginx:v2 至此,我们第一次完成了定制镜像,使用的是 `docker commit` 命令,手动操作给旧的镜像添加了新的一层,形成新的镜像,对镜像多层存储应该有了更直观的感觉。 +### 概述 + +总体概述了以下内容。 + ### 慎用 `docker commit` 使用 `docker commit` 命令虽然可以比较直观的帮助理解镜像分层存储的概念,但是实际环境中并不会这样使用。 首先,如果仔细观察之前的 `docker diff webserver` 的结果,你会发现除了真正想要修改的 `/usr/share/nginx/html/index.html` 文件外,由于命令的执行,还有很多文件被改动或添加了。这还仅仅是最简单的操作,如果是安装软件包、编译构建,那会有大量的无关内容被添加进来,将会导致镜像极为臃肿。 -此外,使用 `docker commit` 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为 **黑箱镜像**,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。 +此外,使用 `docker commit` 意味着所有对镜像的操作都是黑箱操作,生成的镜像也被称为**黑箱镜像**,换句话说,就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。 而且,回顾之前提及的镜像所使用的分层存储的概念,除当前层外,之前的每一层都是不会发生改变的,换句话说,任何修改的结果仅仅是在当前层进行标记、添加、修改,而不会改动上一层。如果使用 `docker commit` 制作镜像,以及后期修改的话,每一次修改都会让镜像更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使根本无法访问到。这会让镜像更加臃肿。 diff --git a/04_image/4.5_build.md b/04_image/4.5_build.md index a30af19..9d50eab 100644 --- a/04_image/4.5_build.md +++ b/04_image/4.5_build.md @@ -2,17 +2,17 @@ 从刚才的 `docker commit` 的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。 -Dockerfile 是一个文本文件,其内包含了一条条的 **指令(Instruction)**,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。 +Dockerfile 是一个文本文件,其内包含了一条条的**指令 (Instruction)**,每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。 -### 使用 docker init 快速创建(推荐) +### 使用 docker init 快速创建 (推荐) -Docker 提供了 `docker init` 命令,可以根据项目类型自动生成 Dockerfile、.dockerignore 和 compose.yaml 文件: +Docker 提供了 `docker init` 命令,可以根据项目类型自动生成 Dockerfile、。dockerignore 和 compose.yaml 文件: ```bash $ docker init ``` -该命令会交互式地询问项目类型(如 Go、Node.js、Python、Rust 等),并生成符合最佳实践的配置文件。对于新项目,这是推荐的起步方式。 +该命令会交互式地询问项目类型 (如 Go、Node.js、Python、Rust 等),并生成符合最佳实践的配置文件。对于新项目,这是推荐的起步方式。 ### 手动创建 Dockerfile @@ -37,7 +37,7 @@ RUN echo '

Hello, Docker!

' > /usr/share/nginx/html/index.html ### FROM 指定基础镜像 -所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。就像我们之前运行了一个 `nginx` 镜像的容器,再进行修改一样,基础镜像是必须指定的。而 `FROM` 就是指定 **基础镜像**,因此一个 `Dockerfile` 中 `FROM` 是必备的指令,并且必须是第一条指令。 +所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制。就像我们之前运行了一个 `nginx` 镜像的容器,再进行修改一样,基础镜像是必须指定的。而 `FROM` 就是指定**基础镜像**,因此一个 `Dockerfile` 中 `FROM` 是必备的指令,并且必须是第一条指令。 在 [Docker Hub](https://hub.docker.com/search?q=&type=image&image_filter=official) 上有非常多的高质量的官方镜像,有可以直接拿来使用的服务类的镜像,如 [`nginx`](https://hub.docker.com/_/nginx/)、[`redis`](https://hub.docker.com/_/redis/)、[`mongo`](https://hub.docker.com/_/mongo/)、[`mysql`](https://hub.docker.com/_/mysql/)、[`httpd`](https://hub.docker.com/_/httpd/)、[`php`](https://hub.docker.com/_/php/)、[`tomcat`](https://hub.docker.com/_/tomcat/) 等;也有一些方便开发、构建、运行各种语言应用的镜像,如 [`node`](https://hub.docker.com/_/node)、[`openjdk`](https://hub.docker.com/_/openjdk/)、[`python`](https://hub.docker.com/_/python/)、[`ruby`](https://hub.docker.com/_/ruby/)、[`golang`](https://hub.docker.com/_/golang/) 等。可以在其中寻找一个最符合我们最终目标的镜像为基础镜像进行定制。 @@ -52,7 +52,7 @@ FROM scratch 如果你以 `scratch` 为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。 -不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 `FROM scratch` 会让镜像体积更加小巧。使用 [Go 语言](https://golang.google.cn/) 开发的应用很多会使用这种方式来制作镜像,这也是有人认为 Go 是特别适合容器微服务架构的语言的原因之一。 +不以任何系统为基础,直接将可执行文件复制进镜像的做法并不罕见,对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 `FROM scratch` 会让镜像体积更加小巧。使用 [Go 语言](https://golang.google.cn/)开发的应用很多会使用这种方式来制作镜像,这也是有人认为 Go 是特别适合容器微服务架构的语言的原因之一。 ### RUN 执行命令 @@ -72,9 +72,9 @@ Dockerfile 中每一个指令都会建立一层,`RUN` 也不例外。每一个 > > 每一个 `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` 等指令进行详细讲解。 +要想编写优秀的 `Dockerfile`,必须了解每一条指令的作用和副作用。在**[第七章 Dockerfile 指令详解](../07_dockerfile/README.md)**中,我们将对 `COPY`,`ADD`,`CMD`,`ENTRYPOINT` 等指令进行详细讲解。 ### 构建镜像 @@ -104,11 +104,11 @@ docker build [选项] <上下文路径/URL/-> 在这里我们指定了最终镜像的名称 `-t nginx:v3`,构建成功后,我们可以像之前运行 `nginx:v2` 那样来运行这个镜像,其结果会和 `nginx:v2` 一样。 -### 镜像构建上下文(Context) +### 镜像构建上下文 -如果注意,会看到 `docker build` 命令最后有一个 `.`。`.` 表示当前目录,而 `Dockerfile` 就在当前目录,因此不少初学者以为这个路径是在指定 `Dockerfile` 所在路径,这么理解其实是不准确的。如果对应上面的命令格式,你可能会发现,这是在指定 **上下文路径**。那么什么是上下文呢? +如果注意,会看到 `docker build` 命令最后有一个 `.`。`.` 表示当前目录,而 `Dockerfile` 就在当前目录,因此不少初学者以为这个路径是在指定 `Dockerfile` 所在路径,这么理解其实是不准确的。如果对应上面的命令格式,你可能会发现,这是在指定**上下文路径**。那么什么是上下文呢? -首先我们要理解 `docker build` 的工作原理。Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。Docker 的引擎提供了一组 REST API,被称为 [Docker Remote API](https://docs.docker.com/develop/sdk/),而如 `docker` 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 `docker` 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。 +首先我们要理解 `docker build` 的工作原理。Docker 在运行时分为 Docker 引擎 (也就是服务端守护进程) 和客户端工具。Docker 的引擎提供了一组 REST API,被称为 [Docker Remote API](https://docs.docker.com/develop/sdk/),而如 `docker` 命令这样的客户端工具,则是通过这组 API 与 Docker 引擎交互,从而完成各种功能。因此,虽然表面上我们好像是在本机执行各种 `docker` 功能,但实际上,一切都是使用的远程调用形式在服务端 (Docker 引擎) 完成。也因为这种 C/S 设计,让我们操作远程服务器的 Docker 引擎变得轻而易举。 当我们进行镜像构建的时候,并非所有定制都会通过 `RUN` 指令完成,经常会需要将一些本地文件复制进镜像,比如通过 `COPY` 指令、`ADD` 指令等。而 `docker build` 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。那么在这种客户端/服务端的架构中,如何才能让服务端获得本地文件呢? @@ -120,7 +120,7 @@ docker build [选项] <上下文路径/URL/-> COPY ./package.json /app/ ``` -这并不是要复制执行 `docker build` 命令所在的目录下的 `package.json`,也不是复制 `Dockerfile` 所在目录下的 `package.json`,而是复制 **上下文(context)** 目录下的 `package.json`。 +这并不是要复制执行 `docker build` 命令所在的目录下的 `package.json`,也不是复制 `Dockerfile` 所在目录下的 `package.json`,而是复制**上下文 (context)** 目录下的 `package.json`。 因此,`COPY` 这类指令中的源文件的路径都是*相对路径*。这也是初学者经常会问的为什么 `COPY ../package.json /app` 或者 `COPY /opt/xxxx /app` 无法工作的原因,因为这些路径已经超出了上下文的范围,Docker 引擎无法获得这些位置的文件。如果真的需要那些文件,应该将它们复制到上下文目录中去。 @@ -146,6 +146,8 @@ Sending build context to Docker daemon 2.048 kB ### 其它 `docker build` 的用法 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 直接用 Git repo 进行构建 或许你已经注意到了,`docker build` 还支持从 URL 构建,比如可以直接从 Git repo 中构建: diff --git a/04_image/4.6_other.md b/04_image/4.6_other.md index 360f1e0..ef0f90e 100644 --- a/04_image/4.6_other.md +++ b/04_image/4.6_other.md @@ -41,6 +41,10 @@ f477a6e18e98 About a minute ago 214.9 MB Docker 还提供了 `docker save` 和 `docker load` 命令,用以将镜像保存为一个文件,然后传输到另一个位置上,再加载进来。这是在没有 Docker Registry 时的做法,现在已经不推荐,镜像迁移应该直接使用 Docker Registry,无论是直接使用 Docker Hub 还是使用内网私有 Registry 都可以。 +#### 概述 + +总体概述了以下内容。 + #### 保存镜像 使用 `docker save` 命令可以将镜像保存为归档文件。 @@ -63,7 +67,7 @@ filename: POSIX tar archive 这里的 filename 可以为任意名称甚至任意后缀名,但文件的本质都是归档文件 -**注意:如果同名则会覆盖(没有警告)** +**注意:如果同名则会覆盖 (没有警告)** 若使用 `gzip` 压缩: diff --git a/04_image/4.7_internal.md b/04_image/4.7_internal.md index c8efa73..1ead9b6 100644 --- a/04_image/4.7_internal.md +++ b/04_image/4.7_internal.md @@ -8,22 +8,22 @@ Docker 镜像是怎么实现增量的修改和维护的?为什么容器启动 Docker 镜像并不是一个单纯的文件,而是由一组文件系统叠加构成的。 -最底层的镜像称为 **基础镜像(Base Image)**,通常是各种 Linux 发行版的 root 文件系统,如 Ubuntu、Debian、CentOS 等。 +最底层的镜像称为**基础镜像 (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`,所有镜像都可以共享它。 * **轻量**:镜像仅仅记录了与基础镜像的差异,因此体积非常小。 ### 容器层与读写 -我们要理解的一个关键概念是:**镜像的每一层都是只读的(Read-only)**。 +我们要理解的一个关键概念是:**镜像的每一层都是只读的 (Read-only)**。 那么,既然镜像只读,容器为什么能写文件呢? -当容器启动时,Docker 会在镜像的最上层,添加一个新的**可写层(Writable Layer)**,通常被称为**容器层**。 +当容器启动时,Docker 会在镜像的最上层,添加一个新的**可写层 (Writable Layer)**,通常被称为**容器层**。 ```mermaid flowchart TD @@ -39,27 +39,27 @@ flowchart TD Note["所有的写操作都在容器层这里"] -.-> L4 ``` -* **读取文件**:当容器需要读取文件时,Docker 会从最上层(容器层)开始向下层(镜像层)寻找,直到找到该文件为止。 -* **修改文件**:当容器需要修改某个文件时,Docker 会从下层镜像中将该文件复制到上层的容器层,然后对副本进行修改。这被称为**写时复制(Copy-on-Write, CoW)** 策略。 -* **删除文件**:当容器删除某个文件时,Docker 并不是真的去下层删除它(因为下层是只读的),而是在容器层创建一个特殊的“白障(Whiteout)”文件,用来标记该文件已被删除,从而在容器视图中隐藏它。 +* **读取文件**:当容器需要读取文件时,Docker 会从最上层 (容器层) 开始向下层 (镜像层) 寻找,直到找到该文件为止。 +* **修改文件**:当容器需要修改某个文件时,Docker 会从下层镜像中将该文件复制到上层的容器层,然后对副本进行修改。这被称为**写时复制 (Copy-on-Write,CoW)** 策略。 +* **删除文件**:当容器删除某个文件时,Docker 并不是真的去下层删除它 (因为下层是只读的),而是在容器层创建一个特殊的 “白障 (Whiteout)” 文件,用来标记该文件已被删除,从而在容器视图中隐藏它。 这就是为什么: -1. **容器删除后数据会丢失**:因为所有的数据修改都保存在最上层的容器层中,容器销毁时,这个层也就随之销毁了。(除非使用了数据卷,详见[数据管理](../08_data_network/README.md))。 +1. **容器删除后数据会丢失**:因为所有的数据修改都保存在最上层的容器层中,容器销毁时,这个层也就随之销毁了。(除非使用了数据卷,详见[数据管理](../08_data_network/README.md))。 2. **镜像不可变**:无论我们在容器里删除了多少文件,基础镜像的体积并不会减小,因为它们依然存在于底层的只读层中。 ### 内容寻址与镜像 ID -Docker 镜像的每一层都有一个唯一的 ID,这个 ID 是根据该层的内容计算出来的哈希值(SHA256)。这意味着: +Docker 镜像的每一层都有一个唯一的 ID,这个 ID 是根据该层的内容计算出来的哈希值 (SHA256)。这意味着: * **内容即 ID**:只要层的内容有一丁点变化,ID 就会变。 * **安全性**:确保了镜像内容的完整性,下载过程中如果数据损坏,ID 校验就会失败。 -* **去重**:如果两个不同的镜像(甚至是不同来源的镜像)包含相同的层(ID 相同),Docker 引擎在本地只会存储一份,绝不重复下载。 +* **去重**:如果两个不同的镜像 (甚至是不同来源的镜像) 包含相同的层 (ID 相同),Docker 引擎在本地只会存储一份,绝不重复下载。 ### 联合文件系统 -Docker 使用联合文件系统(Union FS)来实现这种分层挂载。常见的驱动包括 `overlay2`(目前推荐)、`aufs`(早期使用)、`btrfs`、`zfs` 等。 +Docker 使用联合文件系统 (Union FS) 来实现这种分层挂载。常见的驱动包括 `overlay2` (目前推荐)、`aufs` (早期使用)、`btrfs`、`zfs` 等。 -虽然实现细节不同,但它们都遵循上述的 **分层 + CoW** 模型。 +虽然实现细节不同,但它们都遵循上述的**分层 + CoW** 模型。 -> 想要深入了解 Overlay2 等文件系统的具体实现原理,包括 WorkDir、UpperDir、LowerDir 等底层细节,请阅读 **[第十四章 底层实现](../14_implementation/README.md)**中的**[联合文件系统](../14_implementation/14.4_ufs.md)** 章节。 +> 想要深入了解 Overlay2 等文件系统的具体实现原理,包括 WorkDir、UpperDir、LowerDir 等底层细节,请阅读**[第十四章底层实现](../14_implementation/README.md)**中的**[联合文件系统](../14_implementation/14.4_ufs.md)**章节。 diff --git a/04_image/README.md b/04_image/README.md index 171a145..b606384 100644 --- a/04_image/README.md +++ b/04_image/README.md @@ -1,9 +1,13 @@ -# 第四章 使用镜像 +# 第四章使用镜像 在之前的介绍中,我们知道镜像是 Docker 的三大组件之一。 Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。 +## 概述 + +总体概述了以下内容。 + ## 本章内容 本章将介绍更多关于镜像的内容,包括: diff --git a/05_container/5.1_run.md b/05_container/5.1_run.md index a97f556..9921ab5 100644 --- a/05_container/5.1_run.md +++ b/05_container/5.1_run.md @@ -12,6 +12,8 @@ ### 新建并启动 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 基本语法 运行以下命令: @@ -22,7 +24,7 @@ docker run [选项] 镜像 [命令] [参数...] #### 最简单的例子 -输出 "Hello World" 后容器自动终止: +输出 “Hello World” 后容器自动终止: ```bash $ docker run ubuntu:24.04 /bin/echo 'Hello world' @@ -81,6 +83,8 @@ flowchart TD ### 常用启动选项 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 基础选项 | 选项 | 说明 | 示例 | @@ -191,7 +195,9 @@ root@ba267838cc1b:/# ps ### 常见问题 -#### Q: 容器启动后立即退出 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:容器启动后立即退出 **原因**:主进程执行完毕或无法保持运行 @@ -207,7 +213,7 @@ $ docker run -d nginx # nginx 是持续运行的服务 详细解释见[后台运行](5.2_daemon.md)。 -#### Q: 无法连接容器内的服务 +#### Q:无法连接容器内的服务 **原因**:未正确映射端口 @@ -221,7 +227,7 @@ $ docker run -d nginx $ docker run -d -p 80:80 nginx ``` -#### Q: 容器内修改的文件丢失 +#### Q:容器内修改的文件丢失 **原因**:未使用数据卷,数据保存在容器存储层 diff --git a/05_container/5.2_daemon.md b/05_container/5.2_daemon.md index 4ad8206..b6402c3 100644 --- a/05_container/5.2_daemon.md +++ b/05_container/5.2_daemon.md @@ -9,11 +9,13 @@ - **前台运行**:程序占用当前终端,输出直接显示,关闭终端程序就停止 - **后台运行**:程序在后台执行,不占用终端,终端关闭也不影响程序 -Docker 容器默认是**前台运行**的。使用 `-d`(detach)参数可以让容器在后台运行。 +Docker 容器默认是**前台运行**的。使用 `-d` (detach) 参数可以让容器在后台运行。 ### 基本使用 -#### 前台运行(默认) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 前台运行 (默认) 运行以下命令: @@ -25,12 +27,12 @@ hello world hello world ``` -容器会把输出的结果(STDOUT)打印到宿主机上面。此时: +容器会把输出的结果 (STDOUT) 打印到宿主机上面。此时: - 终端被占用,无法执行其他命令 - 按 `Ctrl+C` 会终止容器 - 关闭终端窗口,容器也会停止 -#### 后台运行(使用 -d 参数) +#### 后台运行 (使用 -d 参数) 运行以下命令: @@ -43,11 +45,11 @@ $ docker run -d ubuntu:24.04 /bin/sh -c "while true; do echo hello world; sleep - 容器在后台运行 - 返回容器的完整 ID - 终端立即释放,可以继续执行其他命令 -- 输出不会直接显示(需要用 `docker logs` 查看) +- 输出不会直接显示 (需要用 `docker logs` 查看) -### 深入理解:容器为什么会"立即退出"? +### 深入理解:容器为什么会 “立即退出”? -> **这是初学者最常遇到的困惑。** 理解这个问题,你就理解了 Docker 的核心设计理念。 +> **这是初学者最常遇到的困惑。**理解这个问题,你就理解了 Docker 的核心设计理念。 很多人尝试这样启动容器: @@ -59,6 +61,8 @@ $ docker run -d ubuntu:24.04 #### 核心原理:容器的生命周期与主进程绑定 +如下代码块所示,展示了相关示例: + ```mermaid flowchart TD subgraph Lifecycle ["Docker 容器的生命周期 = 容器内 PID 1 进程的生命周期"] @@ -71,15 +75,15 @@ flowchart TD 当你运行 `docker run -d ubuntu:24.04` 时: 1. 容器启动 2. 没有指定命令,默认执行 `/bin/bash` -3. 但没有交互式终端(没有 `-it` 参数),bash 发现没有输入源 +3. 但没有交互式终端 (没有 `-it` 参数),bash 发现没有输入源 4. bash 立即退出 5. 主进程退出,容器停止 **关键理解**: -- ❌ `-d` 参数**不是**让容器"一直运行" -- ✅ `-d` 参数是让容器"在后台运行",能运行多久取决于主进程 +- ❌ `-d` 参数**不是**让容器 “一直运行” +- ✅ `-d` 参数是让容器 “在后台运行”,能运行多久取决于主进程 -#### 常见的"立即退出"场景 +#### 常见的 “立即退出” 场景 | 场景 | 原因 | 解决方案 | |------|------|---------| @@ -89,6 +93,8 @@ flowchart TD ### 查看后台容器 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 查看运行中的容器 运行以下命令: @@ -111,7 +117,7 @@ hello world ... ``` -**实时查看日志**(类似 `tail -f`): +**实时查看日志** (类似 `tail -f`): ```bash $ docker container logs -f 77b2dc01fe0f @@ -125,11 +131,13 @@ $ docker container logs -f 77b2dc01fe0f $ docker container ls -a ``` -加上 `-a` 参数可以看到所有容器,包括已停止的。这对于调试"容器启动即退出"的问题非常有用。 +加上 `-a` 参数可以看到所有容器,包括已停止的。这对于调试 “容器启动即退出” 的问题非常有用。 ### 最佳实践 -#### 1. 长期运行的服务使用 -d +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。长期运行的服务使用 -d 运行以下命令: @@ -147,7 +155,7 @@ $ docker run -d -p 3306:3306 mysql:8 $ docker run -d -p 6379:6379 redis ``` -#### 2. 调试时先用前台模式 +#### 2。调试时先用前台模式 当容器启动有问题时,**去掉 `-d` 参数**可以直接看到输出和错误: @@ -157,7 +165,7 @@ $ docker run -d -p 6379:6379 redis $ docker run myimage:latest ``` -#### 3. 使用 --rm 自动清理 +#### 3。使用 --rm 自动清理 对于一次性任务,使用 `--rm` 参数让容器退出后自动删除: @@ -169,7 +177,7 @@ Hello, World! ... ``` -#### 4. 配合日志查看 +#### 4。配合日志查看 运行以下命令: @@ -193,7 +201,9 @@ $ docker logs -t myapp ### 常见问题排查 -#### Q: 容器启动后立即退出 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:容器启动后立即退出 1. **查看退出状态码**: ```bash @@ -214,7 +224,7 @@ $ docker logs -t myapp ``` -#### Q: 容器在后台运行但无法访问服务 +#### Q:容器在后台运行但无法访问服务 1. **检查端口映射**: ```bash @@ -226,7 +236,7 @@ $ docker logs -t myapp $ docker exec mycontainer ps aux ``` -#### Q: 如何让已经在后台运行的容器回到前台? +#### Q:如何让已经在后台运行的容器回到前台? 使用 `docker attach`: diff --git a/05_container/5.3_stop.md b/05_container/5.3_stop.md index 78c2fa4..a221e8e 100644 --- a/05_container/5.3_stop.md +++ b/05_container/5.3_stop.md @@ -14,7 +14,9 @@ --- -### docker stop(推荐) +### docker stop (推荐) + +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: #### docker stop 基本用法 @@ -67,6 +69,8 @@ $ docker stop $(docker ps -q) ### docker kill +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 基本用法 运行以下命令: @@ -140,6 +144,8 @@ c5d3a5e8f7b2 nginx "nginx" Up 5 minutes mynginx ### 重新启动容器 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 启动已停止的容器 运行以下命令: @@ -192,6 +198,8 @@ stateDiagram-v2 ### 批量操作 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 停止所有容器 运行以下命令: @@ -220,7 +228,9 @@ $ docker stop $(docker ps -q) && docker container prune -f ### 常见问题 -#### Q: 容器停止很慢 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:容器停止很慢 原因:应用没有正确处理 SIGTERM 信号,需要等待超时后强制终止。 @@ -229,7 +239,7 @@ $ docker stop $(docker ps -q) && docker container prune -f 2. 使用 `docker stop -t 0` 立即终止 3. 检查 Dockerfile 中的 `STOPSIGNAL` 配置 -#### Q: 如何让容器优雅退出 +#### Q:如何让容器优雅退出 确保容器主进程正确处理信号: @@ -243,7 +253,7 @@ FROM node:22 CMD ["node", "server.js"] ``` -#### Q: 容器无法停止 +#### Q:容器无法停止 运行以下命令: diff --git a/05_container/5.4_attach_exec.md b/05_container/5.4_attach_exec.md index 664bb35..1683913 100644 --- a/05_container/5.4_attach_exec.md +++ b/05_container/5.4_attach_exec.md @@ -1,5 +1,7 @@ ## 5.4 进入容器 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 为什么需要进入容器 使用 `-d` 参数启动容器后,容器在后台运行。以下场景需要进入容器内部操作: @@ -22,7 +24,9 @@ Docker 提供两种进入容器的命令: --- -### docker exec(推荐) +### docker exec (推荐) + +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: #### docker exec 基本用法 @@ -115,7 +119,9 @@ root@69d137adef7a:/# # 有提示符 --- -### docker attach(谨慎使用) +### docker attach (谨慎使用) + +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: #### docker attach 基本用法 @@ -127,7 +133,7 @@ $ docker attach 容器名 #### 工作原理 -`attach` 会附加到容器的**主进程**(PID 1)的标准输入输出: +`attach` 会附加到容器的**主进程** (PID 1) 的标准输入输出: ```mermaid flowchart LR @@ -228,7 +234,9 @@ flowchart LR ### 最佳实践 -#### 1. 首选 docker exec +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。首选 docker exec 运行以下命令: @@ -246,16 +254,16 @@ $ docker exec myapp tail -f /var/log/app.log $ docker exec myapp python manage.py migrate ``` -#### 2. 生产环境避免进入容器 +#### 2。生产环境避免进入容器 笔者建议:生产环境应尽量避免进入容器直接操作,而是通过: -- 日志系统查看日志(如 `docker logs` 或集中式日志) +- 日志系统查看日志 (如 `docker logs` 或集中式日志) - 监控系统查看状态 - 重新部署而非手动修改 -#### 3. 无 shell 镜像的处理 +#### 3。无 shell 镜像的处理 -某些精简镜像(如基于 `scratch` 或 `distroless`)没有 shell: +某些精简镜像 (如基于 `scratch` 或 `distroless`) 没有 shell: ```bash ## 这会失败 @@ -272,11 +280,13 @@ $ docker debug myapp ### 常见问题 -#### Q: exec 进入后看不到其他终端的操作 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:exec 进入后看不到其他终端的操作 这是正常的。exec 启动的是独立进程,多个 exec 会话互不影响。 -#### Q: 容器没有 bash +#### Q:容器没有 bash 尝试使用 sh: @@ -284,7 +294,7 @@ $ docker debug myapp $ docker exec -it myapp /bin/sh ``` -#### Q: 需要 root 权限 +#### Q:需要 root 权限 运行以下命令: diff --git a/05_container/5.5_import_export.md b/05_container/5.5_import_export.md index 1f30bc5..89dd6d8 100644 --- a/05_container/5.5_import_export.md +++ b/05_container/5.5_import_export.md @@ -31,4 +31,4 @@ test/ubuntu v1.0 9d37a6082e97 About a minute ago $ 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 c497458..f56965f 100644 --- a/05_container/5.6_rm.md +++ b/05_container/5.6_rm.md @@ -65,6 +65,8 @@ $ docker rm -v mycontainer ### 批量删除 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 删除所有已停止的容器 运行以下命令: @@ -86,7 +88,7 @@ Total reclaimed space: 150MB $ docker container prune -f ``` -#### 删除所有容器(包括运行中的) +#### 删除所有容器 (包括运行中的) 运行以下命令: @@ -134,6 +136,10 @@ $ docker container prune --filter "until=24h" | `before=xxx` | 在某容器之前创建 | `-f before=mycontainer` | | `since=xxx` | 在某容器之后创建 | `-f since=mycontainer` | +#### 概述 + +总体概述了以下内容。 + #### 示例 运行以下命令: @@ -170,6 +176,8 @@ $ docker image rm nginx ### 清理策略建议 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 开发环境 运行以下命令: @@ -227,7 +235,9 @@ docker system df ### 常见问题 -#### Q: 容器无法删除 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:容器无法删除 运行以下命令: @@ -245,10 +255,10 @@ $ docker rm mycontainer $ docker rm -f mycontainer ``` -#### Q: 删除后磁盘空间没释放 +#### Q:删除后磁盘空间没释放 可能原因: -1. 容器的数据卷未删除(使用 `-v` 参数) +1. 容器的数据卷未删除 (使用 `-v` 参数) 2. 镜像未删除 3. 构建缓存未清理 diff --git a/05_container/README.md b/05_container/README.md index 7624cd3..cade17f 100644 --- a/05_container/README.md +++ b/05_container/README.md @@ -1,8 +1,8 @@ -# 第五章 操作容器 +# 第五章操作容器 容器是 Docker 又一核心概念。 -简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统(提供了运行态环境和其他系统环境)和跑在上面的应用。 +简单的说,容器是独立运行的一个或一组应用,以及它们的运行态环境。对应的,虚拟机可以理解为模拟运行的一整套操作系统 (提供了运行态环境和其他系统环境) 和跑在上面的应用。 本章将具体介绍如何来管理一个容器,包括创建、启动和停止等。 diff --git a/06_repository/6.1_dockerhub.md b/06_repository/6.1_dockerhub.md index ede5664..b0f9714 100644 --- a/06_repository/6.1_dockerhub.md +++ b/06_repository/6.1_dockerhub.md @@ -1,5 +1,7 @@ ## 6.1 Docker Hub +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 什么是 Docker Hub Docker Hub 是 Docker 的中央镜像仓库,通过它您可以轻松地分享和获取 Docker 镜像。 @@ -8,16 +10,18 @@ Docker Hub 是 Docker 的中央镜像仓库,通过它您可以轻松地分享 [Docker Hub](https://hub.docker.com/) 是 Docker 官方维护的公共镜像仓库,也是全球最大的容器镜像库。 它提供了: -- **官方镜像**:由 Docker 官方和软件厂商(如 Nginx, MySQL, Node.js)维护的高质量镜像。 +- **官方镜像**:由 Docker 官方和软件厂商 (如 Nginx,MySQL,Node.js) 维护的高质量镜像。 - **个人/组织仓库**:用户可以上传自己的镜像。 -- **自动构建**:与 GitHub/Bitbucket 集成(需付费)。 +- **自动构建**:与 GitHub/Bitbucket 集成 (需付费)。 - **Webhooks**:镜像更新时触发回调。 --- ### 核心功能 -#### 1. 搜索镜像 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。搜索镜像 我们可以通过 `docker search` 命令来查找官方仓库中的镜像,并利用 `docker pull` 命令来将它下载到本地。 @@ -32,7 +36,7 @@ centos The official build of CentOS. 7000+ [OK] > **技巧**:始终优先使用 `OFFICIAL` 标记为 `[OK]` 的镜像,安全性更有保障。 -#### 2. 拉取镜像 +#### 2。拉取镜像 运行以下命令: @@ -40,7 +44,7 @@ centos The official build of CentOS. 7000+ [OK] $ docker pull nginx:alpine ``` -#### 3. 推送镜像 +#### 3。推送镜像 需要先登录: @@ -67,6 +71,12 @@ $ docker push username/myapp:v1 ### 限制与配额 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 概述 + +总体概述了以下内容。 + #### 镜像拉取限制 自 2020 年 11 月起,Docker Hub 对匿名和免费用户实施了拉取速率限制: @@ -86,14 +96,16 @@ $ docker push username/myapp:v1 ### 安全最佳实践 -#### 1. 启用 2FA(双因素认证) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。启用 2FA (双因素认证) 为了保护您的 Docker Hub 账号安全,我们建议采取以下措施。 在 Account Settings -> Security 中启用 2FA,保护账号安全。启用后,CLI 登录需要使用 **Access Token** 而非密码。 -#### 2. 使用 Access Token +#### 2。使用 Access Token 不要在脚本或 CI/CD 中直接使用登录密码。 1. 在 Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token。 @@ -103,7 +115,7 @@ $ docker push username/myapp:v1 $ docker login -u username -p dckr_pat_xxxxxxx ``` -#### 3. 关注镜像漏洞 +#### 3。关注镜像漏洞 Docker Hub 会对官方镜像和付费用户的镜像进行安全扫描。在镜像标签页可以看到漏洞扫描结果。 @@ -111,7 +123,7 @@ Docker Hub 会对官方镜像和付费用户的镜像进行安全扫描。在镜 ### 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 f0e1468..65d691c 100644 --- a/06_repository/6.2_registry.md +++ b/06_repository/6.2_registry.md @@ -8,6 +8,12 @@ ### 安装运行 docker-registry +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 概述 + +总体概述了以下内容。 + #### 容器运行 如果您需要搭建私有仓库,可以通过官方提供的 `registry` 镜像快速部署。 @@ -99,12 +105,16 @@ REPOSITORY TAG IMAGE ID CREAT 这是因为 Docker 默认不允许非 `HTTPS` 方式推送镜像。我们可以通过 Docker 的配置选项来取消这个限制,或者查看下一节配置能够通过 `HTTPS` 访问的私有仓库。 -#### Linux(systemd) +#### 概述 + +总体概述了以下内容。 + +#### Linux 默认情况下,Docker 强制使用 HTTPS 协议推送镜像。如果您搭建的私有仓库是 HTTP 协议,需要进行如下配置。 -对于使用 `systemd` 的系统,请在 `/etc/docker/daemon.json` 中写入如下内容(如果文件不存在请新建该文件) +对于使用 `systemd` 的系统,请在 `/etc/docker/daemon.json` 中写入如下内容 (如果文件不存在请新建该文件) ```json { @@ -122,4 +132,4 @@ REPOSITORY TAG IMAGE ID CREAT ### 其他 -对于 Docker Desktop for Windows 、 Docker Desktop for Mac 在设置中的 `Docker Engine` 中进行编辑 ,增加和上边一样的字符串即可。 +对于 Docker Desktop for Windows、Docker Desktop for Mac 在设置中的 `Docker Engine` 中进行编辑,增加和上边一样的字符串即可。 diff --git a/06_repository/6.3_registry_auth.md b/06_repository/6.3_registry_auth.md index c52a8cd..c572175 100644 --- a/06_repository/6.3_registry_auth.md +++ b/06_repository/6.3_registry_auth.md @@ -140,7 +140,7 @@ $ docker run --rm \ ### 编辑 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 385a42c..31762db 100644 --- a/06_repository/6.4_nexus3_registry.md +++ b/06_repository/6.4_nexus3_registry.md @@ -1,6 +1,6 @@ ## 6.4 Nexus 3 -使用 Docker 官方的 Registry 创建的仓库面临一些维护问题。比如某些镜像删除以后空间默认是不会回收的,需要一些命令去回收空间然后重启 Registry。在企业中把内部的一些工具包放入 `Nexus` 中是比较常见的做法,最新版本 `Nexus3.x` 全面支持 Docker 的私有镜像。所以使用 [`Nexus3.x`](https://www.sonatype.com/product/repository-oss-download) 一个软件来管理 `Docker` , `Maven` , `Yum` , `PyPI` 等是一个明智的选择。 +使用 Docker 官方的 Registry 创建的仓库面临一些维护问题。比如某些镜像删除以后空间默认是不会回收的,需要一些命令去回收空间然后重启 Registry。在企业中把内部的一些工具包放入 `Nexus` 中是比较常见的做法,最新版本 `Nexus3.x` 全面支持 Docker 的私有镜像。所以使用 [`Nexus3.x`](https://www.sonatype.com/product/repository-oss-download) 一个软件来管理 `Docker`,`Maven`,`Yum`,`PyPI` 等是一个明智的选择。 ### 启动 Nexus 容器 @@ -36,17 +36,17 @@ $ docker exec nexus3 cat /nexus-data/admin.password 9266139e-41a2-4abb-92ec-e4142a3532cb ``` -首次启动 Nexus 的默认帐号是 `admin` ,密码则是上边命令获取到的,点击右上角登录,首次登录需更改初始密码。 +首次启动 Nexus 的默认帐号是 `admin`,密码则是上边命令获取到的,点击右上角登录,首次登录需更改初始密码。 登录之后可以点击页面上方的齿轮按钮按照下面的方法进行设置。 ### 创建仓库 -创建一个私有仓库的方法: `Repository->Repositories` 点击右边菜单 `Create repository` 选择 `docker (hosted)` +创建一个私有仓库的方法:`Repository->Repositories` 点击右边菜单 `Create repository` 选择 `docker (hosted)` -* **Name**: 仓库的名称 -* **HTTP**: 仓库单独的访问端口(例如:**5001**) -* **Hosted -> Deployment policy**: 请选择**Allow redeploy** 否则无法上传 Docker 镜像。 +* **Name**:仓库的名称 +* **HTTP**:仓库单独的访问端口 (例如:**5001**) +* **Hosted -> Deployment policy**:请选择 **Allow redeploy** 否则无法上传 Docker 镜像。 其它的仓库创建方法请各位自己摸索,还可以创建一个 `docker (proxy)` 类型的仓库链接到 DockerHub 上。再创建一个 `docker (group)` 类型的仓库把刚才的 `hosted` 与 `proxy` 添加在一起。主机在访问的时候默认下载私有仓库中的镜像,如果没有将链接到 DockerHub 中下载并缓存到 Nexus 中。 @@ -115,7 +115,7 @@ server { ### Docker 主机访问镜像仓库 -如果不启用 SSL 加密可以通过 [前面章节](6.2_registry.md) 的方法添加非 https 仓库地址到 Docker 的配置文件中然后重启 Docker。 +如果不启用 SSL 加密可以通过[前面章节](6.2_registry.md)的方法添加非 https 仓库地址到 Docker 的配置文件中然后重启 Docker。 使用 SSL 加密以后程序需要访问就不能采用修改配置的方式了。具体方法如下: diff --git a/06_repository/README.md b/06_repository/README.md index 7f86d38..e07a8bb 100644 --- a/06_repository/README.md +++ b/06_repository/README.md @@ -1,7 +1,7 @@ -# 第六章 访问仓库 +# 第六章访问仓库 -仓库(`Repository`)是集中存放镜像的地方。 +仓库 (`Repository`) 是集中存放镜像的地方。 -一个容易混淆的概念是注册服务器(`Registry`)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址 `docker.io/ubuntu` 来说,`docker.io` 是注册服务器地址,`ubuntu` 是仓库名。 +一个容易混淆的概念是注册服务器 (`Registry`)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以被认为是一个具体的项目或目录。例如对于仓库地址 `docker.io/ubuntu` 来说,`docker.io` 是注册服务器地址,`ubuntu` 是仓库名。 大部分时候,并不需要严格区分这两者的概念。 diff --git a/06_repository/summary.md b/06_repository/summary.md index b0051ff..fa1abf7 100644 --- a/06_repository/summary.md +++ b/06_repository/summary.md @@ -7,6 +7,10 @@ | **安全** | 推荐开启 2FA 并使用 Access Token | | **自动化** | 支持 Webhooks 和自动构建 | +### 概述 + +总体概述了以下内容。 + ### 延伸阅读 - [私有仓库](6.2_registry.md):搭建自己的 Registry diff --git a/07_dockerfile/7.10_workdir.md b/07_dockerfile/7.10_workdir.md index 1df5b2f..9bcf9fc 100644 --- a/07_dockerfile/7.10_workdir.md +++ b/07_dockerfile/7.10_workdir.md @@ -1,7 +1,11 @@ ## 7.10 WORKDIR 指定工作目录 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker WORKDIR <工作目录路径> ``` @@ -12,6 +16,8 @@ WORKDIR <工作目录路径> ### 基本用法 +如下代码块所示,展示了相关示例: + ```docker WORKDIR /app @@ -24,8 +30,12 @@ COPY . . # 复制到 /app/ ### 为什么需要 WORKDIR +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 常见错误 +如下代码块所示,展示了相关示例: + ```docker ## ❌ 错误:cd 在下一个 RUN 中无效 @@ -35,6 +45,8 @@ RUN echo "hello" > world.txt # 文件在根目录! #### 原因分析 +如下代码块所示,展示了相关示例: + ``` RUN cd /app ↓ @@ -46,10 +58,12 @@ RUN echo "hello" > world.txt 启动新容器(工作目录在 /)→ 创建 /world.txt ``` -每个 RUN 都在新容器中执行,**前一个 RUN 的内存状态(包括工作目录)不会保留**。 +每个 RUN 都在新容器中执行,**前一个 RUN 的内存状态 (包括工作目录) 不会保留**。 #### 正确做法 +如下代码块所示,展示了相关示例: + ```docker ## ✅ 正确:使用 WORKDIR @@ -75,6 +89,8 @@ RUN pwd # 输出 /a/b/c ### 使用环境变量 +如下代码块所示,展示了相关示例: + ```docker ENV APP_HOME=/app WORKDIR $APP_HOME @@ -86,6 +102,8 @@ RUN pwd # 输出 /app ### 多阶段构建中的 WORKDIR +如下代码块所示,展示了相关示例: + ```docker ## 构建阶段 @@ -107,7 +125,11 @@ COPY --from=builder /build/dist . ### 最佳实践 -#### 1. 尽早设置 WORKDIR +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。尽早设置 WORKDIR + +如下代码块所示,展示了相关示例: ```docker FROM node:20 @@ -119,7 +141,9 @@ COPY . . CMD ["node", "server.js"] ``` -#### 2. 使用绝对路径 +#### 2。使用绝对路径 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 推荐:绝对路径,意图明确 @@ -131,7 +155,9 @@ WORKDIR /app WORKDIR app ``` -#### 3. 不要用 RUN cd +#### 3。不要用 RUN cd + +如下代码块所示,展示了相关示例: ```docker ## ❌ 避免 @@ -144,7 +170,9 @@ WORKDIR /app RUN echo "hello" > world.txt ``` -#### 4. 适时重置 WORKDIR +#### 4。适时重置 WORKDIR + +如下代码块所示,展示了相关示例: ```docker WORKDIR /app diff --git a/07_dockerfile/7.11_user.md b/07_dockerfile/7.11_user.md index b60ac2c..98e92c2 100644 --- a/07_dockerfile/7.11_user.md +++ b/07_dockerfile/7.11_user.md @@ -1,13 +1,17 @@ ## 7.11 USER 指定当前用户 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker USER <用户名>[:<用户组>] USER [:] ``` -`USER` 指令切换后续指令(RUN、CMD、ENTRYPOINT)的执行用户。 +`USER` 指令切换后续指令 (RUN、CMD、ENTRYPOINT) 的执行用户。 --- @@ -34,8 +38,12 @@ flowchart LR ### 基本用法 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 创建并切换用户 +如下代码块所示,展示了相关示例: + ```docker FROM node:20-alpine @@ -60,6 +68,8 @@ CMD ["node", "server.js"] #### 使用 UID/GID +如下代码块所示,展示了相关示例: + ```docker ## 也可以使用数字 @@ -84,6 +94,10 @@ RUN useradd -r -s /bin/false appuser USER appuser ``` +#### 概述 + +总体概述了以下内容。 + #### 创建用户的方式 **Debian/Ubuntu**: @@ -112,7 +126,9 @@ RUN addgroup -g 1001 -S appgroup && \ ### 运行时切换用户 -#### 使用 gosu(推荐) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 使用 gosu (推荐) 在 ENTRYPOINT 脚本中切换用户时,不要使用 `su` 或 `sudo`,应使用 [gosu](https://github.com/tianon/gosu): @@ -205,7 +221,11 @@ CMD ["node", "server.js"] ### 最佳实践 -#### 1. 始终使用非 root 用户 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。始终使用非 root 用户 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 推荐 @@ -219,7 +239,7 @@ CMD ["myapp"] CMD ["myapp"] # 以 root 运行 ``` -#### 2. 使用固定 UID/GID +#### 2。使用固定 UID/GID 便于在宿主机和容器间共享文件: @@ -231,7 +251,9 @@ RUN addgroup -g 1000 -S appgroup && \ USER 1000:1000 ``` -#### 3. 多阶段构建中的 USER +#### 3。多阶段构建中的 USER + +如下代码块所示,展示了相关示例: ```docker ## 构建阶段可以用 root @@ -255,7 +277,9 @@ CMD ["node", "server.js"] ### 常见问题 -#### Q: 权限被拒绝 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:权限被拒绝 运行以下命令: @@ -269,12 +293,12 @@ permission denied: '/app/data.log' RUN mkdir -p /app/data && chown appuser:appuser /app/data ``` -#### Q: 无法绑定低于 1024 的端口 +#### Q:无法绑定低于 1024 的端口 非 root 用户无法绑定 80、443 等端口。 **解决**: -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 47cec54..66d8c69 100644 --- a/07_dockerfile/7.12_healthcheck.md +++ b/07_dockerfile/7.12_healthcheck.md @@ -1,7 +1,11 @@ ## 7.12 HEALTHCHECK 健康检查 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker HEALTHCHECK [选项] CMD <命令> HEALTHCHECK NONE @@ -19,7 +23,7 @@ HEALTHCHECK NONE - 应用陷入死循环,CPU 爆满但进程存活 **引入 HEALTHCHECK 后**: -Docker 定期执行指定的检查命令,根据返回值判断容器是否"健康"。 +Docker 定期执行指定的检查命令,根据返回值判断容器是否 “健康”。 ``` 容器状态转换: @@ -32,8 +36,12 @@ Starting ──成功──> Healthy ──失败N次──> Unhealthy ### 基本用法 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### Web 服务检查 +如下代码块所示,展示了相关示例: + ```docker FROM nginx RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* @@ -44,9 +52,9 @@ HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ #### 命令返回值 -- `0`: 成功 (healthy) -- `1`: 失败 (unhealthy) -- `2`: 保留值 (不使用) +- `0`:成功 (healthy) +- `1`:失败 (unhealthy) +- `2`:保留值 (不使用) #### 常用选项 @@ -72,6 +80,8 @@ HEALTHCHECK NONE ### 常见检查脚本 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### HTTP 服务 使用 `curl` 或 `wget`: @@ -88,6 +98,8 @@ HEALTHCHECK CMD wget -q --spider http://localhost/ || exit 1 #### 数据库 +如下代码块所示,展示了相关示例: + ```docker ## MySQL @@ -100,6 +112,8 @@ HEALTHCHECK CMD redis-cli ping || exit 1 #### 自定义脚本 +如下代码块所示,展示了相关示例: + ```docker COPY healthcheck.sh /usr/local/bin/ HEALTHCHECK CMD ["healthcheck.sh"] @@ -109,7 +123,7 @@ HEALTHCHECK CMD ["healthcheck.sh"] ### 在 Compose 中使用 -可以在 `compose.yaml`(或 `docker-compose.yml`)中覆盖或定义健康检查: +可以在 `compose.yaml` (或 `docker-compose.yml`) 中覆盖或定义健康检查: ```yaml services: @@ -172,17 +186,19 @@ $ docker inspect --format '{{json .State.Health}}' mycontainer | jq ### 最佳实践 -#### 1. 避免副作用 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。避免副作用 健康检查会被频繁执行,不要在检查脚本中进行写操作或消耗大量资源的操作。 -#### 2. 使用轻量级工具 +#### 2。使用轻量级工具 -优先使用镜像中已有的工具(如 `wget`),避免为了健康检查安装庞大的依赖(如 `curl`)。 +优先使用镜像中已有的工具 (如 `wget`),避免为了健康检查安装庞大的依赖 (如 `curl`)。 -#### 3. 设置合理的 Start Period +#### 3。设置合理的 Start Period -应用启动可能需要时间(如 Java 应用)。设置 `--start-period` 可以防止在启动阶段因检查失败而误判。 +应用启动可能需要时间 (如 Java 应用)。设置 `--start-period` 可以防止在启动阶段因检查失败而误判。 ```docker ## 给应用 1 分钟启动时间 @@ -190,8 +206,8 @@ $ docker inspect --format '{{json .State.Health}}' mycontainer | jq HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1 ``` -#### 4. 只检查核心依赖 +#### 4。只检查核心依赖 -健康检查应主要关注**当前服务**是否可用,而不是检查其下游依赖(数据库等)。下游依赖的检查应由应用逻辑处理。 +健康检查应主要关注**当前服务**是否可用,而不是检查其下游依赖 (数据库等)。下游依赖的检查应由应用逻辑处理。 --- diff --git a/07_dockerfile/7.13_onbuild.md b/07_dockerfile/7.13_onbuild.md index 9a03d4d..0eb49ec 100644 --- a/07_dockerfile/7.13_onbuild.md +++ b/07_dockerfile/7.13_onbuild.md @@ -1,12 +1,16 @@ ## 7.13 ONBUILD 为他人做嫁衣裳 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker ONBUILD <其它指令> ``` -`ONBUILD` 是一个特殊的指令,它后面跟的是其它指令(如 `RUN`, `COPY` 等),这些指令**在当前镜像构建时不会执行**,只有当以当前镜像为基础镜像去构建下一级镜像时才会被执行。 +`ONBUILD` 是一个特殊的指令,它后面跟的是其它指令 (如 `RUN`,`COPY` 等),这些指令**在当前镜像构建时不会执行**,只有当以当前镜像为基础镜像去构建下一级镜像时才会被执行。 --- @@ -57,6 +61,8 @@ FROM my-node-base ### 执行机制 +如下代码块所示,展示了相关示例: + ``` 基础镜像构建: Dockerfile (含 ONBUILD) ──build──> 基础镜像 (记录了 ONBUILD 触发器) @@ -70,7 +76,11 @@ FROM 基础镜像 ──build──> 读取基础镜像触发器 ──> 执行 ### 常见使用场景 -#### 1. 自动处理依赖安装 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。自动处理依赖安装 + +如下代码块所示,展示了相关示例: ```docker ## Python 基础镜像 @@ -79,7 +89,9 @@ ONBUILD COPY requirements.txt ./ ONBUILD RUN pip install -r requirements.txt ``` -#### 2. 自动编译代码 +#### 2。自动编译代码 + +如下代码块所示,展示了相关示例: ```docker ## Go 基础镜像 @@ -88,7 +100,9 @@ ONBUILD COPY . . ONBUILD RUN go build -o app main.go ``` -#### 3. 处理静态资源 +#### 3。处理静态资源 + +如下代码块所示,展示了相关示例: ```docker ## Nginx 静态网站基础镜像 @@ -100,30 +114,34 @@ ONBUILD COPY dist/ /usr/share/nginx/html/ ### 注意事项 -#### 1. 继承性限制 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。继承性限制 `ONBUILD` 指令**只会继承一次**。 - 镜像 A (含 ONBUILD) - 镜像 B (FROM A) -> 触发 ONBUILD - 镜像 C (FROM B) -> **不会**再次触发 ONBUILD -#### 2. 构建上下文 +#### 2。构建上下文 子镜像构建时,`ONBUILD COPY . .` 中的 `.` 指的是**子项目**的构建上下文,而不是基础镜像的上下文。 -#### 3. 不允许级联 +#### 3。不允许级联 `ONBUILD ONBUILD` 是非法的。你不能写 `ONBUILD ONBUILD COPY ...`。 -#### 4. 可能会导致构建失败 +#### 4。可能会导致构建失败 -由于 `ONBUILD` 实际上是在子镜像中执行指令,如果子项目的上下文不满足要求(例如缺少 `package.json`),会导致子镜像构建失败,且错误信息可能比较隐晦。 +由于 `ONBUILD` 实际上是在子镜像中执行指令,如果子项目的上下文不满足要求 (例如缺少 `package.json`),会导致子镜像构建失败,且错误信息可能比较隐晦。 --- ### 最佳实践 -#### 1. 命名规范 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。命名规范 建议在镜像标签中添加 `-onbuild` 后缀,明确告知使用者该镜像包含触发器。 @@ -132,11 +150,11 @@ node:20-onbuild python:3.12-onbuild ``` -#### 2. 避免执行耗时操作 +#### 2。避免执行耗时操作 -尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作(如更新系统软件),这会让子镜像构建变得缓慢且不可控。 +尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作 (如更新系统软件),这会让子镜像构建变得缓慢且不可控。 -#### 3. 清理工作 +#### 3。清理工作 如果 `ONBUILD` 指令产生了临时文件,最好在同一个指令链中清理,或者提供机制让子镜像清理。 diff --git a/07_dockerfile/7.14_label.md b/07_dockerfile/7.14_label.md index 9df92a3..b02e04b 100644 --- a/07_dockerfile/7.14_label.md +++ b/07_dockerfile/7.14_label.md @@ -1,7 +1,11 @@ ## 7.14 LABEL 为镜像添加元数据 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker LABEL = = ... ``` @@ -14,21 +18,27 @@ LABEL = = ... 1. **版本管理**:记录版本号、构建时间、Git Commit ID 2. **联系信息**:维护者邮箱、文档地址、支持渠道 -3. **自动化工具**: CI/CD 工具可以读取标签触发操作 +3. **自动化工具**:CI/CD 工具可以读取标签触发操作 4. **许可证信息**:声明开源协议 --- ### 基本用法 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 定义单个标签 +如下代码块所示,展示了相关示例: + ```docker LABEL version="1.0" LABEL description="这是一个 Web 应用服务器" ``` -#### 定义多个标签(推荐) +#### 定义多个标签 (推荐) + +如下代码块所示,展示了相关示例: ```docker LABEL maintainer="user@example.com" \ @@ -41,7 +51,7 @@ LABEL maintainer="user@example.com" \ --- -### 常用标签规范(OCI Annotations) +### 常用标签规范 为了标准和互操作性,推荐使用 [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys) 定义的标准标签: @@ -57,8 +67,14 @@ LABEL maintainer="user@example.com" \ | `org.opencontainers.image.title` | 镜像标题 | `My App` | | `org.opencontainers.image.description` | 描述 | `Production ready web server` | +#### 概述 + +总体概述了以下内容。 + #### 示例 +如下代码块所示,展示了相关示例: + ```docker LABEL org.opencontainers.image.authors="yeasy" \ org.opencontainers.image.documentation="https://yeasy.gitbooks.io" \ @@ -68,7 +84,7 @@ LABEL org.opencontainers.image.authors="yeasy" \ --- -### MAINTAINER 指令(已废弃) +### MAINTAINER 指令 (已废弃) 旧版本的 Dockerfile 中常看到 `MAINTAINER` 指令: @@ -116,6 +132,8 @@ $ docker build \ ### 查看标签 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### docker inspect 查看镜像的标签信息: diff --git a/07_dockerfile/7.15_shell.md b/07_dockerfile/7.15_shell.md index e2889b4..1cba226 100644 --- a/07_dockerfile/7.15_shell.md +++ b/07_dockerfile/7.15_shell.md @@ -1,7 +1,11 @@ ## 7.15 SHELL 指令 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker SHELL ["executable", "parameters"] ``` @@ -10,15 +14,17 @@ SHELL ["executable", "parameters"] - **Linux 默认**:`["/bin/sh", "-c"]` - **Windows 默认**:`["cmd", "/S", "/C"]` -该指令会影响后续的 `RUN`, `CMD`, `ENTRYPOINT` 指令(当它们使用 shell 格式时)。 +该指令会影响后续的 `RUN`,`CMD`,`ENTRYPOINT` 指令 (当它们使用 shell 格式时)。 --- ### 为什么要用 SHELL 指令 -#### 1. 使用 bash 特性 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: -默认的 `/bin/sh`(通常是 dash 或 alpine 的 ash)功能有限。如果你需要使用 bash 的特有功能(如数组、`{}` 扩展、`pipefail` 等),可以切换 shell。 +#### 1。使用 bash 特性 + +默认的 `/bin/sh` (通常是 dash 或 alpine 的 ash) 功能有限。如果你需要使用 bash 的特有功能 (如数组、`{}` 扩展、`pipefail` 等),可以切换 shell。 ```docker FROM ubuntu:24.04 @@ -32,7 +38,7 @@ SHELL ["/bin/bash", "-c"] RUN echo {a..z} ``` -#### 2. 增强错误处理(pipefail) +#### 2。增强错误处理 默认情况下,管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功,整个指令就视为成功。这可能掩盖构建错误。 @@ -54,7 +60,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN wget -O - https://invalid-url | tar xz ``` -#### 3. Windows 环境 +#### 3。Windows 环境 在 Windows 容器中,经常需要在 `cmd` 和 `powershell` 之间切换。 @@ -103,7 +109,7 @@ RUN echo "Using sh again" ### 对其他指令的影响 -`SHELL` 影响的是所有使用 **shell 格式** 的指令: +`SHELL` 影响的是所有使用 **shell 格式**的指令: | 指令格式 | 是否受 SHELL 影响 | |---------|-------------------| @@ -118,7 +124,9 @@ RUN echo "Using sh again" ### 最佳实践 -#### 1. 推荐开启 pipefail +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。推荐开启 pipefail 对于使用 bash 的镜像,强烈建议开启 `pipefail`,以确保构建过程中的错误能被及时捕获。 @@ -126,11 +134,11 @@ RUN echo "Using sh again" SHELL ["/bin/bash", "-o", "pipefail", "-c"] ``` -#### 2. 明确意图 +#### 2。明确意图 如果由于脚本需求必须更改 shell,最好在 Dockerfile 中显式声明,而不是依赖默认行为。 -#### 3. 尽量保持一致 +#### 3。尽量保持一致 避免在 Dockerfile 中频繁切换 SHELL,这会使构建过程难以理解和调试。尽量在头部定义一次即可。 diff --git a/07_dockerfile/7.18_multistage_builds_laravel.md b/07_dockerfile/7.18_multistage_builds_laravel.md index 62d5640..d59936b 100644 --- a/07_dockerfile/7.18_multistage_builds_laravel.md +++ b/07_dockerfile/7.18_multistage_builds_laravel.md @@ -125,6 +125,8 @@ RUN set -x ; cd ${LARAVEL_PATH} \ ### 最后一个阶段构建 NGINX 镜像 +如下代码块所示,展示了相关示例: + ```docker FROM nginx:alpine as nginx @@ -152,7 +154,7 @@ $ docker build -t my/nginx --target=nginx . $ docker network create laravel ``` -启动 laravel 容器, `--name=laravel` 参数设定的名字必须与 `nginx` 配置文件中的 `fastcgi_pass laravel:9000;` 一致 +启动 laravel 容器,`--name=laravel` 参数设定的名字必须与 `nginx` 配置文件中的 `fastcgi_pass laravel:9000;` 一致 ```bash $ docker run -dit --rm --name=laravel --network=laravel my/laravel @@ -170,7 +172,7 @@ $ docker run -dit --rm --network=laravel -p 8080:80 my/nginx ### 生产环境优化 -本小节内容为了方便测试,将配置文件直接放到了镜像中,实际在使用时 **建议** 将配置文件作为 `config` 或 `secret` 挂载到容器中,请读者自行学习 `Kubernetes` 的相关内容。 +本小节内容为了方便测试,将配置文件直接放到了镜像中,实际在使用时**建议**将配置文件作为 `config` 或 `secret` 挂载到容器中,请读者自行学习 `Kubernetes` 的相关内容。 由于篇幅所限本小节只是简单列出,更多内容可以参考 https://github.com/khs1994-docker/laravel-demo 项目。 diff --git a/07_dockerfile/7.1_run.md b/07_dockerfile/7.1_run.md index e8d22e1..6ceaa14 100644 --- a/07_dockerfile/7.1_run.md +++ b/07_dockerfile/7.1_run.md @@ -1,7 +1,11 @@ ## 7.1 RUN 执行命令 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker RUN RUN ["executable", "param1", "param2"] @@ -13,7 +17,11 @@ RUN ["executable", "param1", "param2"] ### 两种格式对比 -#### 1. Shell 格式 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。Shell 格式 + +如下代码块所示,展示了相关示例: ```docker RUN apt-get update @@ -26,7 +34,9 @@ RUN apt-get update RUN echo "Hello" > /test.txt ``` -#### 2. Exec 格式 +#### 2。Exec 格式 + +如下代码块所示,展示了相关示例: ```docker RUN ["apt-get", "update"] @@ -34,17 +44,19 @@ RUN ["apt-get", "update"] - **特点**:直接调用可执行文件,不经过 Shell。 - **优势**:避免 Shell 字符串解析问题,适用于参数中包含特殊字符的情况。 -- **注意**:无法使用 `$VAR` 环境变量替换(除非显式调用 shell)。 +- **注意**:无法使用 `$VAR` 环境变量替换 (除非显式调用 shell)。 --- ### 常见最佳实践 -#### 1. 组合命令(减少层数) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。组合命令 (减少层数) 每一个 `RUN` 指令都会新建一层镜像。为了减少镜像体积和层数,应使用 `&&` 连接命令。 -**❌ 糟糕的写法**(创建 3 层): +**❌ 糟糕的写法** (创建 3 层): ```docker RUN apt-get update @@ -52,7 +64,7 @@ RUN apt-get install -y nginx RUN rm -rf /var/lib/apt/lists/* ``` -**✅ 推荐写法**(创建 1 层): +**✅ 推荐写法** (创建 1 层): ```docker RUN apt-get update && \ @@ -60,7 +72,7 @@ RUN apt-get update && \ rm -rf /var/lib/apt/lists/* ``` -#### 2. 清理缓存 +#### 2。清理缓存 在安装完软件后,立即清除缓存,可以显著减小镜像体积。 @@ -74,7 +86,7 @@ RUN apt-get update && \ RUN apk add --no-cache package-bar ``` -#### 3. 使用 `set -e` 和 `pipefail` +#### 3。使用 `set -e` 和 `pipefail` 默认情况下,管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功,整个 `RUN` 就视为成功。 @@ -97,21 +109,27 @@ RUN wget http://url | gzip -d > file ### 常见问题 -#### Q: 为什么 `RUN cd /app` 不生效? +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:为什么 `RUN cd /app` 不生效? + +如下代码块所示,展示了相关示例: ```docker RUN cd /app RUN touch hello.txt ``` -**结果**:`hello.txt` 会出现在根目录 `/`,而不是 `/app`。**原因**:每个 `RUN` 都在一个新的 Shell/容器 环境中执行。`cd` 只影响当前 `RUN` 的环境。**解决**:使用 `WORKDIR` 指令。 +**结果**:`hello.txt` 会出现在根目录 `/`,而不是 `/app`。**原因**:每个 `RUN` 都在一个新的 Shell/容器环境中执行。`cd` 只影响当前 `RUN` 的环境。**解决**:使用 `WORKDIR` 指令。 ```docker WORKDIR /app RUN touch hello.txt ``` -#### Q: 环境变量不生效? +#### Q:环境变量不生效? + +如下代码块所示,展示了相关示例: ```docker RUN export MY_VAR=hello @@ -129,7 +147,9 @@ RUN echo $MY_VAR ### 高级技巧 -#### 1. 使用 BuildKit 的挂载缓存 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。使用 BuildKit 的挂载缓存 BuildKit 支持在 `RUN` 指令中使用 `--mount` 挂载缓存,加速构建。 @@ -148,7 +168,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \ go build -o app ``` -#### 2. 挂载密钥 +#### 2。挂载密钥 安全地使用 SSH 密钥或 Token,而不将其记录在镜像中。 diff --git a/07_dockerfile/7.2_copy.md b/07_dockerfile/7.2_copy.md index 1c8fe2a..2caaa9a 100644 --- a/07_dockerfile/7.2_copy.md +++ b/07_dockerfile/7.2_copy.md @@ -1,7 +1,11 @@ ## 7.2 COPY 复制文件 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker COPY [选项] <源路径>... <目标路径> COPY [选项] ["<源路径1>", "<源路径2>", ... "<目标路径>"] @@ -13,8 +17,12 @@ COPY [选项] ["<源路径1>", "<源路径2>", ... "<目标路径>"] ### 基本用法 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 复制单个文件 +如下代码块所示,展示了相关示例: + ```docker ## 复制文件到指定目录 @@ -27,6 +35,8 @@ COPY config.json /app/settings.json #### 复制多个文件 +如下代码块所示,展示了相关示例: + ```docker ## 复制多个指定文件 @@ -40,6 +50,8 @@ COPY src/*.js /app/src/ #### 复制目录 +如下代码块所示,展示了相关示例: + ```docker ## 复制整个目录的内容(不是目录本身) @@ -78,13 +90,19 @@ COPY app[0-9].js /app/ # app0.js ~ app9.js ### 目标路径 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 绝对路径 +如下代码块所示,展示了相关示例: + ```docker COPY app.js /usr/src/app/ ``` -#### 相对路径(基于 WORKDIR) +#### 相对路径 (基于 WORKDIR) + +如下代码块所示,展示了相关示例: ```docker WORKDIR /app @@ -168,8 +186,12 @@ ADD app.tar.gz /app/ ### 多阶段构建中的 COPY +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 从其他构建阶段复制 +如下代码块所示,展示了相关示例: + ```docker ## 构建阶段 @@ -186,7 +208,9 @@ FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html ``` -#### 使用 --link 优化缓存(BuildKit) +#### 使用 --link 优化缓存 + +如下代码块所示,展示了相关示例: ```docker ## 使用 --link 后,文件以独立层添加,不依赖前序指令 @@ -225,7 +249,11 @@ Dockerfile ### 最佳实践 -#### 1. 利用缓存,先复制依赖文件 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。利用缓存,先复制依赖文件 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 好:先复制依赖定义,再安装,最后复制代码 @@ -240,7 +268,9 @@ COPY . . RUN npm install ``` -#### 2. 使用 .dockerignore +#### 2。使用。dockerignore + +如下代码块所示,展示了相关示例: ```docker ## 确保 node_modules 不被复制 @@ -251,7 +281,9 @@ COPY . . ... ``` -#### 3. 明确复制路径 +#### 3。明确复制路径 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 好:明确的路径 diff --git a/07_dockerfile/7.3_add.md b/07_dockerfile/7.3_add.md index 985e0c4..b1fc15a 100644 --- a/07_dockerfile/7.3_add.md +++ b/07_dockerfile/7.3_add.md @@ -1,7 +1,11 @@ ## 7.3 ADD 更高级的复制文件 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker ADD [选项] <源路径>... <目标路径> ADD [选项] ["<源路径>", ... "<目标路径>"] @@ -9,7 +13,7 @@ ADD [选项] ["<源路径>", ... "<目标路径>"] `ADD` 在 `COPY` 基础上增加了两个功能: 1. 自动解压 tar 压缩包 -2. 支持从 URL 下载文件(不推荐) +2. 支持从 URL 下载文件 (不推荐) --- @@ -29,7 +33,11 @@ ADD [选项] ["<源路径>", ... "<目标路径>"] ### 自动解压功能 -#### 基本用法(自动解压本地 tar) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 基本用法 (自动解压本地 tar) + +如下代码块所示,展示了相关示例: ```docker ## 自动解压 tar.gz 到目标目录 @@ -54,6 +62,8 @@ ADD ubuntu-noble-core-cloudimg-amd64-root.tar.gz / #### 解压过程 +如下代码块所示,展示了相关示例: + ``` ADD app.tar.gz /app/ │ @@ -69,10 +79,14 @@ app.tar.gz 包含: /app/ 目录结果: --- -### URL 下载功能(不推荐) +### URL 下载功能 (不推荐) + +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: #### 基本用法 +如下代码块所示,展示了相关示例: + ```docker ## 从 URL 下载文件 @@ -90,6 +104,8 @@ ADD https://example.com/app.zip /app/app.zip #### 推荐替代方案 +如下代码块所示,展示了相关示例: + ```docker ## ❌ 不推荐:使用 ADD 下载 @@ -110,6 +126,8 @@ RUN curl -fsSL https://example.com/app.tar.gz | tar -xz -C /app ### 修改文件所有者 +如下代码块所示,展示了相关示例: + ```docker ADD --chown=node:node app.tar.gz /app/ ADD --chown=1000:1000 files/ /app/ @@ -119,8 +137,12 @@ ADD --chown=1000:1000 files/ /app/ ### 何时使用 ADD +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### ✅ 适合使用 ADD +如下代码块所示,展示了相关示例: + ```docker ## 解压本地 tar 文件 @@ -134,6 +156,8 @@ ADD dist.tar.gz /app/ #### ❌ 不适合使用 ADD +如下代码块所示,展示了相关示例: + ```docker ## 复制普通文件(用 COPY) @@ -181,7 +205,11 @@ ADD app.tar.gz /app/ ### 最佳实践 -#### 1. 默认使用 COPY +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。默认使用 COPY + +如下代码块所示,展示了相关示例: ```docker ## ✅ 大多数场景使用 COPY @@ -189,7 +217,9 @@ ADD app.tar.gz /app/ COPY . /app/ ``` -#### 2. 仅在需要解压时使用 ADD +#### 2。仅在需要解压时使用 ADD + +如下代码块所示,展示了相关示例: ```docker ## ✅ 自动解压场景 @@ -197,7 +227,9 @@ COPY . /app/ ADD app.tar.gz /app/ ``` -#### 3. 不要用 ADD 下载文件 +#### 3。不要用 ADD 下载文件 + +如下代码块所示,展示了相关示例: ```docker ## ❌ 避免 @@ -209,7 +241,9 @@ ADD https://example.com/file.tar.gz /tmp/ RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app ``` -#### 4. 解压后清理 +#### 4。解压后清理 + +如下代码块所示,展示了相关示例: ```docker ## 如果需要控制解压过程 diff --git a/07_dockerfile/7.4_cmd.md b/07_dockerfile/7.4_cmd.md index 529d5f9..be432f1 100644 --- a/07_dockerfile/7.4_cmd.md +++ b/07_dockerfile/7.4_cmd.md @@ -1,8 +1,10 @@ ## 7.4 CMD 容器启动命令 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 什么是 CMD -`CMD` 指令用于指定容器启动时默认执行的命令。它定义了容器的"主进程"。 +`CMD` 指令用于指定容器启动时默认执行的命令。它定义了容器的 “主进程”。 > **核心概念**:容器的生命周期 = 主进程的生命周期。CMD 指定的命令就是这个主进程。 @@ -18,7 +20,9 @@ CMD 有三种格式: | **shell 格式** | `CMD 命令 参数1 参数2` | ⚠️ 简单场景 | | **参数格式** | `CMD ["参数1", "参数2"]` | 配合 ENTRYPOINT | -#### exec 格式(推荐) +#### exec 格式 (推荐) + +如下代码块所示,展示了相关示例: ```docker CMD ["nginx", "-g", "daemon off;"] @@ -28,11 +32,13 @@ CMD ["node", "server.js"] **优点**: - 直接执行指定程序,是容器的 PID 1 -- 正确接收信号(如 SIGTERM) +- 正确接收信号 (如 SIGTERM) - 无需 shell 解析 #### shell 格式 +如下代码块所示,展示了相关示例: + ```docker CMD echo "Hello World" CMD nginx -g "daemon off;" @@ -63,8 +69,14 @@ CMD ["sh", "-c", "echo $HOME"] | 环境变量 | ❌ 需要 shell 包装 | ✅ 自动解析 | | 推荐使用 | ✅ 大多数场景 | 需要 shell 特性时 | +#### 概述 + +总体概述了以下内容。 + #### 信号传递问题示例 +如下代码块所示,展示了相关示例: + ```docker ## ❌ shell 格式:docker stop 会超时 @@ -107,8 +119,12 @@ CMD ["/bin/bash"] + cat /etc/os-release ### 经典错误:容器立即退出 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 错误示例 +如下代码块所示,展示了相关示例: + ```docker ## ❌ 容器启动后立即退出 @@ -117,6 +133,8 @@ CMD service nginx start #### 原因分析 +如下代码块所示,展示了相关示例: + ``` 1. CMD service nginx start ↓ 被转换为 @@ -133,6 +151,8 @@ CMD service nginx start #### 正确做法 +如下代码块所示,展示了相关示例: + ```docker ## ✅ 让 nginx 在前台运行 @@ -150,6 +170,8 @@ CMD ["nginx", "-g", "daemon off;"] #### 单独使用 CMD +如下代码块所示,展示了相关示例: + ```docker ## Dockerfile @@ -163,6 +185,8 @@ $ docker run myimage curl -v ... # 完全覆盖 #### 搭配 ENTRYPOINT +如下代码块所示,展示了相关示例: + ```docker ## Dockerfile @@ -175,13 +199,17 @@ $ docker run myimage # curl -s http://example.com $ docker run myimage http://other.com # curl -s http://other.com(参数覆盖) ``` -详见 [ENTRYPOINT 入口点](7.5_entrypoint.md) 章节。 +详见 [ENTRYPOINT 入口点](7.5_entrypoint.md)章节。 --- ### 最佳实践 -#### 1. 优先使用 exec 格式 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。优先使用 exec 格式 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 推荐 @@ -193,7 +221,9 @@ CMD ["python", "app.py"] CMD ["sh", "-c", "echo $PATH && python app.py"] ``` -#### 2. 确保应用在前台运行 +#### 2。确保应用在前台运行 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 前台运行 @@ -208,7 +238,9 @@ CMD service nginx start CMD systemctl start nginx ``` -#### 3. 使用双引号 +#### 3。使用双引号 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 正确:双引号 @@ -220,7 +252,9 @@ CMD ["node", "server.js"] CMD ['node', 'server.js'] ``` -#### 4. 配合 ENTRYPOINT 使用 +#### 4。配合 ENTRYPOINT 使用 + +如下代码块所示,展示了相关示例: ```docker ## 用于可配置参数的场景 @@ -239,7 +273,9 @@ $ docker run myapp --port 9000 ### 常见问题 -#### Q: CMD 可以写多个吗? +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:CMD 可以写多个吗? 不可以。多个 CMD 只有最后一个生效: @@ -248,7 +284,9 @@ CMD ["echo", "first"] CMD ["echo", "second"] # 只有这个生效 ``` -#### Q: 如何在 CMD 中使用环境变量? +#### Q:如何在 CMD 中使用环境变量? + +如下代码块所示,展示了相关示例: ```docker ## 方法1:使用 shell 格式 @@ -260,7 +298,7 @@ CMD echo "Port is $PORT" CMD ["sh", "-c", "echo Port is $PORT"] ``` -#### Q: 为什么我的容器不响应 Ctrl+C? +#### Q:为什么我的容器不响应 Ctrl+C? 可能是使用了 shell 格式,信号被 sh 吃掉了: diff --git a/07_dockerfile/7.5_entrypoint.md b/07_dockerfile/7.5_entrypoint.md index 95b2af6..c818054 100644 --- a/07_dockerfile/7.5_entrypoint.md +++ b/07_dockerfile/7.5_entrypoint.md @@ -1,5 +1,7 @@ ## 7.5 ENTRYPOINT 入口点 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 什么是 ENTRYPOINT `ENTRYPOINT` 指定容器启动时运行的入口程序。与 CMD 不同,ENTRYPOINT 定义的命令不会被 `docker run` 的参数覆盖,而是**接收这些参数**。 @@ -29,6 +31,8 @@ ENTRYPOINT nginx -g "daemon off;" ### ENTRYPOINT vs CMD +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 核心区别 | 特性 | ENTRYPOINT | CMD | @@ -40,6 +44,8 @@ ENTRYPOINT nginx -g "daemon off;" #### 行为对比 +如下代码块所示,展示了相关示例: + ```docker ## 只用 CMD @@ -80,12 +86,16 @@ $ docker run myimage -v http://other.com # curl -s -v http://other.com ✓ ### 场景一:让镜像像命令一样使用 -#### 需求(启动前准备) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: -创建一个查询公网 IP 的"命令"镜像。 +#### 需求 (启动前准备) + +创建一个查询公网 IP 的 “命令” 镜像。 #### 使用 CMD 的问题 +如下代码块所示,展示了相关示例: + ```docker FROM ubuntu:24.04 RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* @@ -105,6 +115,8 @@ exec: "-i": executable file not found #### 使用 ENTRYPOINT 解决 +如下代码块所示,展示了相关示例: + ```docker FROM ubuntu:24.04 RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* @@ -123,6 +135,8 @@ HTTP/1.1 200 OK #### 交互图示 +如下代码块所示,展示了相关示例: + ``` ENTRYPOINT ["curl", "-s", "http://myip.ipip.net"] │ @@ -138,12 +152,16 @@ curl -s http://myip.ipip.net -i ### 场景二:启动前的准备工作 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 需求 -在启动主服务前执行初始化脚本(如数据库迁移、权限设置)。 +在启动主服务前执行初始化脚本 (如数据库迁移、权限设置)。 #### 实现方式 +如下代码块所示,展示了相关示例: + ```docker FROM redis:7-alpine COPY docker-entrypoint.sh /usr/local/bin/ @@ -175,6 +193,8 @@ exec "$@" #### 工作流程 +如下代码块所示,展示了相关示例: + ``` docker run redis docker run redis bash │ │ @@ -189,14 +209,16 @@ docker-entrypoint.sh redis-server docker-entrypoint.sh bash #### 关键点 -1. **exec "$@"**:用传入的参数替换当前进程,确保信号正确传递 +1. **exec “$@”**:用传入的参数替换当前进程,确保信号正确传递 2. **条件判断**:根据 CMD 不同执行不同逻辑 -3. **用户切换**:使用 `gosu` 切换用户(比 `su` 更适合容器) +3. **用户切换**:使用 `gosu` 切换用户 (比 `su` 更适合容器) --- ### 场景三:带参数的应用 +如下代码块所示,展示了相关示例: + ```docker FROM python:3.12-slim WORKDIR /app @@ -264,7 +286,11 @@ $ docker run --entrypoint /bin/cat myimage /etc/os-release ### 最佳实践 -#### 1. 使用 exec 格式 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。使用 exec 格式 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 推荐 @@ -276,14 +302,16 @@ ENTRYPOINT ["python", "app.py"] ENTRYPOINT python app.py ``` -#### 2. 提供有意义的默认参数 +#### 2。提供有意义的默认参数 + +如下代码块所示,展示了相关示例: ```docker ENTRYPOINT ["nginx"] CMD ["-g", "daemon off;"] ``` -#### 3. 入口脚本使用 exec +#### 3。入口脚本使用 exec 运行以下命令: @@ -296,7 +324,7 @@ CMD ["-g", "daemon off;"] exec "$@" ``` -#### 4. 处理信号 +#### 4。处理信号 确保 ENTRYPOINT 脚本能正确传递信号: diff --git a/07_dockerfile/7.6_env.md b/07_dockerfile/7.6_env.md index 0afbd69..8bcfc27 100644 --- a/07_dockerfile/7.6_env.md +++ b/07_dockerfile/7.6_env.md @@ -1,7 +1,11 @@ ## 7.6 ENV 设置环境变量 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker ## 格式一:单个变量 @@ -16,8 +20,12 @@ ENV = = ... ### 基本用法 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 设置单个变量 +如下代码块所示,展示了相关示例: + ```docker ENV NODE_VERSION 20.10.0 ENV APP_ENV production @@ -25,6 +33,8 @@ ENV APP_ENV production #### 设置多个变量 +如下代码块所示,展示了相关示例: + ```docker ENV NODE_VERSION=20.10.0 \ APP_ENV=production \ @@ -37,7 +47,11 @@ ENV NODE_VERSION=20.10.0 \ ### 环境变量的作用 -#### 1. 后续指令中使用 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。后续指令中使用 + +如下代码块所示,展示了相关示例: ```docker ENV NODE_VERSION=20.10.0 @@ -57,7 +71,9 @@ WORKDIR $APP_HOME COPY . $APP_HOME ``` -#### 2. 容器运行时使用 +#### 2。容器运行时使用 + +如下代码块所示,展示了相关示例: ```docker ENV DATABASE_URL=postgres://localhost/mydb @@ -114,7 +130,11 @@ $ docker run -e APP_ENV=development -e DEBUG=true myimage $ docker run --env-file .env myimage ``` -#### .env 文件格式 +#### 概述 + +总体概述了以下内容。 + +#### 。env 文件格式 运行以下命令: @@ -137,8 +157,14 @@ DATABASE_URL=postgres://localhost/mydb | **覆盖方式** | `docker run -e` | `docker build --build-arg` | | **适用场景** | 应用配置 | 构建参数(如版本号) | +#### 概述 + +总体概述了以下内容。 + #### 组合使用 +如下代码块所示,展示了相关示例: + ```docker ## ARG 接收构建时参数 @@ -163,7 +189,11 @@ $ docker build --build-arg NODE_VERSION=18 -t myapp . ### 最佳实践 -#### 1. 统一管理版本号 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。统一管理版本号 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 好:版本集中管理 @@ -179,7 +209,9 @@ RUN apt-get install nginx=${NGINX_VERSION} RUN apt-get install nginx=1.25.0 ``` -#### 2. 不要存储敏感信息 +#### 2。不要存储敏感信息 + +如下代码块所示,展示了相关示例: ```docker ## ❌ 错误:密码写入镜像 @@ -193,7 +225,9 @@ ENV DB_PASSWORD=secret123 ... ``` -#### 3. 为应用提供合理默认值 +#### 3。为应用提供合理默认值 + +如下代码块所示,展示了相关示例: ```docker ENV APP_ENV=production \ @@ -201,7 +235,9 @@ ENV APP_ENV=production \ LOG_LEVEL=info ``` -#### 4. 使用有意义的变量名 +#### 4。使用有意义的变量名 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 好:清晰的命名 @@ -219,7 +255,9 @@ ENV HOST=localhost \ ### 常见问题 -#### Q: 环境变量在 CMD 中不展开 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:环境变量在 CMD 中不展开 exec 格式不会自动展开环境变量: @@ -233,7 +271,7 @@ CMD ["python", "app.py", "--port", "$PORT"] CMD ["sh", "-c", "python app.py --port $PORT"] ``` -#### Q: 如何查看容器的环境变量 +#### Q:如何查看容器的环境变量 运行以下命令: @@ -242,7 +280,9 @@ $ docker inspect mycontainer --format '{{json .Config.Env}}' $ docker exec mycontainer env ``` -#### Q: 多行 ENV 还是多个 ENV +#### Q:多行 ENV 还是多个 ENV + +如下代码块所示,展示了相关示例: ```docker ## ✅ 推荐:减少层数 diff --git a/07_dockerfile/7.7_arg.md b/07_dockerfile/7.7_arg.md index b0b07bf..cdfd342 100644 --- a/07_dockerfile/7.7_arg.md +++ b/07_dockerfile/7.7_arg.md @@ -1,7 +1,11 @@ ## 7.7 ARG 构建参数 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker ARG <参数名>[=<默认值>] ``` @@ -33,8 +37,12 @@ ARG <参数名>[=<默认值>] ### 基本用法 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 定义和使用 +如下代码块所示,展示了相关示例: + ```docker ## 定义有默认值的 ARG @@ -64,8 +72,12 @@ $ docker build --build-arg NODE_VERSION=18 -t myapp . ### ARG 的作用域 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### FROM 之前的 ARG +如下代码块所示,展示了相关示例: + ```docker ## FROM 之前的 ARG 只能用于 FROM 指令 @@ -81,6 +93,8 @@ RUN echo $REGISTRY # 输出空 #### FROM 之后重新声明 +如下代码块所示,展示了相关示例: + ```docker ARG NODE_VERSION=20 @@ -94,6 +108,8 @@ RUN echo "Node version: $NODE_VERSION" #### 多阶段构建中的 ARG +如下代码块所示,展示了相关示例: + ```docker ARG BASE_VERSION=alpine @@ -114,7 +130,11 @@ RUN echo "Running with Node $NODE_VERSION" ### 常见使用场景 -#### 1. 控制基础镜像版本 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。控制基础镜像版本 + +如下代码块所示,展示了相关示例: ```docker ARG ALPINE_VERSION=3.19 @@ -125,7 +145,9 @@ FROM alpine:${ALPINE_VERSION} $ docker build --build-arg ALPINE_VERSION=3.18 . ``` -#### 2. 设置软件版本 +#### 2。设置软件版本 + +如下代码块所示,展示了相关示例: ```docker ARG NGINX_VERSION=1.25.0 @@ -133,7 +155,9 @@ ARG NGINX_VERSION=1.25.0 RUN curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xz ``` -#### 3. 配置构建环境 +#### 3。配置构建环境 + +如下代码块所示,展示了相关示例: ```docker ARG BUILD_ENV=production @@ -146,7 +170,9 @@ RUN if [ "$ENABLE_DEBUG" = "true" ]; then \ fi ``` -#### 4. 配置私有仓库 +#### 4。配置私有仓库 + +如下代码块所示,展示了相关示例: ```docker ARG NPM_TOKEN @@ -203,7 +229,11 @@ $ docker build --build-arg HTTP_PROXY=http://proxy:8080 . ### 最佳实践 -#### 1. 为 ARG 提供合理默认值 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。为 ARG 提供合理默认值 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 好:有默认值 @@ -215,7 +245,9 @@ ARG NODE_VERSION=20 ARG NODE_VERSION ``` -#### 2. 不要用 ARG 存储敏感信息 +#### 2。不要用 ARG 存储敏感信息 + +如下代码块所示,展示了相关示例: ```docker ## ❌ 错误:密码会被记录在镜像历史中 @@ -228,7 +260,9 @@ RUN echo "password=$DB_PASSWORD" > /app/.env ... ``` -#### 3. 使用 ARG 提高构建灵活性 +#### 3。使用 ARG 提高构建灵活性 + +如下代码块所示,展示了相关示例: ```docker ARG BASE_IMAGE=python:3.12-slim diff --git a/07_dockerfile/7.8_volume.md b/07_dockerfile/7.8_volume.md index 57d2539..49b7049 100644 --- a/07_dockerfile/7.8_volume.md +++ b/07_dockerfile/7.8_volume.md @@ -1,7 +1,11 @@ ## 7.8 VOLUME 定义匿名卷 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker VOLUME ["/路径1", "/路径2"] VOLUME /路径 @@ -43,8 +47,12 @@ flowchart LR ### 基本用法 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 定义单个卷 +如下代码块所示,展示了相关示例: + ```docker FROM mysql:8.0 VOLUME /var/lib/mysql @@ -52,6 +60,8 @@ VOLUME /var/lib/mysql #### 定义多个卷 +如下代码块所示,展示了相关示例: + ```docker FROM myapp VOLUME ["/data", "/logs", "/config"] @@ -61,7 +71,9 @@ VOLUME ["/data", "/logs", "/config"] ### VOLUME 的行为 -#### 1. 自动创建匿名卷 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。自动创建匿名卷 如果运行时未指定挂载,Docker 会自动创建匿名卷: @@ -72,7 +84,7 @@ DRIVER VOLUME NAME local a1b2c3d4e5f6... # 自动创建的匿名卷 ``` -#### 2. 可被命名卷覆盖 +#### 2。可被命名卷覆盖 运行以下命令: @@ -82,7 +94,7 @@ local a1b2c3d4e5f6... # 自动创建的匿名卷 $ docker run -v mysql_data:/var/lib/mysql mysql:8.0 ``` -#### 3. 可被 Bind Mount 覆盖 +#### 3。可被 Bind Mount 覆盖 运行以下命令: @@ -109,8 +121,14 @@ RUN echo "hello" > /data/test.txt **原因**:VOLUME 指令之后,Docker 将该目录视为外部挂载点,不再记录对它的修改。 +#### 概述 + +总体概述了以下内容。 + #### 正确做法 +如下代码块所示,展示了相关示例: + ```docker FROM ubuntu @@ -127,8 +145,12 @@ VOLUME /data ### 常见使用场景 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 数据库持久化 +如下代码块所示,展示了相关示例: + ```docker FROM postgres:15 VOLUME /var/lib/postgresql/data @@ -136,6 +158,8 @@ VOLUME /var/lib/postgresql/data #### 日志目录 +如下代码块所示,展示了相关示例: + ```docker FROM nginx VOLUME /var/log/nginx @@ -143,6 +167,8 @@ VOLUME /var/log/nginx #### 上传文件目录 +如下代码块所示,展示了相关示例: + ```docker FROM myapp VOLUME /app/uploads @@ -182,7 +208,7 @@ $ docker inspect mycontainer --format '{{json .Mounts}}' | jq ### 在 Compose 中 -在 Compose 中 配置如下: +在 Compose 中配置如下: ```yaml services: @@ -204,6 +230,12 @@ volumes: ### 安全注意事项 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 概述 + +总体概述了以下内容。 + #### 匿名卷可能导致数据丢失 运行以下命令: @@ -227,7 +259,11 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.0 ### 最佳实践 -#### 1. 定义必须持久化的路径 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。定义必须持久化的路径 + +如下代码块所示,展示了相关示例: ```docker ## 数据库必须使用卷 @@ -236,7 +272,9 @@ FROM postgres:15 VOLUME /var/lib/postgresql/data ``` -#### 2. 不要在 VOLUME 后修改目录 +#### 2。不要在 VOLUME 后修改目录 + +如下代码块所示,展示了相关示例: ```docker ## ❌ 避免 @@ -250,7 +288,9 @@ RUN mkdir -p /app/data && cp init-data.json /app/data/ VOLUME /app/data ``` -#### 3. 文档中说明 VOLUME 用途 +#### 3。文档中说明 VOLUME 用途 + +如下代码块所示,展示了相关示例: ```docker ## 持久化用户上传的文件 diff --git a/07_dockerfile/7.9_expose.md b/07_dockerfile/7.9_expose.md index dcf4ba0..9fcbc88 100644 --- a/07_dockerfile/7.9_expose.md +++ b/07_dockerfile/7.9_expose.md @@ -1,7 +1,11 @@ ## 7.9 EXPOSE 声明端口 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本语法 +如下代码块所示,展示了相关示例: + ```docker EXPOSE <端口> [<端口>/<协议>...] ``` @@ -12,6 +16,8 @@ EXPOSE <端口> [<端口>/<协议>...] ### 基本用法 +如下代码块所示,展示了相关示例: + ```docker ## 声明单个端口 @@ -31,7 +37,9 @@ EXPOSE 53/udp ### EXPOSE 的作用 -#### 1. 文档说明 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。文档说明 告诉镜像使用者,容器将在哪些端口提供服务: @@ -48,7 +56,7 @@ $ docker inspect nginx --format '{{.Config.ExposedPorts}}' map[80/tcp:{}] ``` -#### 2. 配合 -P 使用 +#### 2。配合 -P 使用 使用 `docker run -P` 时,Docker 会自动映射 EXPOSE 的端口到宿主机随机端口: @@ -82,8 +90,14 @@ flowchart TD Expose ~~~ Run ``` +#### 概述 + +总体概述了以下内容。 + #### 没有 EXPOSE 也能 -p +如下代码块所示,展示了相关示例: + ```docker ## 即使没有 EXPOSE,也可以使用 -p @@ -103,8 +117,12 @@ $ docker run -p 8080:80 mynginx ### 常见误解 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 误解:EXPOSE 会打开端口 +如下代码块所示,展示了相关示例: + ```docker ## ❌ 错误理解:这不会让容器可从外部访问 @@ -120,6 +138,8 @@ EXPOSE 只是元数据声明。容器是否实际监听该端口,取决于容 #### 正确理解 +如下代码块所示,展示了相关示例: + ```docker ## Dockerfile @@ -137,7 +157,11 @@ $ docker run -p 8080:80 nginx # 2. 映射:宿主机 8080 → 容器 80 ### 最佳实践 -#### 1. 总是声明应用使用的端口 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。总是声明应用使用的端口 + +如下代码块所示,展示了相关示例: ```docker ## Web 服务 @@ -156,7 +180,9 @@ FROM redis EXPOSE 6379 ``` -#### 2. 使用明确的协议 +#### 2。使用明确的协议 + +如下代码块所示,展示了相关示例: ```docker ## 默认是 TCP @@ -172,7 +198,9 @@ EXPOSE 53/udp EXPOSE 53/tcp 53/udp ``` -#### 3. 与应用实际端口保持一致 +#### 3。与应用实际端口保持一致 + +如下代码块所示,展示了相关示例: ```docker ## ✅ 好:EXPOSE 与应用端口一致 @@ -191,6 +219,8 @@ CMD ["node", "server.js"] # 实际监听 3000 ### 使用环境变量 +如下代码块所示,展示了相关示例: + ```docker ARG PORT=80 EXPOSE $PORT @@ -200,7 +230,7 @@ EXPOSE $PORT ### 在 Compose 中 -在 Compose 中 配置如下: +在 Compose 中配置如下: ```yaml services: diff --git a/07_dockerfile/README.md b/07_dockerfile/README.md index 1097b27..80d6f0e 100644 --- a/07_dockerfile/README.md +++ b/07_dockerfile/README.md @@ -1,22 +1,28 @@ # 第七章 Dockerfile 指令详解 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ## 什么是 Dockerfile -Dockerfile 是一个文本文件,其內包含了一条条的 **指令(Instruction)**,每一条指令构建一层,therefore 每一条指令的内容,就是描述该层应当如何构建。 +Dockerfile 是一个文本文件,其內包含了一条条的**指令 (Instruction)**,每一条指令构建一层,therefore 每一条指令的内容,就是描述该层应当如何构建。 -在 [第四章](../04_image/README.md) 中,我们通过 `docker commit` 学习了镜像的构成。但是,手动 `commit` 只能作为临时修补,并不适合作为生产环境镜像的构建方式。 +在[第四章](../04_image/README.md)中,我们通过 `docker commit` 学习了镜像的构成。但是,手动 `commit` 只能作为临时修补,并不适合作为生产环境镜像的构建方式。 使用 Dockerfile 构建镜像有以下优势: * **自动化**:可以通过 `docker build` 命令自动构建镜像。 * **可重复性**:由于 Dockerfile 是文本文件,可以确保每次构建的结果一致。 -* **版本控制**:Dockerfile 可以纳入版本控制系统(如 Git),便于追踪变更。 +* **版本控制**:Dockerfile 可以纳入版本控制系统 (如 Git),便于追踪变更。 * **透明性**:任何人都可以通过阅读 Dockerfile 了解镜像的构建过程。 ## Dockerfile 基本结构 Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。 +### 概述 + +总体概述了以下内容。 + ### 指令详解 本章将详细讲解 Dockerfile 中的各个指令: diff --git a/08_data_network/README.md b/08_data_network/README.md index 11686c1..885bbeb 100644 --- a/08_data_network/README.md +++ b/08_data_network/README.md @@ -1,4 +1,4 @@ -# 第八章 数据与网络管理 +# 第八章数据与网络管理 本章将介绍 Docker 中的数据管理与网络配置。 diff --git a/08_data_network/data/bind-mounts.md b/08_data_network/data/bind-mounts.md index 90f4e82..f0867a1 100644 --- a/08_data_network/data/bind-mounts.md +++ b/08_data_network/data/bind-mounts.md @@ -1,8 +1,10 @@ ## 挂载主机目录 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 什么是绑定挂载 -Bind Mount(绑定挂载)将**宿主机的目录或文件**直接挂载到容器中。容器可以读写宿主机的文件系统。 +Bind Mount (绑定挂载) 将**宿主机的目录或文件**直接挂载到容器中。容器可以读写宿主机的文件系统。 ```mermaid flowchart LR @@ -32,6 +34,10 @@ flowchart LR | **适用场景** | 开发环境、配置文件 | 生产数据持久化 | | **备份** | 直接访问文件 | 需要通过 Docker | +#### 概述 + +总体概述了以下内容。 + #### 选择建议 | 需求 | 推荐方案 | @@ -47,7 +53,9 @@ flowchart LR ### 基本语法 -#### 使用 --mount(推荐) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 使用 --mount (推荐) 运行以下命令: @@ -57,7 +65,7 @@ $ docker run -d \ nginx ``` -#### 使用 -v(简写) +#### 使用 -v (简写) 运行以下命令: @@ -79,6 +87,8 @@ $ docker run -d \ ### 使用场景 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 场景一:开发环境代码同步 运行以下命令: @@ -182,7 +192,7 @@ $ docker run -d \ mysql ``` -> ⚠️ **注意**:挂载单个文件时,如果宿主机上的文件被编辑器替换(而非原地修改),容器内仍是旧文件的 inode。建议重启容器或挂载目录。 +> ⚠️ **注意**:挂载单个文件时,如果宿主机上的文件被编辑器替换 (而非原地修改),容器内仍是旧文件的 inode。建议重启容器或挂载目录。 --- @@ -221,7 +231,9 @@ $ docker inspect mycontainer --format '{{json .Mounts}}' | jq ### 常见问题 -#### Q: 路径不存在报错 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:路径不存在报错 运行以下命令: @@ -231,9 +243,9 @@ docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /not/exist ``` -**解决**:确保源路径存在,或改用 `-v`(会自动创建) +**解决**:确保源路径存在,或改用 `-v` (会自动创建) -#### Q: 权限问题 +#### Q:权限问题 容器内用户可能无权访问挂载的文件: @@ -251,9 +263,9 @@ $ docker run -u root ... $ docker run -u $(id -u):$(id -g) ... ``` -#### Q: macOS/Windows 性能问题 +#### Q:macOS/Windows 性能问题 -在 Docker Desktop 上,Bind Mount 性能较差(需要跨文件系统同步): +在 Docker Desktop 上,Bind Mount 性能较差 (需要跨文件系统同步): ```bash ## 使用 :cached 或 :delegated 提高性能(macOS) @@ -271,7 +283,9 @@ $ docker run -v /host/path:/container/path:cached myapp ### 最佳实践 -#### 1. 开发环境使用 Bind Mount +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。开发环境使用 Bind Mount 运行以下命令: @@ -281,7 +295,7 @@ $ docker run -v /host/path:/container/path:cached myapp $ docker run -v $(pwd):/app -p 3000:3000 node npm run dev ``` -#### 2. 生产环境使用 Volume +#### 2。生产环境使用 Volume 运行以下命令: @@ -291,7 +305,7 @@ $ docker run -v $(pwd):/app -p 3000:3000 node npm run dev $ docker run -v mysql_data:/var/lib/mysql mysql ``` -#### 3. 配置文件使用只读挂载 +#### 3。配置文件使用只读挂载 运行以下命令: @@ -299,7 +313,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql $ docker run -v /config/nginx.conf:/etc/nginx/nginx.conf:ro nginx ``` -#### 4. 注意路径安全 +#### 4。注意路径安全 运行以下命令: diff --git a/08_data_network/data/tmpfs.md b/08_data_network/data/tmpfs.md index c6fe3b8..2f07468 100644 --- a/08_data_network/data/tmpfs.md +++ b/08_data_network/data/tmpfs.md @@ -10,6 +10,8 @@ ### 基本用法 +如下代码块所示,展示了相关示例: + ```bash $ docker run --tmpfs /run:rw,noexec,nosuid,size=64m nginx ``` diff --git a/08_data_network/data/volume.md b/08_data_network/data/volume.md index bf4378f..68f4bc9 100644 --- a/08_data_network/data/volume.md +++ b/08_data_network/data/volume.md @@ -1,5 +1,7 @@ ## 数据卷 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 为什么需要数据卷 容器的存储层有一个关键问题:**容器删除后,数据就没了**。 @@ -11,7 +13,7 @@ flowchart LR Delete -->|数据都在容器 writable 层| Lost[DATA LOST! ❌] ``` -数据卷(Volume)解决了这个问题,它的生命周期独立于容器。 +数据卷 (Volume) 解决了这个问题,它的生命周期独立于容器。 --- @@ -29,7 +31,11 @@ flowchart LR ### 数据卷 vs 容器存储层 -#### 容器存储层(不推荐存储重要数据) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 容器存储层 (不推荐存储重要数据) + +如下代码块所示,展示了相关示例: ```mermaid graph TD @@ -43,7 +49,9 @@ graph TD Delete[容器删除] -->|导致| DataLost[数据丢失 ❌] ``` -#### 数据卷(推荐) +#### 数据卷 (推荐) + +如下代码块所示,展示了相关示例: ```mermaid graph TD @@ -63,6 +71,8 @@ graph TD ### 数据卷基本操作 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 创建数据卷 运行以下命令: @@ -104,13 +114,15 @@ $ docker volume inspect my-vol **关键字段**: - `Mountpoint`:数据卷在宿主机上的实际存储位置 -- `Driver`:存储驱动(默认 local,也可以用第三方驱动) +- `Driver`:存储驱动 (默认 local,也可以用第三方驱动) --- ### 挂载数据卷 -#### 方式一:--mount(推荐) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 方式一:--mount (推荐) 运行以下命令: @@ -129,7 +141,7 @@ $ docker run -d \ | `target` | 容器内挂载路径 | | `readonly` | 可选,只读挂载 | -#### 方式二:-v(简写) +#### 方式二:-v (简写) 运行以下命令: @@ -172,6 +184,8 @@ $ docker run -d \ ### 使用场景示例 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 场景一:数据库持久化 运行以下命令: @@ -242,6 +256,8 @@ $ docker run -d \ ### 数据卷管理 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 删除数据卷 运行以下命令: @@ -280,6 +296,8 @@ $ docker volume prune -f ### 数据卷备份与恢复 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 备份数据卷 运行以下命令: @@ -360,13 +378,15 @@ $ docker run -v mydata:/app/data nginx $ docker run -v /host/path:/app/data nginx ``` -详见 [绑定挂载](bind-mounts.md) 章节。 +详见[绑定挂载](bind-mounts.md)章节。 --- ### 常见问题 -#### Q: 如何知道容器使用了哪些数据卷? +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:如何知道容器使用了哪些数据卷? 运行以下命令: @@ -374,7 +394,7 @@ $ docker run -v /host/path:/app/data nginx $ docker inspect container_name --format '{{json .Mounts}}' | jq ``` -#### Q: 数据卷的数据在哪里? +#### Q:数据卷的数据在哪里? 运行以下命令: @@ -390,7 +410,7 @@ $ docker volume inspect my-vol > ⚠️ **注意**:不建议直接修改 Mountpoint 中的文件,应通过容器操作。 -#### Q: 如何在不同机器间迁移数据卷? +#### Q:如何在不同机器间迁移数据卷? 1. 在源机器备份:`docker run --rm -v mydata:/data -v $(pwd):/backup alpine tar czf /backup/data.tar.gz -C /data .` 2. 传输 tar.gz 文件 diff --git a/08_data_network/network/README.md b/08_data_network/network/README.md index afc9216..ff7e47d 100644 --- a/08_data_network/network/README.md +++ b/08_data_network/network/README.md @@ -1,9 +1,11 @@ # 网络配置 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ## Docker 网络概述 Docker 容器需要网络来: -- 与外部世界通信(访问互联网、被外部访问) +- 与外部世界通信 (访问互联网、被外部访问) - 容器之间相互通信 - 与宿主机通信 @@ -47,6 +49,8 @@ graph TD ### 数据流向 +如下代码块所示,展示了相关示例: + ```mermaid flowchart LR subgraph Comm1 ["容器间通信"] @@ -89,7 +93,9 @@ ghi789... none null local --- -## 用户自定义网络(推荐) +## 用户自定义网络 (推荐) + +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: ### 为什么要用自定义网络 @@ -148,6 +154,8 @@ flowchart LR ## 容器互联 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 同一网络内的容器 同一自定义网络内的容器可以直接通信: @@ -238,6 +246,8 @@ $ docker port mycontainer ### 端口映射示意图 +如下代码块所示,展示了相关示例: + ```mermaid flowchart TD Req["外部请求 http://宿主机IP:8080"] --> Host["宿主机:8080"] diff --git a/08_data_network/network/dns.md b/08_data_network/network/dns.md index ccc18e3..c6d5597 100644 --- a/08_data_network/network/dns.md +++ b/08_data_network/network/dns.md @@ -1,17 +1,19 @@ ## 配置 DNS +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 容器的 DNS 机制 Docker 容器的 DNS 配置有两种情况: -1. **默认 Bridge 网络**:继承宿主机的 DNS 配置(`/etc/resolv.conf`)。 -2. **自定义网络**(推荐):使用 Docker 嵌入式 DNS 服务器 (Embedded DNS),支持通过**容器名**进行服务发现。 +1. **默认 Bridge 网络**:继承宿主机的 DNS 配置 (`/etc/resolv.conf`)。 +2. **自定义网络** (推荐):使用 Docker 嵌入式 DNS 服务器 (Embedded DNS),支持通过**容器名**进行服务发现。 --- ### 嵌入式 DNS -这是 Docker 网络最强大的功能之一。在自定义网络中,容器可以通过"名字"找到彼此,而不需要知道对方的 IP(因为 IP 可能会变)。 +这是 Docker 网络最强大的功能之一。在自定义网络中,容器可以通过 “名字” 找到彼此,而不需要知道对方的 IP (因为 IP 可能会变)。 ```bash ## 1. 创建自定义网络 @@ -30,13 +32,13 @@ PING web (172.18.0.2): 56 data bytes ``` **原理**: -Docker 守护进程在 `127.0.0.11` 运行了一个 DNS 服务器。容器内的 DNS 请求会被转发到这里。如果是容器名,解析为容器 IP;如果是外部域名(如 google.com),转发给上游 DNS。 +Docker 守护进程在 `127.0.0.11` 运行了一个 DNS 服务器。容器内的 DNS 请求会被转发到这里。如果是容器名,解析为容器 IP;如果是外部域名 (如 google.com),转发给上游 DNS。 --- ### 配置 DNS 参数 -如果你需要手动配置容器的 DNS(例如使用内网 DNS 服务器),可以在 `docker run` 中使用以下参数: +如果你需要手动配置容器的 DNS (例如使用内网 DNS 服务器),可以在 `docker run` 中使用以下参数: #### 1. --dns @@ -67,7 +69,7 @@ $ docker run -h myweb nginx ### 全局 DNS 配置 -如果希望所有容器都使用特定的 DNS 服务器(而不是继承宿主机),可以修改 `/etc/docker/daemon.json`: +如果希望所有容器都使用特定的 DNS 服务器 (而不是继承宿主机),可以修改 `/etc/docker/daemon.json`: ```json { @@ -84,17 +86,19 @@ $ docker run -h myweb nginx ### 常见问题 -#### Q: 容器无法解析域名 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:容器无法解析域名 **现象**:`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 端口。 -#### Q: 无法通过容器名通信 +#### Q:无法通过容器名通信 **现象**:`ping db` 提示 `bad address 'db'`。**原因**: -- 你可能在使用**默认的 bridge 网络**。默认 bridge 网络**不支持**通过容器名进行 DNS 解析(这是一个历史遗留设计)。 +- 你可能在使用**默认的 bridge 网络**。默认 bridge 网络**不支持**通过容器名进行 DNS 解析 (这是一个历史遗留设计)。 - **解决**:使用自定义网络 (`docker network create ...`)。 --- diff --git a/08_data_network/network/port_mapping.md b/08_data_network/network/port_mapping.md index f3635d5..4cff55b 100644 --- a/08_data_network/network/port_mapping.md +++ b/08_data_network/network/port_mapping.md @@ -1,13 +1,15 @@ ## 外部访问容器 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 为什么要映射端口 -容器运行在自己的隔离网络环境中(通常是 Bridge 模式)。这意味着: -- **容器之间**:可以通过 IP 或容器名(自定义网络)互通。 +容器运行在自己的隔离网络环境中 (通常是 Bridge 模式)。这意味着: +- **容器之间**:可以通过 IP 或容器名 (自定义网络) 互通。 - **宿主机访问容器**:可以通过容器 IP 访问。 - **外部网络访问容器**:❌ 默认无法直接访问。 -为了让外部(如你的浏览器、其他局域网机器)访问容器内的服务,我们需要将容器的端口**映射**到宿主机的端口。 +为了让外部 (如你的浏览器、其他局域网机器) 访问容器内的服务,我们需要将容器的端口**映射**到宿主机的端口。 ```mermaid flowchart TD @@ -20,7 +22,9 @@ flowchart TD ### 端口映射方式 -#### 1. 指定映射 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。指定映射 Docker 提供了多种方式来指定端口映射,最常用的是 `-p` 参数。 @@ -44,12 +48,12 @@ $ docker run -d -p 8080:80 nginx | `hostPort:containerPort` | 绑定所有 IP (0.0.0.0) 的特定端口 | `-p 8080:80` (默认) | | `containerPort` | 绑定所有 IP 的随机端口 | `-p 80` | -#### 2. 随机映射 +#### 2。随机映射 如果您不关心宿主机使用哪个端口,可以使用随机映射功能。 -使用 `-P` (大写) 参数,Docker 会随机映射 Dockerfile 中 `EXPOSE` 指令暴露的所有端口到宿主机的高端口(49000-49900)。 +使用 `-P` (大写) 参数,Docker 会随机映射 Dockerfile 中 `EXPOSE` 指令暴露的所有端口到宿主机的高端口 (49000-49900)。 ```bash $ docker run -d -P nginx @@ -69,6 +73,8 @@ abc123456 0.0.0.0:49153->80/tcp ### 查看端口映射 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### docker port 我们可以使用 `docker port` 命令来查看当前容器的端口映射规则。 @@ -96,14 +102,16 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web ### 最佳实践与安全 -#### 1. 限制监听 IP +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。限制监听 IP 为了保证服务的安全性,我们应该谨慎选择绑定的 IP 地址。 默认情况下,`-p 8080:80` 会监听 `0.0.0.0:8080`,这意味着任何人只要能连接你的宿主机 IP,就能访问该服务。 -如果不希望对外暴露(例如数据库服务),应绑定到 `127.0.0.1`: +如果不希望对外暴露 (例如数据库服务),应绑定到 `127.0.0.1`: ```bash ## 仅允许本机访问 @@ -111,7 +119,7 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web $ docker run -d -p 127.0.0.1:3306:3306 mysql ``` -#### 2. 避免端口冲突 +#### 2。避免端口冲突 如果宿主机 8080 已经被占用了,容器将无法启动。 @@ -119,9 +127,9 @@ $ docker run -d -p 127.0.0.1:3306:3306 mysql - 更换宿主机端口:`-p 8081:80` - 让 Docker 自动分配:`-p 80` -#### 3. UDP 映射 +#### 3。UDP 映射 -默认是 TCP 协议。如果要映射 UDP 服务(如 DNS, Syslog): +默认是 TCP 协议。如果要映射 UDP 服务 (如 DNS,Syslog): ```bash $ docker run -d -p 53:53/udp dns-server @@ -131,7 +139,7 @@ $ docker run -d -p 53:53/udp dns-server ### 实现原理 -Docker 使用 `docker-proxy` 进程(用户态)或 `iptables` DNAT 规则(内核态)来实现端口转发。 +Docker 使用 `docker-proxy` 进程 (用户态) 或 `iptables` DNAT 规则 (内核态) 来实现端口转发。 当流量到达宿主机端口时,iptables 规则将其目标地址修改为容器 IP 并转发: @@ -141,6 +149,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_buildx/9.1_buildkit.md b/09_buildx/9.1_buildkit.md index 2350623..8ecc1ec 100644 --- a/09_buildx/9.1_buildkit.md +++ b/09_buildx/9.1_buildkit.md @@ -48,7 +48,7 @@ COPY --from=builder /app/dist /app/dist 使用多阶段构建,构建的镜像中只包含了目标文件夹 `dist`,但仍然存在一些问题,当 `package.json` 文件变动时,`RUN npm i && rm -rf ~/.npm` 这一层会重新执行,变更多次后,生成了大量的中间层镜像。 -为解决这个问题,进一步的我们可以设想一个类似 **数据卷** 的功能,在镜像构建时把 `node_modules` 文件夹挂载上去,在构建完成后,这个 `node_modules` 文件夹会自动卸载,实际的镜像中并不包含 `node_modules` 这个文件夹,这样我们就省去了每次获取依赖的时间,大大增加了镜像构建效率,同时也避免了生成了大量的中间层镜像。 +为解决这个问题,进一步的我们可以设想一个类似**数据卷**的功能,在镜像构建时把 `node_modules` 文件夹挂载上去,在构建完成后,这个 `node_modules` 文件夹会自动卸载,实际的镜像中并不包含 `node_modules` 这个文件夹,这样我们就省去了每次获取依赖的时间,大大增加了镜像构建效率,同时也避免了生成了大量的中间层镜像。 `BuildKit` 提供了 `RUN --mount=type=cache` 指令,可以实现上边的设想。 @@ -104,7 +104,7 @@ RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \ #### `RUN --mount=type=bind` -该指令可以将一个镜像(或上一构建阶段)的文件挂载到指定位置。 +该指令可以将一个镜像 (或上一构建阶段) 的文件挂载到指定位置。 ```docker ## syntax=docker/dockerfile:1 @@ -126,7 +126,7 @@ RUN --mount=type=tmpfs,target=/temp \ #### `RUN --mount=type=secret` -该指令可以将一个文件(例如密钥)挂载到指定位置。 +该指令可以将一个文件 (例如密钥) 挂载到指定位置。 ```docker ## syntax=docker/dockerfile:1 diff --git a/09_buildx/9.2_buildx.md b/09_buildx/9.2_buildx.md index 54712d9..e101c32 100644 --- a/09_buildx/9.2_buildx.md +++ b/09_buildx/9.2_buildx.md @@ -1,5 +1,7 @@ ## 9.2 使用 Buildx 构建镜像 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 使用 Buildx 的使用非常直观,绝大多数情况下可以替代 `docker build` 命令。 @@ -12,7 +14,7 @@ $ docker buildx build . => ... ``` -Buildx 使用 [BuildKit 引擎](9.1_buildkit.md) 进行构建,支持许多新的功能,具体参考 [Buildkit](9.1_buildkit.md) 一节。 +Buildx 使用 [BuildKit 引擎](9.1_buildkit.md)进行构建,支持许多新的功能,具体参考 [Buildkit](9.1_buildkit.md) 一节。 #### 使用 `bake` diff --git a/09_buildx/9.3_multi-arch-images.md b/09_buildx/9.3_multi-arch-images.md index 8789138..48eedd0 100644 --- a/09_buildx/9.3_multi-arch-images.md +++ b/09_buildx/9.3_multi-arch-images.md @@ -1,6 +1,6 @@ ## 9.3 构建多种系统架构支持的 Docker 镜像 -Docker 镜像可以支持多种系统架构,这意味着你可以在 `x86_64`、`arm64` 等不同架构的机器上运行同一个镜像。这是通过一个名为 "manifest list"(或称为 "fat manifest")的文件来实现的。 +Docker 镜像可以支持多种系统架构,这意味着你可以在 `x86_64`、`arm64` 等不同架构的机器上运行同一个镜像。这是通过一个名为 “manifest list” (或称为 “fat manifest”) 的文件来实现的。 ### Manifest List 是什么? @@ -79,14 +79,14 @@ $ docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t your-us 在 `Dockerfile` 中,你可以使用一些预定义的构建参数来根据目标平台定制构建过程: -* `TARGETPLATFORM`: 构建镜像的目标平台,例如 `linux/amd64`。 -* `TARGETOS`: 目标平台的操作系统,例如 `linux`。 -* `TARGETARCH`: 目标平台的架构,例如 `amd64`。 -* `TARGETVARIANT`: 目标平台的变种,例如 `v7`。 -* `BUILDPLATFORM`: 构建环境的平台。 -* `BUILDOS`: 构建环境的操作系统。 -* `BUILDARCH`: 构建环境的架构。 -* `BUILDVARIANT`: 构建环境的变种。 +* `TARGETPLATFORM`:构建镜像的目标平台,例如 `linux/amd64`。 +* `TARGETOS`:目标平台的操作系统,例如 `linux`。 +* `TARGETARCH`:目标平台的架构,例如 `amd64`。 +* `TARGETVARIANT`:目标平台的变种,例如 `v7`。 +* `BUILDPLATFORM`:构建环境的平台。 +* `BUILDOS`:构建环境的操作系统。 +* `BUILDARCH`:构建环境的架构。 +* `BUILDVARIANT`:构建环境的变种。 例如,你可以这样编写 `Dockerfile` 来拷贝特定架构的二进制文件: @@ -101,7 +101,7 @@ COPY bin/dist-${TARGETOS}-${TARGETARCH} /dist ENTRYPOINT ["/dist"] ``` -### 使用 `docker manifest`(底层工具) +### 使用 `docker manifest` (底层工具) 除了 `docker buildx`,我们也可以直接操作 Manifest List 来手动组合不同架构的镜像。 diff --git a/09_buildx/README.md b/09_buildx/README.md index eac8939..16b6b0a 100644 --- a/09_buildx/README.md +++ b/09_buildx/README.md @@ -4,6 +4,10 @@ Docker Buildx 是一个 docker CLI 插件,其扩展了 docker 命令,支持 > Buildx 需要 Docker v19.03+。在较新版本中已更常用且功能更完整。 +## 概述 + +总体概述了以下内容。 + ## 本章内容 本章将详细介绍 Docker Buildx 的使用,包括: diff --git a/10_compose/10.1_introduction.md b/10_compose/10.1_introduction.md index dd7d34a..3cc0c60 100644 --- a/10_compose/10.1_introduction.md +++ b/10_compose/10.1_introduction.md @@ -4,11 +4,15 @@ 其代码目前在 [https://github.com/docker/compose](https://github.com/docker/compose) 上开源。 -`Compose` 定位是 「定义和运行多个 Docker 容器的应用(Defining and running multi-container Docker applications)」,其前身是开源项目 Fig。 +`Compose` 定位是 “定义和运行多个 Docker 容器的应用 (Defining and running multi-container Docker applications)”,其前身是开源项目 Fig。 通过第一部分中的介绍,我们知道使用一个 `Dockerfile` 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。 -`Compose` 恰好满足了这样的需求。它允许用户通过一个单独的 `compose.yaml`(历史默认名也常见为 `docker-compose.yml`)模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。 +`Compose` 恰好满足了这样的需求。它允许用户通过一个单独的 `compose.yaml` (历史默认名也常见为 `docker-compose.yml`) 模板文件 (YAML 格式) 来定义一组相关联的应用容器为一个项目 (project)。 + +### 概述 + +总体概述了以下内容。 ### 模板文件规范 diff --git a/10_compose/10.2_install.md b/10_compose/10.2_install.md index 31bdb40..654d760 100644 --- a/10_compose/10.2_install.md +++ b/10_compose/10.2_install.md @@ -12,13 +12,13 @@ Linux 系统请使用以下介绍的方法安装。 ### Linux -在 Linux 上,你可以通过下载 Docker Compose CLI 插件(二进制文件名为 `docker-compose`)来安装。 +在 Linux 上,你可以通过下载 Docker Compose CLI 插件 (二进制文件名为 `docker-compose`) 来安装。 -从 [官方 GitHub Release](https://github.com/docker/compose/releases) 处直接下载编译好的二进制文件即可。 +从[官方 GitHub Release](https://github.com/docker/compose/releases) 处直接下载编译好的二进制文件即可。 > **提示**:版本更新较快,请访问上述链接获取最新版本号,替换下方命令中的版本号。 -例如,在 Linux 64 位系统上直接下载对应的二进制包(以 v5.0.2 为例)。 +例如,在 Linux 64 位系统上直接下载对应的二进制包 (以 v5.0.2 为例)。 ```bash $ DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker} diff --git a/10_compose/10.3_usage.md b/10_compose/10.3_usage.md index f9e5512..19b1ac8 100644 --- a/10_compose/10.3_usage.md +++ b/10_compose/10.3_usage.md @@ -10,7 +10,7 @@ * 项目 (`project`):由一组关联的应用容器组成的一个完整业务单元。 -可见,一个项目可以由多个服务(容器)关联而成,`Compose` 面向项目进行管理。 +可见,一个项目可以由多个服务 (容器) 关联而成,`Compose` 面向项目进行管理。 ### 场景 @@ -52,7 +52,7 @@ CMD ["python", "app.py"] #### compose.yaml -编写 `compose.yaml` 文件,这是 Compose 推荐使用的主模板文件(也兼容 `docker-compose.yml` 等历史文件名)。 +编写 `compose.yaml` 文件,这是 Compose 推荐使用的主模板文件 (也兼容 `docker-compose.yml` 等历史文件名)。 ```yaml services: diff --git a/10_compose/10.4_commands.md b/10_compose/10.4_commands.md index c001c55..c1a271d 100644 --- a/10_compose/10.4_commands.md +++ b/10_compose/10.4_commands.md @@ -16,7 +16,7 @@ docker compose [-f=...] [options] [COMMAND] [ARGS...] ### 命令选项 -* `-f, --file FILE` 指定使用的 Compose 模板文件。默认会自动识别 `compose.yaml`(也兼容 `docker-compose.yml` 等),并且可以多次指定。 +* `-f, --file FILE` 指定使用的 Compose 模板文件。默认会自动识别 `compose.yaml` (也兼容 `docker-compose.yml` 等),并且可以多次指定。 * `-p, --project-name NAME` 指定项目名称,默认将使用所在目录名称作为项目名。 @@ -26,11 +26,13 @@ docker compose [-f=...] [options] [COMMAND] [ARGS...] ### 命令使用说明 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### `build` 格式为 `docker compose build [options] [SERVICE...]`。 -构建(重新构建)项目中的服务容器。 +构建 (重新构建) 项目中的服务容器。 服务容器一旦构建后,将会带上一个标记名,例如对于 web 项目中的一个 db 容器,可能是 web_db。 @@ -40,7 +42,7 @@ docker compose [-f=...] [options] [COMMAND] [ARGS...] * `--force-rm` 删除构建过程中的临时容器。 -* `--no-cache` 构建镜像过程中不使用 cache(这将加长构建过程)。 +* `--no-cache` 构建镜像过程中不使用 cache (这将加长构建过程)。 * `--pull` 始终尝试通过 pull 来获取更新版本的镜像。 @@ -98,9 +100,9 @@ $ docker compose kill -s SIGINT 选项: -* `--protocol=proto` 指定端口协议,tcp(默认值)或者 udp。 +* `--protocol=proto` 指定端口协议,tcp (默认值) 或者 udp。 -* `--index=index` 如果同一服务存在多个容器,指定命令对象容器的序号(默认为 1)。 +* `--index=index` 如果同一服务存在多个容器,指定命令对象容器的序号 (默认为 1)。 #### `ps` @@ -134,13 +136,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` 命令来停止容器。 选项: @@ -216,7 +218,7 @@ $ docker compose scale web=3 db=2 将启动 3 个容器运行 web 服务,2 个容器运行 db 服务。 -> **提示**:部分版本的 Compose 可能不再提供独立的 `scale` 子命令(或不推荐使用)。此时可使用 `docker compose up` 的 `--scale` 选项达到同样效果: +> **提示**:部分版本的 Compose 可能不再提供独立的 `scale` 子命令 (或不推荐使用)。此时可使用 `docker compose up` 的 `--scale` 选项达到同样效果: > > ```bash > $ docker compose up -d --scale web=3 --scale db=2 @@ -226,7 +228,7 @@ $ docker compose scale web=3 db=2 选项: -* `-t, --timeout TIMEOUT` 停止容器时候的超时(默认为 10 秒)。 +* `-t, --timeout TIMEOUT` 停止容器时候的超时 (默认为 10 秒)。 #### `start` @@ -242,7 +244,7 @@ $ docker compose scale web=3 db=2 选项: -* `-t, --timeout TIMEOUT` 停止容器时候的超时(默认为 10 秒)。 +* `-t, --timeout TIMEOUT` 停止容器时候的超时 (默认为 10 秒)。 #### `top` @@ -258,7 +260,7 @@ $ docker compose scale web=3 db=2 格式为 `docker compose up [options] [SERVICE...]`。 -该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。 +该命令十分强大,它将尝试自动完成包括构建镜像,(重新) 创建服务,启动服务,并关联服务相关容器的一系列操作。 链接的服务都将会被自动启动,除非已经处于运行状态。 @@ -270,7 +272,7 @@ $ docker compose scale web=3 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 ` 来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。 选项: @@ -286,7 +288,7 @@ $ docker compose scale web=3 db=2 * `--no-build` 不自动构建缺失的服务镜像。 -* `-t, --timeout TIMEOUT` 停止容器时候的超时(默认为 10 秒)。 +* `-t, --timeout TIMEOUT` 停止容器时候的超时 (默认为 10 秒)。 #### `version` diff --git a/10_compose/10.5_compose_file.md b/10_compose/10.5_compose_file.md index 44c8728..7dae12e 100644 --- a/10_compose/10.5_compose_file.md +++ b/10_compose/10.5_compose_file.md @@ -2,7 +2,7 @@ 模板文件是使用 `Compose` 的核心,涉及到的指令关键字也比较多。但大家不用担心,这里面大部分指令跟 `docker run` 相关参数的含义都是类似的。 -默认的模板文件名称为 `compose.yaml`(也兼容 `docker-compose.yml` 等历史文件名),格式为 YAML。 +默认的模板文件名称为 `compose.yaml` (也兼容 `docker-compose.yml` 等历史文件名),格式为 YAML。 ```yaml services: @@ -14,15 +14,15 @@ services: - "/data" ``` -注意每个服务都必须通过 `image` 指令指定镜像或 `build` 指令(需要 Dockerfile)等来自动构建生成镜像。 +注意每个服务都必须通过 `image` 指令指定镜像或 `build` 指令 (需要 Dockerfile) 等来自动构建生成镜像。 -如果使用 `build` 指令,在 `Dockerfile` 中设置的选项(例如:`CMD`、`EXPOSE`、`VOLUME`、`ENV` 等)将会自动被获取,无需在 Compose 文件中重复设置。 +如果使用 `build` 指令,在 `Dockerfile` 中设置的选项 (例如:`CMD`、`EXPOSE`、`VOLUME`、`ENV` 等) 将会自动被获取,无需在 Compose 文件中重复设置。 下面分别介绍各个指令的用法。 ### `build` -指定 `Dockerfile` 所在文件夹的路径(可以是绝对路径,或者相对 Compose 文件的路径)。`Compose` 将会利用它自动构建这个镜像,然后使用这个镜像。 +指定 `Dockerfile` 所在文件夹的路径 (可以是绝对路径,或者相对 Compose 文件的路径)。`Compose` 将会利用它自动构建这个镜像,然后使用这个镜像。 ```yaml services: @@ -58,7 +58,7 @@ build: ### `cap_add, cap_drop` -指定容器的内核能力(capacity)分配。 +指定容器的内核能力 (capacity) 分配。 例如,让容器拥有所有能力可以指定为: @@ -104,7 +104,7 @@ cgroup_parent: cgroups_1 container_name: docker-web-container ``` ->注意: 指定容器名称后,该服务将无法进行扩展(scale),因为 Docker 不允许多个容器具有相同的名称。 +>注意:指定容器名称后,该服务将无法进行扩展 (scale),因为 Docker 不允许多个容器具有相同的名称。 ### `deploy` @@ -138,7 +138,7 @@ services: image: postgres ``` ->注意:`web` 服务不会等待 `redis` `db` 「完全启动」之后才启动。 +>注意:`web` 服务不会等待 `redis` `db` “完全启动” 之后才启动。 ### `dns` @@ -216,7 +216,7 @@ environment: - SESSION_SECRET ``` -如果变量名称或者值中用到 `true|false,yes|no` 等表达 [布尔](https://yaml.org/type/bool.html) 含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义。这些特定词汇,包括 +如果变量名称或者值中用到 `true|false,yes|no` 等表达[布尔](https://yaml.org/type/bool.html)含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义。这些特定词汇,包括 ```bash y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF @@ -288,7 +288,7 @@ image: a4bc65fd ### `labels` -为容器添加 Docker 元数据(metadata)信息。例如可以为容器添加辅助说明信息。 +为容器添加 Docker 元数据 (metadata) 信息。例如可以为容器添加辅助说明信息。 ```yaml labels: @@ -299,7 +299,7 @@ labels: ### `links` ->注意:不推荐使用该指令。容器之间应通过 Docker 网络(networks)进行互联。 +>注意:不推荐使用该指令。容器之间应通过 Docker 网络 (networks) 进行互联。 ### `logging` @@ -370,7 +370,7 @@ pid: "host" 暴露端口信息。 -使用宿主端口:容器端口 `(HOST:CONTAINER)` 格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。 +使用宿主端口:容器端口 `(HOST:CONTAINER)` 格式,或者仅仅指定容器的端口 (宿主将会随机选择端口) 都可以。 ```yaml ports: @@ -407,7 +407,7 @@ secrets: ### `security_opt` -指定容器模板标签(label)机制的默认属性(用户、角色、类型、级别等)。例如配置标签的用户名和角色名。 +指定容器模板标签 (label) 机制的默认属性 (用户、角色、类型、级别等)。例如配置标签的用户名和角色名。 ```yaml security_opt: @@ -441,7 +441,7 @@ sysctls: 指定容器的 ulimits 限制值。 -例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制) 和 40000(系统硬限制,只能 root 用户提高)。 +例如,指定最大进程数为 65535,指定文件句柄数为 20000 (软限制,应用可以随时修改,不能超过硬限制) 和 40000 (系统硬限制,只能 root 用户提高)。 ```yaml ulimits: @@ -453,7 +453,7 @@ sysctls: ### `volumes` -数据卷所挂载路径设置。可以设置为宿主机路径(`HOST:CONTAINER`)或者数据卷名称(`VOLUME:CONTAINER`),并且可以设置访问模式 (`HOST:CONTAINER:ro`)。 +数据卷所挂载路径设置。可以设置为宿主机路径 (`HOST:CONTAINER`) 或者数据卷名称 (`VOLUME:CONTAINER`),并且可以设置访问模式 (`HOST:CONTAINER:ro`)。 该指令中路径支持相对路径。 diff --git a/10_compose/10.6_django.md b/10_compose/10.6_django.md index 319a1b9..4c5654d 100644 --- a/10_compose/10.6_django.md +++ b/10_compose/10.6_django.md @@ -6,7 +6,7 @@ ### 架构概览 -在开始之前,先看整体架构(如图 10-1 所示): +在开始之前,先看整体架构 (如图 10-1 所示): ```mermaid flowchart TD @@ -37,7 +37,7 @@ flowchart TD - `web` 服务运行 Django 应用,对外暴露 8000 端口 - `db` 服务运行 PostgreSQL 数据库,只在内部网络可访问 - 两个服务通过 Docker Compose 自动创建的网络相互通信 -- `web` 服务可以通过服务名 `db` 访问数据库(Docker 内置 DNS) +- `web` 服务可以通过服务名 `db` 访问数据库 (Docker 内置 DNS) ### 准备工作 @@ -51,6 +51,8 @@ $ mkdir django-docker && cd django-docker ### 步骤 1:创建 Dockerfile +如下代码块所示,展示了相关示例: + ```docker FROM python:3.12-slim @@ -89,6 +91,8 @@ COPY . /code/ ### 步骤 2:创建 requirements.txt +如下代码块所示,展示了相关示例: + ```txt Django>=5.0,<6.0 psycopg[binary]>=3.1,<4.0 @@ -144,7 +148,7 @@ volumes: #### db 服务 -db 服务 配置如下: +db 服务配置如下: ```yaml db: @@ -164,7 +168,7 @@ db: #### web 服务 -web 服务 配置如下: +web 服务配置如下: ```yaml web: @@ -255,7 +259,7 @@ $ docker compose up ``` 你会看到: -1. 首先构建 web 镜像(第一次运行) +1. 首先构建 web 镜像 (第一次运行) 2. 启动 db 服务,等待健康检查通过 3. 启动 web 服务 @@ -294,9 +298,11 @@ $ docker compose exec db psql -U django_user -d django_db ### 常见问题排查 -#### Q1: 数据库连接失败 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: -**错误信息**:`django.db.utils.OperationalError: could not connect to server`**可能原因与解决方案**: +#### Q1:数据库连接失败 + +**错误信息**:`django.db.utils.OperationalError: could not connect to server` **可能原因与解决方案**: | 原因 | 解决方案 | |------|---------| @@ -311,7 +317,7 @@ $ docker compose ps $ docker compose logs db ``` -#### Q2: 代码修改没有生效 +#### Q2:代码修改没有生效 **可能原因**: @@ -319,7 +325,7 @@ $ docker compose logs db 2. **Volume 挂载问题**:检查 `compose.yaml` 中的 volumes 配置 3. **缓存问题**:尝试 `docker compose restart web` -#### Q3: 权限问题(Linux) +#### Q3:权限问题 运行以下命令: diff --git a/10_compose/10.7_rails.md b/10_compose/10.7_rails.md index da81da4..92a27e6 100644 --- a/10_compose/10.7_rails.md +++ b/10_compose/10.7_rails.md @@ -45,6 +45,8 @@ $ mkdir rails-docker && cd rails-docker ### 步骤 1:创建 Dockerfile +如下代码块所示,展示了相关示例: + ```docker FROM ruby:3.2 @@ -143,7 +145,7 @@ $ docker compose run --rm web rails new . --force --database=postgresql --skip-b - `--rm`:执行后删除临时容器 - `--force`:覆盖已存在的文件 - `--database=postgresql`:配置使用 PostgreSQL -- `--skip-bundle`:暂不安装依赖(稍后统一安装) +- `--skip-bundle`:暂不安装依赖 (稍后统一安装) 生成的目录结构: @@ -249,7 +251,9 @@ $ docker compose exec web bash ### 常见问题 -#### Q: 数据库连接失败 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### Q:数据库连接失败 检查 `DATABASE_URL` 环境变量格式是否正确,确保 db 服务已启动: @@ -258,7 +262,7 @@ $ docker compose ps $ docker compose logs db ``` -#### Q: server.pid 文件导致启动失败 +#### Q:server.pid 文件导致启动失败 错误信息:`A server is already running` @@ -268,7 +272,7 @@ $ docker compose logs db $ docker compose exec web rm -f tmp/pids/server.pid ``` -#### Q: Gem 安装失败 +#### Q:Gem 安装失败 可能需要更新 bundler 或清理缓存: diff --git a/10_compose/10.8_wordpress.md b/10_compose/10.8_wordpress.md index 340d35c..e320fe5 100644 --- a/10_compose/10.8_wordpress.md +++ b/10_compose/10.8_wordpress.md @@ -1,11 +1,13 @@ ## 10.8 实战 WordPress -WordPress 是全球最流行的内容管理系统(CMS)。使用 Docker Compose 可以在几分钟内搭建一个包含数据库、Web 服务和持久化存储的生产级 WordPress 环境。 +WordPress 是全球最流行的内容管理系统 (CMS)。使用 Docker Compose 可以在几分钟内搭建一个包含数据库、Web 服务和持久化存储的生产级 WordPress 环境。 --- ### 项目结构 +如下代码块所示,展示了相关示例: + ``` wordpress/ ├── compose.yaml @@ -79,7 +81,9 @@ networks: ### 配置文件详解 -#### 1. 环境变量(.env) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。环境变量 (。env) 为了安全,不要在 `compose.yaml` 中直接写密码。创建 `.env` 文件: @@ -90,15 +94,15 @@ DB_PASSWORD=somestronguserpassword Compose 会自动读取此同级目录下的文件。 -#### 2. 数据持久化 +#### 2。数据持久化 我们定义了两个命名卷: -- `db_data`: 确保 MySQL 容器重建后数据不丢失 -- `wp_data`: 保存 WordPress 的核心文件、插件、主题和上传的媒体文件 +- `db_data`:确保 MySQL 容器重建后数据不丢失 +- `wp_data`:保存 WordPress 的核心文件、插件、主题和上传的媒体文件 -#### 3. PHP 配置优化 +#### 3。PHP 配置优化 -默认的 WordPress 镜像上传文件限制较小(通常 2MB)。创建 `uploads.ini`: +默认的 WordPress 镜像上传文件限制较小 (通常 2MB)。创建 `uploads.ini`: ```ini file_uploads = On @@ -131,7 +135,9 @@ $ docker compose logs -f ### 生产环境最佳实践 -#### 1. 数据库备份 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。数据库备份 不要只依赖 Volume。建议定期备份数据库: @@ -161,11 +167,11 @@ $ docker exec wordpress_db mysqldump -u wordpress -pwordpress wordpress > backup - wp_net ``` -#### 2. 使用 Nginx 反向代理 +#### 2。使用 Nginx 反向代理 在生产环境中,不要直接暴露 WordPress 端口,而是通过 Nginx 进行反向代理并配置 SSL。 -#### 3. 使用 Redis 缓存 +#### 3。使用 Redis 缓存 WordPress 支持 Redis 缓存以提高性能。 @@ -187,15 +193,17 @@ WordPress 支持 Redis 缓存以提高性能。 ### 常见问题 -#### Q: 数据库连接错误 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: -**现象**:访问页面显示 "Error establishing a database connection"。**排查**: +#### Q:数据库连接错误 + +**现象**:访问页面显示 “Error establishing a database connection”。**排查**: 1. 检查 `docker compose logs wordpress` 2. 确认 `.env` 中的密码与 YAML 文件引用一致 -3. 确认 `WORDPRESS_DB_HOST` 也是 `db`(服务名) +3. 确认 `WORDPRESS_DB_HOST` 也是 `db` (服务名) 4. MySQL 8.0 可能需要几秒钟启动,WordPress 会自动重试,稍等片刻即可。 -#### Q: 无法上传大文件 +#### Q:无法上传大文件 **解决**:确保挂载了 `uploads.ini` 配置,并且重启了容器: ```bash diff --git a/10_compose/README.md b/10_compose/README.md index a11a67f..c150175 100644 --- a/10_compose/README.md +++ b/10_compose/README.md @@ -1,6 +1,6 @@ # 第十章 Docker Compose -`Docker Compose` 是 Docker 官方编排(Orchestration)项目之一,负责快速的部署分布式应用。 +`Docker Compose` 是 Docker 官方编排 (Orchestration) 项目之一,负责快速的部署分布式应用。 本章将介绍 `Compose` 项目情况以及安装和使用。 diff --git a/11_ops/README.md b/11_ops/README.md index 11ffc23..a833e41 100644 --- a/11_ops/README.md +++ b/11_ops/README.md @@ -1,4 +1,4 @@ -# 第十一章 运维管理 +# 第十一章运维管理 本章将介绍 Docker 的运维管理,包括监控、日志与安全。 diff --git a/11_ops/logs/README.md b/11_ops/logs/README.md index b27a7ba..f53f973 100644 --- a/11_ops/logs/README.md +++ b/11_ops/logs/README.md @@ -4,23 +4,23 @@ ## Docker 日志驱动 -Docker 提供了多种日志驱动(Log Driver)机制,允许我们将容器日志转发到不同的后端。 +Docker 提供了多种日志驱动 (Log Driver) 机制,允许我们将容器日志转发到不同的后端。 常见的日志驱动包括: -* `json-file`: 默认驱动,将日志以 JSON 格式写入本地文件。 -* `syslog`: 将日志转发到 syslog 服务器。 -* `journald`: 将日志写入 systemd journal。 -* `fluentd`: 将日志转发到 fluentd 收集器。 -* `gelf`: 支持 GELF 协议的日志后端(如 Graylog)。 -* `awslogs`: 发送到 Amazon CloudWatch Logs。 +* `json-file`:默认驱动,将日志以 JSON 格式写入本地文件。 +* `syslog`:将日志转发到 syslog 服务器。 +* `journald`:将日志写入 systemd journal。 +* `fluentd`:将日志转发到 fluentd 收集器。 +* `gelf`:支持 GELF 协议的日志后端 (如 Graylog)。 +* `awslogs`:发送到 Amazon CloudWatch Logs。 ## 日志管理方案 对于大规模的容器集群,我们通常会采用 EFK (Elasticsearch + Fluentd + Kibana) 或 ELK (Elasticsearch + Logstash + Kibana) 方案。 -* **Elasticsearch**: 负责日志的存储和全文检索。 -* **Fluentd/Logstash**: 负责日志的采集、过滤和转发。 -* **Kibana**: 负责日志的可视化展示。 +* **Elasticsearch**:负责日志的存储和全文检索。 +* **Fluentd/Logstash**:负责日志的采集、过滤和转发。 +* **Kibana**:负责日志的可视化展示。 本章将介绍如何使用 EFK 方案来处理 Docker 容器日志。 diff --git a/11_ops/logs/elk.md b/11_ops/logs/elk.md index f8f5078..8373b16 100644 --- a/11_ops/logs/elk.md +++ b/11_ops/logs/elk.md @@ -1,23 +1,23 @@ ## ELK/EFK 堆栈 -ELK (Elasticsearch, Logstash, Kibana) 是目前业界最流行的开源日志解决方案。而在容器领域,由于 Fluentd 更加轻量级且对容器支持更好,EFK (Elasticsearch, Fluentd, Kibana) 组合也变得非常流行。 +ELK (Elasticsearch,Logstash,Kibana) 是目前业界最流行的开源日志解决方案。而在容器领域,由于 Fluentd 更加轻量级且对容器支持更好,EFK (Elasticsearch,Fluentd,Kibana) 组合也变得非常流行。 ### 方案架构 我们将采用以下架构: -1. **Docker Container**: 容器将日志输出到标准输出 (stdout/stderr)。 -2. **Fluentd**: 作为 Docker 的 Logging Driver 或运行为守护容器,收集容器日志。 -3. **Elasticsearch**: 存储从 Fluentd 接收到的日志数据。 -4. **Kibana**: 从 Elasticsearch 读取数据并进行可视化展示。 +1. **Docker Container**:容器将日志输出到标准输出 (stdout/stderr)。 +2. **Fluentd**:作为 Docker 的 Logging Driver 或运行为守护容器,收集容器日志。 +3. **Elasticsearch**:存储从 Fluentd 接收到的日志数据。 +4. **Kibana**:从 Elasticsearch 读取数据并进行可视化展示。 ### 部署流程 我们将使用 Docker Compose 来一键部署整个日志堆栈。 -#### 1. 编写 Compose 文件 +#### 1。编写 Compose 文件 -1. 编写 `compose.yaml`(或 `docker-compose.yml`)配置如下: +1. 编写 `compose.yaml` (或 `docker-compose.yml`) 配置如下: ```yaml services: @@ -71,9 +71,9 @@ networks: logging: ``` -#### 2. 配置 Fluentd +#### 2。配置 Fluentd -创建 `fluentd/conf/fluent.conf`: +创建 `fluentd/conf/fluent.conf`: ```ini @@ -102,9 +102,9 @@ networks: ``` -#### 3. 配置应用容器使用 fluentd 驱动 +#### 3。配置应用容器使用 fluentd 驱动 -启动一个测试容器,指定日志驱动为 `fluentd`: +启动一个测试容器,指定日志驱动为 `fluentd`: ```bash docker run -d \ @@ -115,9 +115,9 @@ docker run -d \ nginx ``` -**注意**: 确保 `fluentd` 容器已经启动并监听在 `localhost:24224`。在生产环境中,如果你是在不同机器上,需要将 `localhost` 替换为运行 fluentd 的主机 IP。 +**注意**:确保 `fluentd` 容器已经启动并监听在 `localhost:24224`。在生产环境中,如果你是在不同机器上,需要将 `localhost` 替换为运行 fluentd 的主机 IP。 -#### 4. 在 Kibana 中查看日志 +#### 4。在 Kibana 中查看日志 1. 访问 `http://localhost:5601`。 2. 进入 **Management**->**Kibana**->**Index Patterns**。 diff --git a/11_ops/monitor/README.md b/11_ops/monitor/README.md index 502fd63..6e2cbc0 100644 --- a/11_ops/monitor/README.md +++ b/11_ops/monitor/README.md @@ -4,13 +4,17 @@ 在传统架构中,我们通常关注主机的 CPU、内存、磁盘 IO 等指标。而在容器环境下,除了主机层面的监控,我们更关注容器级别的资源使用情况、服务的运行状态以及编排系统的健康状况。 +## 概述 + +总体概述了以下内容。 + ## 常见的监控方案 目前主流的容器监控方案包括: -* **cAdvisor**: Google 开源的容器资源监控工具,Docker 原生支持。 -* **Prometheus**: CNCF 毕业项目,云原生时代最流行的监控系统。 -* **Grafana**: 强大的可视化平台,常与 Prometheus 配合使用。 -* **ELK/EFK Stack**: 主要用于日志管理,但也能提供一定的监控能力。 +* **cAdvisor**:Google 开源的容器资源监控工具,Docker 原生支持。 +* **Prometheus**:CNCF 毕业项目,云原生时代最流行的监控系统。 +* **Grafana**:强大的可视化平台,常与 Prometheus 配合使用。 +* **ELK/EFK Stack**:主要用于日志管理,但也能提供一定的监控能力。 本章将重点介绍如何使用 Prometheus 和 Grafana 搭建一套完整的容器监控系统。 diff --git a/11_ops/monitor/prometheus.md b/11_ops/monitor/prometheus.md index 05ba04b..0ae9588 100644 --- a/11_ops/monitor/prometheus.md +++ b/11_ops/monitor/prometheus.md @@ -8,18 +8,18 @@ Prometheus 和 Grafana 是目前最流行的开源监控组合,前者负责数 Prometheus 的主要组件包括: -* **Prometheus Server**: 核心组件,负责收集和存储时间序列数据。 -* **Exporters**: 负责向 Prometheus 暴露监控数据(如 Node Exporter, cAdvisor)。 -* **Alertmanager**: 处理报警发送。 -* **Pushgateway**: 用于支持短生命周期的 Job 推送数据。 +* **Prometheus Server**:核心组件,负责收集和存储时间序列数据。 +* **Exporters**:负责向 Prometheus 暴露监控数据 (如 Node Exporter,cAdvisor)。 +* **Alertmanager**:处理报警发送。 +* **Pushgateway**:用于支持短生命周期的 Job 推送数据。 ### 快速部署 我们可以使用 Docker Compose 快速部署一套 Prometheus + Grafana 监控环境。 -#### 1. 准备配置文件 +#### 1。准备配置文件 -创建 `prometheus.yml`: +创建 `prometheus.yml`: ```yaml global: @@ -39,9 +39,9 @@ scrape_configs: - targets: ['cadvisor:8080'] ``` -#### 2. 编写 Docker Compose 文件 +#### 2。编写 Docker Compose 文件 -创建 `compose.yaml`(或 `docker-compose.yml`): +创建 `compose.yaml` (或 `docker-compose.yml`): ```yaml services: @@ -88,7 +88,7 @@ networks: monitoring: ``` -#### 3. 启动服务 +#### 3。启动服务 运行以下命令: @@ -99,11 +99,11 @@ $ docker compose up -d 启动后,访问以下地址: * Prometheus: `http://localhost:9090` -* Grafana: `http://localhost:3000` (默认账号密码: admin/admin) +* Grafana:`http://localhost:3000` (默认账号密码:admin/admin) ### 配置 Grafana 面板 1. 在 Grafana 中添加 Prometheus 数据源,URL 填写 `http://prometheus:9090`。 -2. 导入现成的 Dashboard 模板,例如 [Node Exporter Full](https://grafana.com/grafana/dashboards/1860) (ID: 1860) 和 [Docker Container](https://grafana.com/grafana/dashboards/193) (ID: 193)。 +2. 导入现成的 Dashboard 模板,例如 [Node Exporter Full](https://grafana.com/grafana/dashboards/1860) (ID:1860) 和 [Docker Container](https://grafana.com/grafana/dashboards/193) (ID:193)。 这样,你就拥有了一个直观的容器监控大屏。 diff --git a/11_ops/security/README.md b/11_ops/security/README.md index 5c7155a..63f8f1b 100644 --- a/11_ops/security/README.md +++ b/11_ops/security/README.md @@ -28,7 +28,9 @@ flowchart LR ## 核心安全机制 -### 1. 命名空间(Namespace) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +### 1。命名空间 提供进程、网络、文件系统等资源的隔离: @@ -41,9 +43,9 @@ flowchart LR | IPC | 进程通信 | 隔离共享内存 | | UTS | 主机名 | 独立主机名 | -详见 [命名空间](../../14_implementation/14.2_namespace.md) 章节。 +详见[命名空间](../../14_implementation/14.2_namespace.md)章节。 -### 2. 控制组(Cgroups) +### 2。控制组 限制容器的资源使用,防止资源耗尽攻击: @@ -61,7 +63,7 @@ $ docker run --cpus=1.5 myapp $ docker run --device-write-bps /dev/sda:10mb myapp ``` -### 3. 能力机制(Capabilities) +### 3。能力机制 Linux 将 root 权限拆分为多个细粒度的能力。Docker 默认禁用危险能力: @@ -87,6 +89,8 @@ $ docker exec myapp cat /proc/1/status | grep Cap ## 镜像安全 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 使用可信镜像 运行以下命令: @@ -149,7 +153,9 @@ $ cosign verify --key cosign.pub $IMAGE ## 运行时安全 -### 1. 非 root 用户运行 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +### 1。非 root 用户运行 > 笔者强调:这是最重要的安全实践之一。 @@ -179,7 +185,7 @@ CMD ["node", "server.js"] $ docker run -u 1001:1001 myapp ``` -### 2. 只读文件系统 +### 2。只读文件系统 运行以下命令: @@ -193,7 +199,7 @@ $ docker run --read-only myapp $ docker run --read-only --tmpfs /tmp --tmpfs /var/run myapp ``` -### 3. 禁用特权模式 +### 3。禁用特权模式 运行以下命令: @@ -207,7 +213,7 @@ $ docker run --privileged myapp $ docker run --cap-add=SYS_TIME myapp ``` -### 4. 限制资源 +### 4。限制资源 运行以下命令: @@ -220,7 +226,7 @@ $ docker run \ myapp ``` -### 5. 网络隔离 +### 5。网络隔离 运行以下命令: @@ -239,7 +245,9 @@ $ docker run --network=isolated_net myapp ## Dockerfile 安全实践 -### 1. 使用精简基础镜像 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +### 1。使用精简基础镜像 Dockerfile 内容如下: @@ -255,7 +263,7 @@ FROM node:22 # ~1GB FROM ubuntu:24.04 # ~78MB ``` -### 2. 多阶段构建 +### 2。多阶段构建 Dockerfile 内容如下: @@ -275,7 +283,7 @@ USER node CMD ["node", "/app/server.js"] ``` -### 3. 不存储敏感信息 +### 3。不存储敏感信息 Dockerfile 内容如下: @@ -292,7 +300,7 @@ COPY .env /app/ ... ``` -### 4. 固定依赖版本 +### 4。固定依赖版本 Dockerfile 内容如下: @@ -329,6 +337,8 @@ RUN apk add curl ## 高级安全方案 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### Seccomp 系统调用过滤 限制容器可以使用的系统调用: @@ -345,7 +355,7 @@ $ docker run --security-opt seccomp=/path/to/profile.json myapp $ docker run --security-opt apparmor=docker-default myapp ``` -### 安全容器(gVisor / Kata) +### 安全容器 (gVisor / Kata) 需要更强隔离时: @@ -361,18 +371,18 @@ $ docker run --runtime=runsc myapp 随着软件供应链攻击日益频繁,仅保障运行时安全已不足够。 -### 1. SBOM(软件物料清单) +### 1。SBOM (软件物料清单) SBOM 类似于食品的配料表,列出了容器镜像中包含的所有软件包及其版本。 -- **生成 SBOM**: 使用 `docker buildx build --sbom` 或 `docker scout sbom`。 -- **管理 SBOM**: 确保持续监控 SBOM 中的组件是否存在新披露的漏洞。 +- **生成 SBOM**:使用 `docker buildx build --sbom` 或 `docker scout sbom`。 +- **管理 SBOM**:确保持续监控 SBOM 中的组件是否存在新披露的漏洞。 -### 2. 镜像签名(Sigstore / Notary v2) +### 2。镜像签名 (Sigstore / Notary v2) 确保镜像在构建后未被篡改,且确实来自可信的发布者。 -- **Cosign**: Sigstore 项目的一部分,用于签署和验证容器镜像。 +- **Cosign**:Sigstore 项目的一部分,用于签署和验证容器镜像。 ```bash ## 使用有写权限的仓库地址 $ export IMAGE=<你的仓库地址>/myimage:tag diff --git a/11_ops/security/control_group.md b/11_ops/security/control_group.md index 29bfec5..61b766c 100644 --- a/11_ops/security/control_group.md +++ b/11_ops/security/control_group.md @@ -4,6 +4,6 @@ 它提供了很多有用的特性;以及确保各个容器可以公平地分享主机的内存、CPU、磁盘 IO 等资源;当然,更重要的是,控制组确保了当容器内的资源使用产生压力时不会连累主机系统。 -尽管控制组不负责隔离容器之间相互访问、处理数据和进程,它在防止拒绝服务(DDOS)攻击方面是必不可少的。尤其是在多用户的平台(比如公有或私有的 PaaS)上,控制组十分重要。例如,当某些应用程序表现异常的时候,可以保证一致地正常运行和性能。 +尽管控制组不负责隔离容器之间相互访问、处理数据和进程,它在防止拒绝服务 (DDOS) 攻击方面是必不可少的。尤其是在多用户的平台 (比如公有或私有的 PaaS) 上,控制组十分重要。例如,当某些应用程序表现异常的时候,可以保证一致地正常运行和性能。 控制组机制始于 2006 年,内核从 2.6.24 版本开始被引入。 diff --git a/11_ops/security/daemon_sec.md b/11_ops/security/daemon_sec.md index a8f4251..f107bfc 100644 --- a/11_ops/security/daemon_sec.md +++ b/11_ops/security/daemon_sec.md @@ -1,19 +1,19 @@ -## Docker服务端的防护 +## Docker 服务端的防护 运行一个容器或应用程序的核心是通过 Docker 服务端。Docker 服务的运行目前需要 root 权限,因此其安全性十分关键。 -首先,确保只有可信的用户才可以访问 Docker 服务。Docker 允许用户在主机和容器间共享文件夹,同时不需要限制容器的访问权限,这就容易让容器突破资源限制。例如,恶意用户启动容器的时候将主机的根目录`/`映射到容器的 `/host` 目录中,那么容器理论上就可以对主机的文件系统进行任意修改了。这听起来很疯狂?但是事实上几乎所有虚拟化系统都允许类似的资源共享,而没法禁止用户共享主机根文件系统到虚拟机系统。 +首先,确保只有可信的用户才可以访问 Docker 服务。Docker 允许用户在主机和容器间共享文件夹,同时不需要限制容器的访问权限,这就容易让容器突破资源限制。例如,恶意用户启动容器的时候将主机的根目录 `/` 映射到容器的 `/host` 目录中,那么容器理论上就可以对主机的文件系统进行任意修改了。这听起来很疯狂?但是事实上几乎所有虚拟化系统都允许类似的资源共享,而没法禁止用户共享主机根文件系统到虚拟机系统。 -这将会造成很严重的安全后果。因此,当提供容器创建服务时(例如通过一个 web 服务器),要更加注意进行参数的安全检查,防止恶意的用户用特定参数来创建一些破坏性的容器。 +这将会造成很严重的安全后果。因此,当提供容器创建服务时 (例如通过一个 web 服务器),要更加注意进行参数的安全检查,防止恶意的用户用特定参数来创建一些破坏性的容器。 -为了加强对服务端的保护,Docker 的 REST API(客户端用来跟服务端通信)在 0.5.2 之后使用本地的 Unix 套接字机制替代了原先绑定在 127.0.0.1 上的 TCP 套接字,因为后者容易遭受跨站脚本攻击。现在用户使用 Unix 权限检查来加强套接字的访问安全。 +为了加强对服务端的保护,Docker 的 REST API (客户端用来跟服务端通信) 在 0.5.2 之后使用本地的 Unix 套接字机制替代了原先绑定在 127.0.0.1 上的 TCP 套接字,因为后者容易遭受跨站脚本攻击。现在用户使用 Unix 权限检查来加强套接字的访问安全。 -用户仍可以利用 HTTP 提供 REST API 访问。建议使用安全机制,确保只有可信的网络或 VPN,或证书保护机制(例如受保护的 stunnel 和 ssl 认证)下的访问可以进行。此外,还可以使用 [ HTTPS 和证书](https://docs.docker.com/engine/security/https/) 来加强保护。 +用户仍可以利用 HTTP 提供 REST API 访问。建议使用安全机制,确保只有可信的网络或 VPN,或证书保护机制 (例如受保护的 stunnel 和 ssl 认证) 下的访问可以进行。此外,还可以使用 [HTTPS 和证书](https://docs.docker.com/engine/security/https/)来加强保护。 最近改进的 Linux 命名空间机制将可以实现使用非 root 用户来运行全功能的容器。这将从根本上解决了容器和主机之间共享文件系统而引起的安全问题。 终极目标是改进 2 个重要的安全特性: -* 将容器的 root 用户 [映射到本地主机上的非 root 用户](https://docs.docker.com/engine/security/userns-remap/),减轻容器和主机之间因权限提升而引起的安全问题; -* 允许 Docker 服务端在 [非 root 权限(rootless 模式)](https://docs.docker.com/engine/security/rootless/) 下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程将只允许在限定范围内进行操作,例如仅仅负责虚拟网络设定或文件系统管理、配置操作等。 +* 将容器的 root 用户[映射到本地主机上的非 root 用户](https://docs.docker.com/engine/security/userns-remap/),减轻容器和主机之间因权限提升而引起的安全问题; +* 允许 Docker 服务端在[非 root 权限 (rootless 模式)](https://docs.docker.com/engine/security/rootless/) 下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程将只允许在限定范围内进行操作,例如仅仅负责虚拟网络设定或文件系统管理、配置操作等。 -最后,建议采用专用的服务器来运行 Docker 和相关的管理服务(例如管理服务比如 ssh 监控和进程监控、管理工具 nrpe、collectd 等)。其它的业务服务都放到容器中去运行。 +最后,建议采用专用的服务器来运行 Docker 和相关的管理服务 (例如管理服务比如 ssh 监控和进程监控、管理工具 nrpe、collectd 等)。其它的业务服务都放到容器中去运行。 diff --git a/11_ops/security/kernel_capability.md b/11_ops/security/kernel_capability.md index 72c2db6..18fe965 100644 --- a/11_ops/security/kernel_capability.md +++ b/11_ops/security/kernel_capability.md @@ -1,22 +1,22 @@ ## 内核能力机制 -Docker 利用 Linux 的能力机制(Capabilities)来限制容器的权限,从而提高系统的安全性。 +Docker 利用 Linux 的能力机制 (Capabilities) 来限制容器的权限,从而提高系统的安全性。 -[能力机制(Capability)](https://man7.org/linux/man-pages/man7/capabilities.7.html) 是 Linux 内核一个强大的特性,可以提供细粒度的权限访问控制。 +[能力机制 (Capability)](https://man7.org/linux/man-pages/man7/capabilities.7.html) 是 Linux 内核一个强大的特性,可以提供细粒度的权限访问控制。 Linux 内核自 2.2 版本起就支持能力机制,它将权限划分为更加细粒度的操作能力,既可以作用在进程上,也可以作用在文件上。 例如,一个 Web 服务进程只需要绑定一个低于 1024 的端口的权限,并不需要 root 权限。那么它只需要被授权 `net_bind_service` 能力即可。此外,还有很多其他的类似能力来避免进程获取 root 权限。 默认情况下,Docker 启动的容器被严格限制只允许使用内核的一部分能力。 -使用能力机制对加强 Docker 容器的安全有很多好处。通常,在服务器上会运行一堆需要特权权限的进程,包括有 ssh、cron、syslogd、硬件管理工具模块(例如负载模块)、网络配置工具等等。容器跟这些进程是不同的,因为几乎所有的特权进程都由容器以外的支持系统来进行管理。 -* ssh 访问被主机上ssh服务来管理; +使用能力机制对加强 Docker 容器的安全有很多好处。通常,在服务器上会运行一堆需要特权权限的进程,包括有 ssh、cron、syslogd、硬件管理工具模块 (例如负载模块)、网络配置工具等等。容器跟这些进程是不同的,因为几乎所有的特权进程都由容器以外的支持系统来进行管理。 +* ssh 访问被主机上 ssh 服务来管理; * cron 通常应该作为用户进程执行,权限交给使用它服务的应用来处理; * 日志系统可由 Docker 或第三方服务管理; * 硬件管理无关紧要,容器中也就无需执行 udevd 以及类似服务; * 网络管理也都在主机上设置,除非特殊需求,容器不需要对网络进行配置。 -从上面的例子可以看出,大部分情况下,容器并不需要“真正的” root 权限,容器只需要少数的能力即可。为了加强安全,容器可以禁用一些没必要的权限。 +从上面的例子可以看出,大部分情况下,容器并不需要 “真正的” root 权限,容器只需要少数的能力即可。为了加强安全,容器可以禁用一些没必要的权限。 * 完全禁止任何 mount 操作; * 禁止直接访问本地主机的套接字; * 禁止访问一些文件系统的操作,比如创建新的设备、修改文件属性等; @@ -24,5 +24,5 @@ Linux 内核自 2.2 版本起就支持能力机制,它将权限划分为更加 这样,就算攻击者在容器中取得了 root 权限,也不能获得本地主机的较高权限,能进行的破坏也有限。 -默认情况下,Docker采用 [白名单](https://github.com/moby/moby/blob/master/oci/caps/defaults.go) 机制,禁用必需功能之外的其它权限。 +默认情况下,Docker 采用[白名单](https://github.com/moby/moby/blob/master/oci/caps/defaults.go)机制,禁用必需功能之外的其它权限。 当然,用户也可以根据自身需求来为 Docker 容器启用额外的权限。 diff --git a/11_ops/security/kernel_ns.md b/11_ops/security/kernel_ns.md index 5dda6a2..a26ffa1 100644 --- a/11_ops/security/kernel_ns.md +++ b/11_ops/security/kernel_ns.md @@ -1,18 +1,18 @@ ## 内核命名空间 -命名空间(Namespace)是 Linux 容器隔离的基础,它确保了容器内的进程无法干扰主机或其他容器。 +命名空间 (Namespace) 是 Linux 容器隔离的基础,它确保了容器内的进程无法干扰主机或其他容器。 Docker 容器和 LXC 容器很相似,所提供的安全特性也差不多。当用 `docker run` 启动一个容器时,在后台 Docker 为容器创建了一个独立的命名空间和控制组集合。 命名空间提供了最基础也是最直接的隔离,在容器中运行的进程不会被运行在主机上的进程和其它容器发现和作用。 -每个容器都有自己独有的网络栈,意味着它们不能访问其他容器的 sockets 或接口。不过,如果主机系统上做了相应的设置,容器可以像跟主机交互一样的和其他容器交互。当指定公共端口或使用 links 来连接 2 个容器时,容器就可以相互通信了(可以根据配置来限制通信的策略)。 +每个容器都有自己独有的网络栈,意味着它们不能访问其他容器的 sockets 或接口。不过,如果主机系统上做了相应的设置,容器可以像跟主机交互一样的和其他容器交互。当指定公共端口或使用 links 来连接 2 个容器时,容器就可以相互通信了 (可以根据配置来限制通信的策略)。 从网络架构的角度来看,所有的容器通过本地主机的网桥接口相互通信,就像物理机器通过物理交换机通信一样。 那么,内核中实现命名空间和私有网络的代码是否足够成熟? -内核命名空间从 2.6.15 版本(2008 年 7 月发布)之后被引入,数年间,这些机制的可靠性在诸多大型生产系统中被实践验证。 +内核命名空间从 2.6.15 版本 (2008 年 7 月发布) 之后被引入,数年间,这些机制的可靠性在诸多大型生产系统中被实践验证。 实际上,命名空间的想法和设计提出的时间要更早,最初是为了在内核中引入一种机制来实现 [OpenVZ](https://en.wikipedia.org/wiki/OpenVZ) 的特性。 而 OpenVZ 项目早在 2005 年就发布了,其设计和实现都已经十分成熟。 diff --git a/11_ops/security/other_feature.md b/11_ops/security/other_feature.md index 95a7cc9..0ccefa1 100644 --- a/11_ops/security/other_feature.md +++ b/11_ops/security/other_feature.md @@ -2,11 +2,11 @@ 除了上述机制,Linux 内核还提供了一系列安全增强功能,可以进一步保护容器环境。 -除了能力机制之外,还可以利用一些现有的安全机制来增强使用 Docker 的安全性,例如 TOMOYO, AppArmor, Seccomp, SELinux, GRSEC 等。 +除了能力机制之外,还可以利用一些现有的安全机制来增强使用 Docker 的安全性,例如 TOMOYO,AppArmor,Seccomp,SELinux,GRSEC 等。 Docker 当前默认只启用了能力机制。用户可以采用多种方案来加强 Docker 主机的安全,例如: * 在内核中启用 GRSEC 和 PAX,这将增加很多编译和运行时的安全检查;通过地址随机化避免恶意探测等。并且,启用该特性不需要 Docker 进行任何配置。 * 使用一些有增强安全特性的容器模板,比如带 AppArmor 的模板和 Redhat 带 SELinux 策略的模板。这些模板提供了额外的安全特性。 * 用户可以自定义访问控制机制来定制安全策略。 -跟其它添加到 Docker 容器的第三方工具一样(比如网络拓扑和文件系统共享),有很多类似的机制,在不改变 Docker 内核情况下就可以加固现有的容器。 +跟其它添加到 Docker 容器的第三方工具一样 (比如网络拓扑和文件系统共享),有很多类似的机制,在不改变 Docker 内核情况下就可以加固现有的容器。 diff --git a/11_ops/security/summary.md b/11_ops/security/summary.md index 6fdea98..31b5a3c 100644 --- a/11_ops/security/summary.md +++ b/11_ops/security/summary.md @@ -4,4 +4,4 @@ Docker 的安全性依赖于多层隔离机制的协同工作,同时需要用 总体来看,Docker 容器还是十分安全的,特别是在容器内不使用 root 权限来运行进程的话。 -另外,用户可以使用现有工具,比如 [Apparmor](https://docs.docker.com/engine/security/apparmor/), [Seccomp](https://docs.docker.com/engine/security/seccomp/), SELinux, GRSEC 来增强安全性;甚至自己在内核中实现更复杂的安全机制。 +另外,用户可以使用现有工具,比如 [Apparmor](https://docs.docker.com/engine/security/apparmor/),[Seccomp](https://docs.docker.com/engine/security/seccomp/),SELinux,GRSEC 来增强安全性;甚至自己在内核中实现更复杂的安全机制。 diff --git a/12_orchestration/README.md b/12_orchestration/README.md index c57b4c2..44b4a1f 100644 --- a/12_orchestration/README.md +++ b/12_orchestration/README.md @@ -1,4 +1,4 @@ -# 第十二章 容器编排 +# 第十二章容器编排 本章将介绍容器编排相关的技术与工具。 diff --git a/12_orchestration/etcd/README.md b/12_orchestration/etcd/README.md index e5664d5..3bffeb6 100644 --- a/12_orchestration/etcd/README.md +++ b/12_orchestration/etcd/README.md @@ -1,3 +1,3 @@ # etcd -`etcd` 是 `CoreOS` 团队发起的一个管理配置信息和服务发现(`Service Discovery`)的项目,在这一章里面,我们将基于 `etcd 3.x` 版本介绍该项目的目标,安装和使用,以及实现的技术。 +`etcd` 是 `CoreOS` 团队发起的一个管理配置信息和服务发现 (`Service Discovery`) 的项目,在这一章里面,我们将基于 `etcd 3.x` 版本介绍该项目的目标,安装和使用,以及实现的技术。 diff --git a/12_orchestration/etcd/cluster.md b/12_orchestration/etcd/cluster.md index 24bd52e..658bcbc 100644 --- a/12_orchestration/etcd/cluster.md +++ b/12_orchestration/etcd/cluster.md @@ -2,7 +2,7 @@ 下面我们使用 [Docker Compose](../../10_compose/README.md) 模拟启动一个 3 节点的 `etcd` 集群。 -编辑 `compose.yaml`(或 `docker-compose.yml`)文件 +编辑 `compose.yaml` (或 `docker-compose.yml`) 文件 ```yaml services: diff --git a/12_orchestration/etcd/etcdctl.md b/12_orchestration/etcd/etcdctl.md index 69549f7..7d2660b 100644 --- a/12_orchestration/etcd/etcdctl.md +++ b/12_orchestration/etcd/etcdctl.md @@ -83,11 +83,11 @@ OPTIONS: ### 数据库操作 -数据库操作围绕对键值和目录的 CRUD (符合 REST 风格的一套操作:Create)完整生命周期的管理。 +数据库操作围绕对键值和目录的 CRUD (符合 REST 风格的一套操作:Create) 完整生命周期的管理。 -etcd 在键的组织上采用了层次化的空间结构(类似于文件系统中目录的概念),用户指定的键可以为单独的名字,如 `testkey`,此时实际上放在根目录 `/` 下面,也可以为指定目录结构,如 `cluster1/node2/testkey`,则将创建相应的目录结构。 +etcd 在键的组织上采用了层次化的空间结构 (类似于文件系统中目录的概念),用户指定的键可以为单独的名字,如 `testkey`,此时实际上放在根目录 `/` 下面,也可以为指定目录结构,如 `cluster1/node2/testkey`,则将创建相应的目录结构。 ->注:CRUD 即 Create, Read, Update, Delete,是符合 REST 风格的一套 API 操作。 +>注:CRUD 即 Create,Read,Update,Delete,是符合 REST 风格的一套 API 操作。 #### put @@ -112,7 +112,7 @@ hello 支持的选项为 -`--sort` 对结果进行排序 +`--sort` 对结果进行排序 `--consistent` 将请求发给主节点,保证获取内容的一致性 @@ -127,6 +127,8 @@ $ etcdctl del testkey ### 非数据库操作 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### watch 监测一个键值的变化,一旦键值发生更新,就会输出最新的值。 diff --git a/12_orchestration/etcd/install.md b/12_orchestration/etcd/install.md index 7e0d810..d7702fd 100644 --- a/12_orchestration/etcd/install.md +++ b/12_orchestration/etcd/install.md @@ -2,7 +2,7 @@ 本节将介绍 etcd 的几种常见安装方式,包括二进制安装、Docker 镜像运行以及在 macOS 上的安装。 -`etcd` 基于 `Go` 语言实现,因此,用户可以从 [项目主页](https://github.com/etcd-io/etcd) 下载源代码自行编译,也可以下载编译好的二进制文件,甚至直接使用制作好的 `Docker` 镜像文件来体验。 +`etcd` 基于 `Go` 语言实现,因此,用户可以从[项目主页](https://github.com/etcd-io/etcd)下载源代码自行编译,也可以下载编译好的二进制文件,甚至直接使用制作好的 `Docker` 镜像文件来体验。 >注意:本章节内容基于 etcd `3.4.x` 版本 @@ -30,7 +30,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/12_orchestration/etcd/intro.md b/12_orchestration/etcd/intro.md index 923fda2..89743b2 100644 --- a/12_orchestration/etcd/intro.md +++ b/12_orchestration/etcd/intro.md @@ -6,7 +6,7 @@ 图 12-5 etcd 项目标识 -`etcd` 是 `CoreOS` 团队于 2013 年 6 月发起的开源项目,它的目标是构建一个高可用的分布式键值(`key-value`)数据库,基于 `Go` 语言实现。我们知道,在分布式系统中,各种服务的配置信息的管理分享,服务的发现是一个很基本同时也是很重要的问题。`CoreOS` 项目就希望基于 `etcd` 来解决这一问题。 +`etcd` 是 `CoreOS` 团队于 2013 年 6 月发起的开源项目,它的目标是构建一个高可用的分布式键值 (`key-value`) 数据库,基于 `Go` 语言实现。我们知道,在分布式系统中,各种服务的配置信息的管理分享,服务的发现是一个很基本同时也是很重要的问题。`CoreOS` 项目就希望基于 `etcd` 来解决这一问题。 `etcd` 目前在 [github.com/etcd-io/etcd](https://github.com/etcd-io/etcd) 进行维护。 diff --git a/12_orchestration/kubectl/README.md b/12_orchestration/kubectl/README.md index c2a4f81..eaf1fdf 100644 --- a/12_orchestration/kubectl/README.md +++ b/12_orchestration/kubectl/README.md @@ -42,7 +42,7 @@ kubectl [command] ## port-forward -将本地端口转发到Pod +将本地端口转发到 Pod ## proxy @@ -70,7 +70,7 @@ kubectl [command] ## api-versions -以 "组/版本" 的格式输出服务端支持的 API 版本 +以 “组/版本” 的格式输出服务端支持的 API 版本 ## version diff --git a/12_orchestration/kubernetes/advanced.md b/12_orchestration/kubernetes/advanced.md index f1b27b2..7181ec1 100644 --- a/12_orchestration/kubernetes/advanced.md +++ b/12_orchestration/kubernetes/advanced.md @@ -1,10 +1,10 @@ ## Kubernetes 高级特性 -掌握了 Kubernetes 的核心概念(Pod, Service, Deployment)后,我们需要了解更多高级特性以构建生产级应用。 +掌握了 Kubernetes 的核心概念 (Pod,Service,Deployment) 后,我们需要了解更多高级特性以构建生产级应用。 ### 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` * **版本管理**:轻松回滚应用的发布版本。 @@ -12,25 +12,25 @@ ### Ingress - 服务的入口 -Service 虽然提供了负载均衡,但通常是 4 层(TCP/UDP)。**Ingress** 提供了 7 层(HTTP/HTTPS)路由能力,充当集群的网关。 +Service 虽然提供了负载均衡,但通常是 4 层 (TCP/UDP)。**Ingress** 提供了 7 层 (HTTP/HTTPS) 路由能力,充当集群的网关。 -* **域名路由**:基于 Host 将请求转发不同服务 (api.example.com -> api-svc, web.example.com -> web-svc)。 -* **路径路由**:基于 Path 将请求转发 (/api -> api-svc, / -> web-svc)。 +* **域名路由**:基于 Host 将请求转发不同服务 (api.example.com -> api-svc,web.example.com -> web-svc)。 +* **路径路由**:基于 Path 将请求转发 (/api -> api-svc, / -> web-svc)。 * **SSL/TLS**:集中管理证书。 -常见的 Ingress Controller有 Nginx Ingress Controller, Traefik, Istio Gateway 等。 +常见的 Ingress Controller 有 Nginx Ingress Controller,Traefik,Istio Gateway 等。 -### Persistent Volume(PV) 与 StorageClass +### Persistent Volume 与 StorageClass -容器内的文件是临时的。对于有状态应用(如数据库),需要持久化存储。 +容器内的文件是临时的。对于有状态应用 (如数据库),需要持久化存储。 * **PVC (Persistent Volume Claim)**:用户申请存储的声明。 -* **PV (Persistent Volume)**:实际的存储资源(NFS, AWS EBS, Ceph 等)。 +* **PV (Persistent Volume)**:实际的存储资源 (NFS,AWS EBS,Ceph 等)。 * **StorageClass**:定义存储类,支持动态创建 PV。 -### Horizontal Pod Autoscaling(HPA) +### Horizontal Pod Autoscaling -HPA 根据 CPU 利用率或其他指标(如内存、自定义指标)自动扩缩 Deployment 或 ReplicaSet 中的 Pod 数量。 +HPA 根据 CPU 利用率或其他指标 (如内存、自定义指标) 自动扩缩 Deployment 或 ReplicaSet 中的 Pod 数量。 ```yaml apiVersion: autoscaling/v2 @@ -55,7 +55,7 @@ spec: ### ConfigMap 与 Secret -* **ConfigMap**:存储非机密的配置数据(配置文件、环境变量)。 -* **Secret**:存储机密数据(密码、Token、证书),在 Etcd 中加密存储。 +* **ConfigMap**:存储非机密的配置数据 (配置文件、环境变量)。 +* **Secret**:存储机密数据 (密码、Token、证书),在 Etcd 中加密存储。 通过将配置与镜像分离,保证了容器的可移植性。 diff --git a/12_orchestration/kubernetes/concepts.md b/12_orchestration/kubernetes/concepts.md index f033e30..0469c81 100644 --- a/12_orchestration/kubernetes/concepts.md +++ b/12_orchestration/kubernetes/concepts.md @@ -6,16 +6,16 @@ 图 12-2 Kubernetes 基本概念示意图 -* 节点(`Node`):一个节点是一个运行 Kubernetes 中的主机。 -* 容器组(`Pod`):一个 Pod 对应于由若干容器组成的一个容器组,同个组内的容器共享一个存储卷(volume)。 -* 容器组生命周期(`pod-states`):包含所有容器状态集合,包括容器组状态类型,容器组生命周期,事件,重启策略,以及 replication controllers。 +* 节点 (`Node`):一个节点是一个运行 Kubernetes 中的主机。 +* 容器组 (`Pod`):一个 Pod 对应于由若干容器组成的一个容器组,同个组内的容器共享一个存储卷 (volume)。 +* 容器组生命周期 (`pod-states`):包含所有容器状态集合,包括容器组状态类型,容器组生命周期,事件,重启策略,以及 replication controllers。 * Replication Controllers:主要负责指定数量的 pod 在同一时间一起运行。 -* 服务(`services`):一个 Kubernetes 服务是容器组逻辑的高级抽象,同时也对外提供访问容器组的策略。 -* 卷(`volumes`):一个卷就是一个目录,容器对其有访问权限。 -* 标签(`labels`):标签是用来连接一组对象的,比如容器组。标签可以被用来组织和选择子对象。 -* 接口权限(`accessing_the_api`):端口,IP 地址和代理的防火墙规则。 -* web 界面(`ux`):用户可以通过 web 界面操作 Kubernetes。 -* 命令行操作(`cli`):`kubectl`命令。 +* 服务 (`services`):一个 Kubernetes 服务是容器组逻辑的高级抽象,同时也对外提供访问容器组的策略。 +* 卷 (`volumes`):一个卷就是一个目录,容器对其有访问权限。 +* 标签 (`labels`):标签是用来连接一组对象的,比如容器组。标签可以被用来组织和选择子对象。 +* 接口权限 (`accessing_the_api`):端口,IP 地址和代理的防火墙规则。 +* web 界面 (`ux`):用户可以通过 web 界面操作 Kubernetes。 +* 命令行操作 (`cli`):`kubectl` 命令。 ### 节点 @@ -25,7 +25,7 @@ 容器状态用来描述节点的当前状态。现在,其中包含三个信息: -##### 主机IP +##### 主机 IP 主机 IP 需要云平台来查询,`Kubernetes` 把它作为状态的一部分来保存。如果 `Kubernetes` 没有运行在云平台上,节点 ID 就是必需的。IP 地址可以变化,并且可以包含多种类型的 IP 地址,如公共 IP,私有 IP,动态 IP,ipv6 等等。 @@ -67,17 +67,17 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接 * 集群范围内节点同步 * 单节点生命周期管理 -节点控制有一个同步轮询,主要监听所有云平台的虚拟实例,会根据节点状态创建和删除。可以通过 `--node_sync_period`标志来控制该轮询。如果一个实例已经创建,节点控制将会为其创建一个结构。同样的,如果一个节点被删除,节点控制也会删除该结构。在 Kubernetes 启动时可用通过 `--machines`标记来显示指定节点。同样可以使用 `kubectl` 来一条一条的添加节点,两者是相同的。通过设置 `--sync_nodes=false`标记来禁止集群之间的节点同步,你也可以使用 api/kubectl 命令行来增删节点。 +节点控制有一个同步轮询,主要监听所有云平台的虚拟实例,会根据节点状态创建和删除。可以通过 `--node_sync_period` 标志来控制该轮询。如果一个实例已经创建,节点控制将会为其创建一个结构。同样的,如果一个节点被删除,节点控制也会删除该结构。在 Kubernetes 启动时可用通过 `--machines` 标记来显示指定节点。同样可以使用 `kubectl` 来一条一条的添加节点,两者是相同的。通过设置 `--sync_nodes=false` 标记来禁止集群之间的节点同步,你也可以使用 api/kubectl 命令行来增删节点。 ### 容器组 -在 Kubernetes 中,使用的最小单位是容器组,容器组是创建,调度,管理的最小单位。 一个容器组使用相同的 Docker 容器并共享卷(挂载点)。一个容器组是一个特定应用的打包集合,包含一个或多个容器。 +在 Kubernetes 中,使用的最小单位是容器组,容器组是创建,调度,管理的最小单位。一个容器组使用相同的 Docker 容器并共享卷 (挂载点)。一个容器组是一个特定应用的打包集合,包含一个或多个容器。 -和运行的容器类似,一个容器组被认为只有很短的运行周期。容器组被调度到一组节点运行,直到容器的生命周期结束或者其被删除。如果节点死掉,运行在其上的容器组将会被删除而不是重新调度。(也许在将来的版本中会添加容器组的移动)。 +和运行的容器类似,一个容器组被认为只有很短的运行周期。容器组被调度到一组节点运行,直到容器的生命周期结束或者其被删除。如果节点死掉,运行在其上的容器组将会被删除而不是重新调度。(也许在将来的版本中会添加容器组的移动)。 #### 容器组设计的初衷 -容器组(Pod)的设计主要是为了解决应用间的紧密协作和资源共享问题。 +容器组 (Pod) 的设计主要是为了解决应用间的紧密协作和资源共享问题。 #### 资源共享和通信 @@ -85,7 +85,7 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接 在一个容器组中,容器都使用相同的网络地址和端口,可以通过本地网络来相互通信。每个容器组都有独立的 IP,可用通过网络来和其他物理主机或者容器通信。 -容器组有一组存储卷(挂载点),主要是为了让容器在重启之后可以不丢失数据。 +容器组有一组存储卷 (挂载点),主要是为了让容器在重启之后可以不丢失数据。 #### 容器组管理 @@ -105,10 +105,10 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接 为什么不在一个单一的容器里运行多个程序? -* 1.透明化。为了使容器组中的容器保持一致的基础设施和服务,比如进程管理和资源监控。这样设计是为了用户的便利性。 -* 2.解偶软件之间的依赖。每个容器都可能重新构建和发布,Kubernetes 必须支持热发布和热更新(将来)。 -* 3.方便使用。用户不必运行独立的程序管理,也不用担心每个应用程序的退出状态。 -* 4.高效。考虑到基础设施有更多的职责,容器必须要轻量化。 +* 1。透明化。为了使容器组中的容器保持一致的基础设施和服务,比如进程管理和资源监控。这样设计是为了用户的便利性。 +* 2。解偶软件之间的依赖。每个容器都可能重新构建和发布,Kubernetes 必须支持热发布和热更新 (将来)。 +* 3。方便使用。用户不必运行独立的程序管理,也不用担心每个应用程序的退出状态。 +* 4。高效。考虑到基础设施有更多的职责,容器必须要轻量化。 #### 容器组的生命状态 @@ -120,7 +120,7 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接 ##### running -容器组已经被调度到节点,并且所有的容器都已经启动。至少有一个容器处于运行状态(或者处于重启状态)。 +容器组已经被调度到节点,并且所有的容器都已经启动。至少有一个容器处于运行状态 (或者处于重启状态)。 ##### succeeded @@ -144,19 +144,19 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接 * 始终:重启容器,容器组保持 `running` * 失败时:容器组变为 `succeeded` * 从不:容器组变为 `succeeded` -* 容器组状态 `running`,有1容器,容器异常退出 +* 容器组状态 `running`,有 1 容器,容器异常退出 * 记录失败事件 * 如果重启策略为: * 始终:重启容器,容器组保持 `running` * 失败时:重启容器,容器组保持 `running` * 从不:容器组变为 `failed` -* 容器组状态 `running`,有2容器,有1容器异常退出 +* 容器组状态 `running`,有 2 容器,有 1 容器异常退出 * 记录失败事件 * 如果重启策略为: * 始终:重启容器,容器组保持 `running` * 失败时:重启容器,容器组保持 `running` * 从不:容器组保持 `running` - * 当有2容器退出 + * 当有 2 容器退出 * 记录失败事件 * 如果重启策略为: * 始终:重启容器,容器组保持 `running` @@ -181,25 +181,25 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中,有两个接 ### Replication Controllers -> 注:Replication Controller(RC)是早期的控制器类型,现代 Kubernetes 更推荐使用 ReplicaSet/Deployment。 +> 注:Replication Controller (RC) 是早期的控制器类型,现代 Kubernetes 更推荐使用 ReplicaSet/Deployment。 ### 服务 -> 注:服务(Service)定义一组 Pod 的逻辑集合和访问它们的策略。 +> 注:服务 (Service) 定义一组 Pod 的逻辑集合和访问它们的策略。 ### 卷 -> 注:卷(Volume)包含可被 Pod 中容器访问的数据的目录。 +> 注:卷 (Volume) 包含可被 Pod 中容器访问的数据的目录。 ### 标签 -> 注:标签(Label)是附加到对象(如 Pods)上的键值对,用于组织和选择对象子集。 +> 注:标签 (Label) 是附加到对象 (如 Pods) 上的键值对,用于组织和选择对象子集。 ### 接口权限 > 注:接口权限通过认证、授权和准入控制来保护 Kubernetes API 的访问。 -### web界面 +### web 界面 > 注:Kubernetes Dashboard 是一个基于 Web 的用户界面,用于管理集群。 diff --git a/12_orchestration/kubernetes/design.md b/12_orchestration/kubernetes/design.md index 8660947..e6bd841 100644 --- a/12_orchestration/kubernetes/design.md +++ b/12_orchestration/kubernetes/design.md @@ -19,7 +19,7 @@ 图 12-3 Kubernetes 运行原理图 -可见,Kubernetes 首先是一套分布式系统,由多个节点组成,节点分为两类:一类是属于管理平面的主节点/控制节点(Master Node);一类是属于运行平面的工作节点(Worker Node)。 +可见,Kubernetes 首先是一套分布式系统,由多个节点组成,节点分为两类:一类是属于管理平面的主节点/控制节点 (Master Node);一类是属于运行平面的工作节点 (Worker Node)。 显然,复杂的工作肯定都交给控制节点去做了,工作节点负责提供稳定的操作接口和能力抽象即可。 @@ -27,7 +27,7 @@ ### 控制平面 -控制平面(Control Plane)是 Kubernetes 集群的大脑,负责做出全局决策(如调度)以及检测和响应集群事件。 +控制平面 (Control Plane) 是 Kubernetes 集群的大脑,负责做出全局决策 (如调度) 以及检测和响应集群事件。 #### 主节点服务 @@ -35,7 +35,7 @@ * `apiserver` 是整个系统的对外接口,提供一套 RESTful 的 [Kubernetes API](https://kubernetes.io/zh/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 @@ ### 工作节点 * kubelet 是工作节点执行操作的 agent,负责具体的容器生命周期管理,根据从数据库中获取的信息来管理容器,并上报 pod 运行状态等; -* kube-proxy 是一个简单的网络访问代理,同时也是一个 Load Balancer。它负责将访问到某个服务的请求具体分配给工作节点上的 Pod(同一类标签)。 +* kube-proxy 是一个简单的网络访问代理,同时也是一个 Load Balancer。它负责将访问到某个服务的请求具体分配给工作节点上的 Pod (同一类标签)。 ![Proxy 代理对服务的请求](./_images/kube-proxy.png) diff --git a/12_orchestration/kubernetes/intro.md b/12_orchestration/kubernetes/intro.md index 7ca9036..fb50607 100644 --- a/12_orchestration/kubernetes/intro.md +++ b/12_orchestration/kubernetes/intro.md @@ -8,11 +8,11 @@ ### 什么是 Kubernetes -Kubernetes(常简称为 K8s)是 Google 开源的容器编排引擎。如果说 Docker 解决了"如何打包和运送集装箱"的问题,那么 Kubernetes 解决的就是"如何管理海量集装箱的调度、运行和维护"的问题。 +Kubernetes (常简称为 K8s) 是 Google 开源的容器编排引擎。如果说 Docker 解决了 “如何打包和运送集装箱” 的问题,那么 Kubernetes 解决的就是 “如何管理海量集装箱的调度、运行和维护” 的问题。 它不仅仅是一个编排系统,更是一个**云原生应用操作系统**。 -> **名字由来**:Kubernetes 在希腊语中意为"舵手"或"飞行员"。K8s 是因为 k 和 s 之间有 8 个字母。 +> **名字由来**:Kubernetes 在希腊语中意为 “舵手” 或 “飞行员”。K8s 是因为 k 和 s 之间有 8 个字母。 --- @@ -32,23 +32,25 @@ Kubernetes 完美解决了这些问题。 ### 核心概念 -#### Pod(豆荚) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: -Kubernetes 的最小调度单位。一个 Pod 可以包含一个或多个紧密协作的容器(共享网络和存储)。就像豌豆荚里的豌豆一样。 +#### Pod (豆荚) -#### Node(节点) +Kubernetes 的最小调度单位。一个 Pod 可以包含一个或多个紧密协作的容器 (共享网络和存储)。就像豌豆荚里的豌豆一样。 + +#### Node (节点) 运行 Pod 的物理机或虚拟机。 -#### Deployment(部署) +#### Deployment (部署) -定义应用的期望状态(如:需要 3 个副本,镜像版本为 v1)。K8s 会持续确保当前状态符合期望状态。 +定义应用的期望状态 (如:需要 3 个副本,镜像版本为 v1)。K8s 会持续确保当前状态符合期望状态。 -#### Service(服务) +#### Service (服务) 定义一组 Pod 的访问策略。提供稳定的 Cluster IP 和 DNS 名称,负责负载均衡。 -#### Namespace(命名空间) +#### Namespace (命名空间) 用于多租户资源隔离。 @@ -69,17 +71,17 @@ Kubernetes 的最小调度单位。一个 Pod 可以包含一个或多个紧密 ### 架构 -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) +- **Control Plane**:负责决策 (API Server,Scheduler,Controller Manager,etcd) +- **Worker Node**:负责干活 (Kubelet,Kube-proxy,Container Runtime) --- ### 学习建议 Kubernetes 的学习曲线较陡峭。建议的学习路径: -1. **理解基本概念**:Pod, Deployment, Service +1. **理解基本概念**:Pod,Deployment,Service 2. **动手实践**:使用 Minikube 或 Kind 在本地搭建集群 3. **部署应用**:编写 YAML 部署一个无状态应用 4. **深入原理**:网络模型、存储机制、调度算法 diff --git a/12_orchestration/kubernetes/practice.md b/12_orchestration/kubernetes/practice.md index 76a53aa..72cad4a 100644 --- a/12_orchestration/kubernetes/practice.md +++ b/12_orchestration/kubernetes/practice.md @@ -6,7 +6,7 @@ 1. 部署一个 Nginx Deployment。 2. 创建一个 Service 暴露 Nginx。 -3. (可选)通过 Ingress 访问服务。 +3. (可选) 通过 Ingress 访问服务。 ### 步骤 1:创建 Deployment @@ -75,7 +75,7 @@ kubectl get svc nginx-service 如果输出端口是 `80:30080/TCP`,你可以通过 `http://:30080` 访问 Nginx。 -### 步骤 3:模拟滚动更新(Rolling Update) +### 步骤 3:模拟滚动更新 修改 `nginx-deployment.yaml`,将镜像版本改为 `nginx:1.27-alpine`。 diff --git a/12_orchestration/setup/README.md b/12_orchestration/setup/README.md index 4275d0d..e578609 100644 --- a/12_orchestration/setup/README.md +++ b/12_orchestration/setup/README.md @@ -1,6 +1,6 @@ # 部署 Kubernetes -目前,Kubernetes 支持在多种环境下使用,包括本地主机(Ubuntu、Debian、CentOS、Fedora 等)、云服务([腾讯云](https://cloud.tencent.com/act/cps/redirect?redirect=10058&cps_key=3a5255852d5db99dcd5da4c72f05df61)、[阿里云](https://www.aliyun.com/product/kubernetes?source=5176.11533457&userCode=8lx5zmtu&type=copy)、[百度云](https://cloud.baidu.com/product/cce.html) 等)。 +目前,Kubernetes 支持在多种环境下使用,包括本地主机 (Ubuntu、Debian、CentOS、Fedora 等)、云服务 ([腾讯云](https://cloud.tencent.com/act/cps/redirect?redirect=10058&cps_key=3a5255852d5db99dcd5da4c72f05df61)、[阿里云](https://www.aliyun.com/product/kubernetes?source=5176.11533457&userCode=8lx5zmtu&type=copy)、[百度云](https://cloud.baidu.com/product/cce.html)等)。 你可以使用以下几种方式部署 Kubernetes: diff --git a/12_orchestration/setup/k3s.md b/12_orchestration/setup/k3s.md index 7cbe393..a095419 100644 --- a/12_orchestration/setup/k3s.md +++ b/12_orchestration/setup/k3s.md @@ -4,8 +4,8 @@ ### 核心特性 -* **轻量级**:移除过时的、非必须的 Kubernetes 功能(如传统的云提供商插件),使用 SQLite 作为默认数据存储(也支持 Etcd/MySQL/Postgres)。 -* **单一二进制**:所有组件(API Server, Controller Manager, Scheduler, Kubelet, Kube-proxy)打包在一个进程中运行。 +* **轻量级**:移除过时的、非必须的 Kubernetes 功能 (如传统的云提供商插件),使用 SQLite 作为默认数据存储 (也支持 Etcd/MySQL/Postgres)。 +* **单一二进制**:所有组件 (API Server,Controller Manager,Scheduler,Kubelet,Kube-proxy) 打包在一个进程中运行。 * **开箱即用**:内置 Helm Controller、Traefik Ingress controller、ServiceLB、Local-Path-Provisioner。 * **安全**:默认启用安全配置,基于 TLS 通信。 @@ -13,7 +13,7 @@ K3s 的安装非常简单,官方提供了便捷的安装脚本。 -#### 脚本安装(Linux) +#### 脚本安装 K3s 提供了极为便捷的安装脚本: @@ -39,7 +39,7 @@ k3s-master Ready control-plane,master 1m v1.35.1+k3s1 ### 快速使用 -K3s 内置了 `kubectl` 命令(通过 `k3s kubectl` 调用),为了方便,通常会建立别名或配置 `KUBECONFIG`。 +K3s 内置了 `kubectl` 命令 (通过 `k3s kubectl` 调用),为了方便,通常会建立别名或配置 `KUBECONFIG`。 ```bash ## 读取 K3s 的配置文件 diff --git a/12_orchestration/setup/kind.md b/12_orchestration/setup/kind.md index 750191f..058a9fd 100644 --- a/12_orchestration/setup/kind.md +++ b/12_orchestration/setup/kind.md @@ -4,12 +4,12 @@ ### 为什么选择 Kind -Kind 相比其他本地集群方案(如 Minikube)有以下显著优势: +Kind 相比其他本地集群方案 (如 Minikube) 有以下显著优势: * **轻量便捷**:只要有 Docker 环境即可,无需额外虚拟机。 * **多集群支持**:可以轻松在本地启动多个集群。 * **多版本支持**:支持指定 Kubernetes 版本进行测试。 -* **HA 支持**:支持模拟高可用集群(多 Control Plane)。 +* **HA 支持**:支持模拟高可用集群 (多 Control Plane)。 ### 安装 Kind @@ -23,7 +23,7 @@ Kind 是一个二进制文件,并在 PATH 中即可使用。以下是不同系 brew install kind ``` -#### Linux / Windows(WSL2) +#### Linux / Windows 可以下载二进制文件: diff --git a/12_orchestration/setup/kubeadm-docker.md b/12_orchestration/setup/kubeadm-docker.md index c18bf0a..22c2332 100644 --- a/12_orchestration/setup/kubeadm-docker.md +++ b/12_orchestration/setup/kubeadm-docker.md @@ -1,14 +1,14 @@ -## 使用 kubeadm 部署 Kubernetes(使用 Docker) +## 使用 kubeadm 部署 Kubernetes (使用 Docker) `kubeadm` 提供了 `kubeadm init` 以及 `kubeadm join` 这两个命令,作为快速创建 `Kubernetes` 集群的最佳实践。 -> ⚠️ **重要说明**:自 Kubernetes 1.24 起,内置 `dockershim` 已被移除,Kubernetes 默认不再直接使用 Docker Engine 作为容器运行时(CRI)。因此,**更推荐参考**同目录下的《[使用 kubeadm 部署 Kubernetes(CRI 使用 containerd)](kubeadm.md)》。 +> ⚠️ **重要说明**:自 Kubernetes 1.24 起,内置 `dockershim` 已被移除,Kubernetes 默认不再直接使用 Docker Engine 作为容器运行时 (CRI)。因此,**更推荐参考**同目录下的《[使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)](kubeadm.md)》。 > > 本文档主要用于历史环境/学习目的:如果你确实需要在较新版本中继续使用 Docker Engine,通常需要额外部署 `cri-dockerd` 并在 `kubeadm init/join` 中指定 `--cri-socket`。 ### 安装 Docker -参考 [安装 Docker](../../03_install/README.md) 一节安装 Docker。 +参考[安装 Docker](../../03_install/README.md) 一节安装 Docker。 ### 安装 **kubelet****kubeadm****kubectl** @@ -58,6 +58,8 @@ $ sudo yum install -y kubelet kubeadm kubectl ### 修改内核的运行参数 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 加载内核模块 运行以下命令: @@ -72,7 +74,7 @@ $ sudo modprobe overlay $ sudo modprobe br_netfilter ``` -#### 禁用 swap(必须) +#### 禁用 swap (必须) kubelet 默认要求禁用 swap,否则可能导致初始化失败或节点无法加入集群。 @@ -101,6 +103,10 @@ $ sysctl --system 为了让 kubelet 正确运行,我们需要对其进行一些必要的配置。 +#### 概述 + +总体概述了以下内容。 + #### 修改 `kubelet.service` `/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容 @@ -169,7 +175,7 @@ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \ #### node 工作节点 -在 **另一主机**重复**部署** 小节以前的步骤,安装配置好 kubelet。根据提示,加入到集群。 +在**另一主机**重复**部署**小节以前的步骤,安装配置好 kubelet。根据提示,加入到集群。 ```bash $ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \ @@ -186,7 +192,7 @@ $ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \ * `scheduler` 负责对资源进行调度,分配某个 pod 到某个节点上; -* `controller-manager` 负责管理控制器,包括 endpoint-controller(刷新服务和 pod 的关联信息)和 replication-controller(维护某个 pod 的复制为配置的数值)。 +* `controller-manager` 负责管理控制器,包括 endpoint-controller (刷新服务和 pod 的关联信息) 和 replication-controller (维护某个 pod 的复制为配置的数值)。 #### 工作节点服务 @@ -208,6 +214,10 @@ $ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \ 这里以 `flannel` 为例进行介绍。 +#### 概述 + +总体概述了以下内容。 + #### flannel 检查 podCIDR 设置 diff --git a/12_orchestration/setup/kubeadm.md b/12_orchestration/setup/kubeadm.md index 6937651..0d8f6be 100644 --- a/12_orchestration/setup/kubeadm.md +++ b/12_orchestration/setup/kubeadm.md @@ -1,12 +1,12 @@ -## 使用 kubeadm 部署 Kubernetes(CRI 使用 containerd) +## 使用 kubeadm 部署 Kubernetes (CRI 使用 containerd) `kubeadm` 提供了 `kubeadm init` 以及 `kubeadm join` 这两个命令,作为快速创建 `Kubernetes` 集群的最佳实践。 -> **版本说明**:Kubernetes 版本更新较快(约每 4 个月一个新版本),本文档基于 Kubernetes 1.35 编写。请访问 [Kubernetes 官方发布页](https://kubernetes.io/releases/) 获取最新版本信息。 +> **版本说明**:Kubernetes 版本更新较快 (约每 4 个月一个新版本),本文档基于 Kubernetes 1.35 编写。请访问 [Kubernetes 官方发布页](https://kubernetes.io/releases/)获取最新版本信息。 ### 安装 containerd -参考 [安装 Docker](../../03_install/README.md) 一节添加 apt/yum 源,之后执行如下命令。 +参考[安装 Docker](../../03_install/README.md) 一节添加 apt/yum 源,之后执行如下命令。 ```bash ## debian 系 @@ -276,6 +276,8 @@ $ sudo yum install -y kubelet kubeadm kubectl cri-tools kubernetes-cni ### 修改内核的运行参数 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 加载内核模块 运行以下命令: @@ -290,7 +292,7 @@ $ sudo modprobe overlay $ sudo modprobe br_netfilter ``` -#### 禁用 swap(必须) +#### 禁用 swap (必须) kubelet 默认要求禁用 swap,否则可能导致初始化失败或节点无法加入集群。 @@ -319,6 +321,10 @@ $ sysctl --system 为了让 kubelet 正确运行,我们需要对其进行一些必要的配置。 +#### 概述 + +总体概述了以下内容。 + #### 修改 `kubelet.service` `/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容 @@ -393,7 +399,7 @@ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \ #### node 工作节点 -在 **另一主机**重复**部署** 小节以前的步骤,安装配置好 kubelet。根据提示,加入到集群。 +在**另一主机**重复**部署**小节以前的步骤,安装配置好 kubelet。根据提示,加入到集群。 ```bash $ systemctl enable cri-containerd @@ -420,7 +426,7 @@ CONTAINER_RUNTIME_ENDPOINT=/run/cri-containerd/cri-containerd.sock crictl ps -a * `scheduler` 负责对资源进行调度,分配某个 pod 到某个节点上; -* `controller-manager` 负责管理控制器,包括 endpoint-controller(刷新服务和 pod 的关联信息)和 replication-controller(维护某个 pod 的复制为配置的数值)。 +* `controller-manager` 负责管理控制器,包括 endpoint-controller (刷新服务和 pod 的关联信息) 和 replication-controller (维护某个 pod 的复制为配置的数值)。 #### 工作节点服务 @@ -442,6 +448,10 @@ CONTAINER_RUNTIME_ENDPOINT=/run/cri-containerd/cri-containerd.sock crictl ps -a 这里以 `flannel` 为例进行介绍。 +#### 概述 + +总体概述了以下内容。 + #### flannel 检查 podCIDR 设置 diff --git a/13_ecosystem/README.md b/13_ecosystem/README.md index ba56192..7b43447 100644 --- a/13_ecosystem/README.md +++ b/13_ecosystem/README.md @@ -1,4 +1,4 @@ -# 第十三章 容器生态 +# 第十三章容器生态 本章将介绍容器生态圈的相关项目与服务。 diff --git a/13_ecosystem/cloud/README.md b/13_ecosystem/cloud/README.md index 6cc5824..c4bfdc7 100644 --- a/13_ecosystem/cloud/README.md +++ b/13_ecosystem/cloud/README.md @@ -2,4 +2,4 @@ Docker 目前已经得到了众多公有云平台的支持,并成为除虚拟机之外的核心云业务。 -除了 AWS、Google、Azure 等,国内的各大公有云厂商,基本上都同时支持了虚拟机服务和基于 Kubernetes 的容器云业务。有的还推出了其他服务,例如 [容器镜像服务](https://cloud.tencent.com/act/cps/redirect?redirect=11588&cps_key=3a5255852d5db99dcd5da4c72f05df61) 让用户在云上享有安全高效的镜像托管、分发等服务。 +除了 AWS、Google、Azure 等,国内的各大公有云厂商,基本上都同时支持了虚拟机服务和基于 Kubernetes 的容器云业务。有的还推出了其他服务,例如[容器镜像服务](https://cloud.tencent.com/act/cps/redirect?redirect=11588&cps_key=3a5255852d5db99dcd5da4c72f05df61)让用户在云上享有安全高效的镜像托管、分发等服务。 diff --git a/13_ecosystem/cloud/alicloud.md b/13_ecosystem/cloud/alicloud.md index 6b5da06..dbbae37 100644 --- a/13_ecosystem/cloud/alicloud.md +++ b/13_ecosystem/cloud/alicloud.md @@ -6,9 +6,9 @@ 图 13-3 阿里云标识 -[阿里云](https://www.aliyun.com/?source=5176.11533457\&userCode=8lx5zmtu\&type=copy) 创立于 2009 年,是中国较早的云计算平台。阿里云致力于提供安全、可靠的计算和数据处理能力。 +[阿里云](https://www.aliyun.com/?source=5176.11533457\&userCode=8lx5zmtu\&type=copy)创立于 2009 年,是中国较早的云计算平台。阿里云致力于提供安全、可靠的计算和数据处理能力。 -[阿里云](https://www.aliyun.com/?source=5176.11533457\&userCode=8lx5zmtu\&type=copy) 的客户群体中,活跃着微博、虎牙、魅族、优酷等一大批明星互联网公司。在天猫双 11 全球狂欢节等极富挑战的应用场景中,阿里云保持着良好的运行纪录。 +[阿里云](https://www.aliyun.com/?source=5176.11533457\&userCode=8lx5zmtu\&type=copy)的客户群体中,活跃着微博、虎牙、魅族、优酷等一大批明星互联网公司。在天猫双 11 全球狂欢节等极富挑战的应用场景中,阿里云保持着良好的运行纪录。 [阿里云容器服务 Kubernetes 版 ACK](https://www.aliyun.com/product/kubernetes?source=5176.11533457\&userCode=8lx5zmtu\&type=copy) 提供了高性能、可伸缩的容器应用管理服务,支持在一组云服务器上通过 Docker 容器来进行应用生命周期管理。容器服务极大简化了用户对容器管理集群的搭建工作,无缝整合了阿里云虚拟化、存储、网络和安全能力。容器服务提供了多种应用发布方式和流水线般的持续交付能力,原生支持微服务架构,助力用户无缝上云和跨云管理。 diff --git a/13_ecosystem/cloud/aws.md b/13_ecosystem/cloud/aws.md index a631437..ae6dd84 100644 --- a/13_ecosystem/cloud/aws.md +++ b/13_ecosystem/cloud/aws.md @@ -6,12 +6,12 @@ 图 13-1 AWS 标识 -[AWS](https://www.amazonaws.cn),即 Amazon Web Services,是亚马逊(Amazon)公司的 IaaS 和 PaaS 平台服务。AWS 提供了一整套基础设施和应用程序服务,使用户几乎能够在云中运行一切应用程序:从企业应用程序和大数据项目,到社交游戏和移动应用程序。AWS 面向用户提供包括弹性计算、存储、数据库、应用程序在内的一整套云计算服务,能够帮助企业降低 IT 投入成本和维护成本。 +[AWS](https://www.amazonaws.cn),即 Amazon Web Services,是亚马逊 (Amazon) 公司的 IaaS 和 PaaS 平台服务。AWS 提供了一整套基础设施和应用程序服务,使用户几乎能够在云中运行一切应用程序:从企业应用程序和大数据项目,到社交游戏和移动应用程序。AWS 面向用户提供包括弹性计算、存储、数据库、应用程序在内的一整套云计算服务,能够帮助企业降低 IT 投入成本和维护成本。 在容器领域,AWS 目前主流能力可以按场景分为四类: 1. `Amazon EKS`:托管 Kubernetes 控制平面,适合标准云原生工作负载。 -2. `Amazon ECS`:AWS 原生容器编排服务,适合深度集成 AWS 生态(IAM、ALB、CloudWatch)场景。 +2. `Amazon ECS`:AWS 原生容器编排服务,适合深度集成 AWS 生态 (IAM、ALB、CloudWatch) 场景。 3. `AWS Fargate`:无服务器容器运行时,可与 EKS/ECS 结合使用,减少节点运维。 4. `Amazon ECR`:镜像仓库服务,提供私有镜像管理、扫描与访问控制。 diff --git a/13_ecosystem/cloud/intro.md b/13_ecosystem/cloud/intro.md index 36906cb..70661fe 100644 --- a/13_ecosystem/cloud/intro.md +++ b/13_ecosystem/cloud/intro.md @@ -2,21 +2,21 @@ 随着容器技术的普及,目前主流的云计算服务商都提供了成熟的容器服务。与容器相关的云计算服务主要分为以下几种类型: -### 1. 容器编排托管服务(Managed K8s) +### 1。容器编排托管服务 -这是目前最主流的形式。云厂商托管 Kubernetes 的控制平面(Master节点),用户只需管理工作节点(Worker Node)。 +这是目前最主流的形式。云厂商托管 Kubernetes 的控制平面 (Master 节点),用户只需管理工作节点 (Worker Node)。 * **优势**:降低了 Kubernetes 集群的维护成本,高可用性由厂商保证。 -* **典型服务**:AWS EKS, Azure AKS, Google GKE, 阿里云 ACK, 腾讯云 TKE。 +* **典型服务**:AWS EKS,Azure AKS,Google GKE,阿里云 ACK,腾讯云 TKE。 -### 2. 容器实例服务(Serverless Containers) +### 2。容器实例服务 -这一类服务通常被称为 CaaS (Container as a Service)。用户无需管理底层服务器(EC2/CVM),只需提供镜像和配置即可运行容器。 +这一类服务通常被称为 CaaS (Container as a Service)。用户无需管理底层服务器 (EC2/CVM),只需提供镜像和配置即可运行容器。 * **优势**:极致的弹性,按秒计费,零运维。 -* **典型服务**:AWS Fargate, Azure Container Instances, Google Cloud Run, 阿里云 ECI。 +* **典型服务**:AWS Fargate,Azure Container Instances,Google Cloud Run,阿里云 ECI。 -### 3. 镜像仓库服务(Container Registry) +### 3。镜像仓库服务 提供安全、可靠的私有 Docker 镜像存储服务,通常与云厂商的 CI/CD 流水线深度集成。 -* **典型服务**:AWS ECR, Azure ACR, Google GCR/GAR, 阿里云 ACR。 +* **典型服务**:AWS ECR,Azure ACR,Google GCR/GAR,阿里云 ACR。 本章将介绍如何在几个主流云平台上使用 Docker 和 Kubernetes 服务。 diff --git a/13_ecosystem/cloud/multicloud.md b/13_ecosystem/cloud/multicloud.md index 4faeb8d..f7d5f33 100644 --- a/13_ecosystem/cloud/multicloud.md +++ b/13_ecosystem/cloud/multicloud.md @@ -1,6 +1,6 @@ ## 多云部署策略比较 -企业在选择容器云平台时,通常会在 AWS EKS, Azure AKS, Google GKE 以及国内的阿里云 ACK, 腾讯云 TKE 之间进行权衡。 +企业在选择容器云平台时,通常会在 AWS EKS,Azure AKS,Google GKE 以及国内的阿里云 ACK,腾讯云 TKE 之间进行权衡。 ### 三大公有云 Kubernetes 服务对比 @@ -16,27 +16,27 @@ 随着企业业务的扩展,单一云平台可能无法满足所有需求,多云部署成为趋势。 -#### 1. 跨云灾备(Active-Passive) +#### 1。跨云灾备 (Active-Passive) -主要业务运行在一个云(如 AWS),数据实时复制到另一个云(如阿里云)。当主云发生故障时,流量切换到备云。 +主要业务运行在一个云 (如 AWS),数据实时复制到另一个云 (如阿里云)。当主云发生故障时,流量切换到备云。 -* **优点**: 架构相对简单,数据一致性好控制。 -* **缺点**: 资源闲置浪费,切换可能有 RTO。 +* **优点**:架构相对简单,数据一致性好控制。 +* **缺点**:资源闲置浪费,切换可能有 RTO。 -#### 2. 多活部署(Active-Active) +#### 2。多活部署 (Active-Active) -业务同时在多个云上运行,通过全局流量管理(DNS/GSLB)分发流量。 +业务同时在多个云上运行,通过全局流量管理 (DNS/GSLB) 分发流量。 -* **优点**: 高可用,就近接入提升用户体验。 -* **缺点**: 数据同步复杂,跨云网络延迟问题。 +* **优点**:高可用,就近接入提升用户体验。 +* **缺点**:数据同步复杂,跨云网络延迟问题。 -#### 3. 混合云(Hybrid Cloud) +#### 3。混合云 -核心数据和敏感业务保留在私有云(IDC),弹性业务或前端业务部署在公有云。 +核心数据和敏感业务保留在私有云 (IDC),弹性业务或前端业务部署在公有云。 -* **工具**: Google Anthos, AWS Outposts, Azure Arc 都是为了解决混合云统一管理而生。 +* **工具**:Google Anthos,AWS Outposts,Azure Arc 都是为了解决混合云统一管理而生。 ### 建议 -* **技术选型**: 尽量使用标准的 Kubernetes API,避免过度依赖特定云厂商的 CRD 或专有服务,以保持应用的可移植性。 -* **IaC 管理**: 使用 Terraform 或 Pulumi 等工具统一管理多云基础设施。 +* **技术选型**:尽量使用标准的 Kubernetes API,避免过度依赖特定云厂商的 CRD 或专有服务,以保持应用的可移植性。 +* **IaC 管理**:使用 Terraform 或 Pulumi 等工具统一管理多云基础设施。 diff --git a/13_ecosystem/cloud/tencentCloud.md b/13_ecosystem/cloud/tencentCloud.md index 30e5032..06d1ba7 100644 --- a/13_ecosystem/cloud/tencentCloud.md +++ b/13_ecosystem/cloud/tencentCloud.md @@ -6,9 +6,9 @@ 图 13-5 腾讯云标识 -[腾讯云](https://cloud.tencent.com/act/cps/redirect?redirect=1040\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console) 在架构方面经过多年积累,并且有着多年对海量互联网服务的经验。不管是社交、游戏还是其他领域,都有多年的成熟产品来提供产品服务。腾讯在云端完成重要部署,为开发者及企业提供云服务、云数据、云运营等整体一站式服务方案。 +[腾讯云](https://cloud.tencent.com/act/cps/redirect?redirect=1040\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console)在架构方面经过多年积累,并且有着多年对海量互联网服务的经验。不管是社交、游戏还是其他领域,都有多年的成熟产品来提供产品服务。腾讯在云端完成重要部署,为开发者及企业提供云服务、云数据、云运营等整体一站式服务方案。 -具体包括 [云服务器](https://cloud.tencent.com/act/cps/redirect?redirect=1001\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console)、[云存储](https://cloud.tencent.com/act/cps/redirect?redirect=1020\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console)、[云数据库](https://cloud.tencent.com/act/cps/redirect?redirect=1003\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console)、[视频与CDN](https://cloud.tencent.com/act/cps/redirect?redirect=1019\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console) 和 [域名注册](https://dnspod.cloud.tencent.com) 等基础云服务;腾讯云分析(MTA)、腾讯云推送(信鸽)等腾讯整体大数据能力;以及 QQ互联、QQ 空间、微云、微社区等云端链接社交体系。这些正是腾讯云可以提供给这个行业的差异化优势,造就了可支持各种互联网使用场景的高品质的腾讯云技术平台。 +具体包括[云服务器](https://cloud.tencent.com/act/cps/redirect?redirect=1001\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console)、[云存储](https://cloud.tencent.com/act/cps/redirect?redirect=1020\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console)、[云数据库](https://cloud.tencent.com/act/cps/redirect?redirect=1003\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console)、[视频与 CDN](https://cloud.tencent.com/act/cps/redirect?redirect=1019\&cps_key=3a5255852d5db99dcd5da4c72f05df61\&from=console) 和[域名注册](https://dnspod.cloud.tencent.com)等基础云服务;腾讯云分析 (MTA)、腾讯云推送 (信鸽) 等腾讯整体大数据能力;以及 QQ 互联、QQ 空间、微云、微社区等云端链接社交体系。这些正是腾讯云可以提供给这个行业的差异化优势,造就了可支持各种互联网使用场景的高品质的腾讯云技术平台。 [腾讯云容器服务 TKE](https://cloud.tencent.com/act/cps/redirect?redirect=10058\&cps_key=3a5255852d5db99dcd5da4c72f05df61) 是高度可扩展的高性能容器管理服务,用户可以在托管的云服务器实例集群上轻松运行应用程序。使用该服务,将无需安装、运维、扩展用户的集群管理基础设施,只需进行简单的 API 调用,便可启动和停止 Docker 应用程序,查询集群的完整状态,以及使用各种云服务。用户可以根据用户的资源需求和可用性要求在用户的集群中安排容器的置放,满足业务或应用程序的特定要求。 diff --git a/13_ecosystem/coreos/README.md b/13_ecosystem/coreos/README.md index 36512e4..0bcb69d 100644 --- a/13_ecosystem/coreos/README.md +++ b/13_ecosystem/coreos/README.md @@ -4,4 +4,4 @@ `CoreOS` 的安装文件和运行依赖非常小,它提供了精简的 Linux 系统。它使用 Linux 容器在更高的抽象层来管理你的服务,而不是通过常规的包管理工具 `yum` 或 `apt` 来安装包。 -同时,`CoreOS` 几乎可以运行在任何平台:`VirtualBox` `Amazon EC2` `QEMU/KVM` `VMware` `Bare Metal` 和 `OpenStack` 等 。 +同时,`CoreOS` 几乎可以运行在任何平台:`VirtualBox` `Amazon EC2` `QEMU/KVM` `VMware` `Bare Metal` 和 `OpenStack` 等。 diff --git a/13_ecosystem/coreos/install.md b/13_ecosystem/coreos/install.md index 5e57fd5..5b373ef 100644 --- a/13_ecosystem/coreos/install.md +++ b/13_ecosystem/coreos/install.md @@ -1,12 +1,14 @@ ## 安装 Fedora CoreOS +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 下载 ISO -在 [下载页面](https://getfedora.org/coreos/download/) `Bare Metal & Virtualized` 标签页下载 ISO。 +在[下载页面](https://getfedora.org/coreos/download/) `Bare Metal & Virtualized` 标签页下载 ISO。 ### 编写 FCC -FCC 是 Fedora CoreOS Configuration (Fedora CoreOS 配置)的简称。 +FCC 是 Fedora CoreOS Configuration (Fedora CoreOS 配置) 的简称。 ```yaml ## example.fcc @@ -20,7 +22,7 @@ passwd: - ssh-rsa AAAA... ``` -将 `ssh-rsa AAAA...` 替换为自己的 SSH 公钥(位于 `~/.ssh/id_rsa.pub`)。 +将 `ssh-rsa AAAA...` 替换为自己的 SSH 公钥 (位于 `~/.ssh/id_rsa.pub`)。 ### 转换 FCC 为 Ignition diff --git a/13_ecosystem/coreos/intro.md b/13_ecosystem/coreos/intro.md index 3f9cb6f..40b8b4a 100644 --- a/13_ecosystem/coreos/intro.md +++ b/13_ecosystem/coreos/intro.md @@ -4,15 +4,17 @@ ### FCOS 特性 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 一个最小化操作系统 -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 服务已被写入磁盘,从而加快了启动时间。 #### 自动更新 @@ -20,7 +22,7 @@ FCOS 使用 rpm-ostree 系统进行事务性升级。无需像 yum 升级那样 #### 容器工具 -对于诸如构建,复制和其他管理容器的任务,FCOS 用一组容器工具代替了 **Docker CLI**。**podman CLI**工具支持许多容器运行时功能,例如运行,启动,停止,列出和删除容器和镜像。**skopeo CLI**工具可以复制,认证和签名镜像。您还可以使用**crictl CLI** 工具来处理 CRI-O 容器引擎中的容器和镜像。 +对于诸如构建,复制和其他管理容器的任务,FCOS 用一组容器工具代替了 **Docker CLI**。**podman CLI** 工具支持许多容器运行时功能,例如运行,启动,停止,列出和删除容器和镜像。**skopeo CLI** 工具可以复制,认证和签名镜像。您还可以使用 **crictl CLI** 工具来处理 CRI-O 容器引擎中的容器和镜像。 ### 参考文档 diff --git a/13_ecosystem/podman/README.md b/13_ecosystem/podman/README.md index a2786ec..6e62386 100644 --- a/13_ecosystem/podman/README.md +++ b/13_ecosystem/podman/README.md @@ -67,7 +67,7 @@ $ podman build -t myimage . ## Pods 的概念 -与 Docker 不同,Podman 支持 "Pod" 的概念(类似于 Kubernetes 的 Pod),允许你在同一个网络命名空间中运行多个容器。 +与 Docker 不同,Podman 支持 “Pod” 的概念 (类似于 Kubernetes 的 Pod),允许你在同一个网络命名空间中运行多个容器。 ```bash ## 创建一个 Pod @@ -89,6 +89,8 @@ $ alias docker=podman ### 进阶用法 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### Systemd 集成 Podman 可以生成 systemd 单元文件,让容器像普通系统服务一样管理。 diff --git a/14_implementation/14.1_arch.md b/14_implementation/14.1_arch.md index 1737a98..97a0ee3 100644 --- a/14_implementation/14.1_arch.md +++ b/14_implementation/14.1_arch.md @@ -27,31 +27,31 @@ graph LR Docker 的内部架构如同洋葱一样分层,每一层专注解决特定问题: -#### 1. Docker CLI(客户端) +#### 1。Docker CLI (客户端) -用户与 Docker 交互的主要方式。它将用户命令(如 `docker run`)转换为 API 请求发送给 dockerd。 +用户与 Docker 交互的主要方式。它将用户命令 (如 `docker run`) 转换为 API 请求发送给 dockerd。 -#### 2. Dockerd(守护进程) +#### 2。Dockerd (守护进程) Docker 的大脑。 - 监听 API 请求 -- 管理 Docker 对象(镜像、容器、网络、卷) +- 管理 Docker 对象 (镜像、容器、网络、卷) - 编排下层组件完成工作 -#### 3. Containerd(高级运行时) +#### 3。Containerd (高级运行时) -行业标准的容器运行时(CNCF 毕业项目)。 -- 管理容器的完整生命周期(启动、停止) +行业标准的容器运行时 (CNCF 毕业项目)。 +- 管理容器的完整生命周期 (启动、停止) - 镜像拉取与存储 -- **不包含** 复杂的与容器无关的功能(如构建、API) -- Kubernetes 也可以直接使用 containerd(跳过 Docker) +- **不包含**复杂的与容器无关的功能 (如构建、API) +- Kubernetes 也可以直接使用 containerd (跳过 Docker) -#### 4. Runc(低级运行时) +#### 4。Runc (低级运行时) 用于创建和运行容器的 CLI 工具。 -- 直接与内核交互(Namespaces, Cgroups) +- 直接与内核交互 (Namespaces,Cgroups) - 遵循 OCI (Open Container Initiative) 规范 -- **主要职责**:根据配置启动一个容器,然后退出(将控制权交给容器进程) +- **主要职责**:根据配置启动一个容器,然后退出 (将控制权交给容器进程) #### 5. Shim @@ -95,9 +95,9 @@ flowchart TD Shim -.-> |8. Monitor IO/Exit| Container ``` -1. **CLI**发送请求给**Dockerd**2.**Dockerd**解析请求,调用**Containerd**3.**Containerd** 准备镜像,转换为 OCI Bundle -4. **Containerd**创建**Shim** 进程 -5. **Shim**调用**Runc**6.**Runc** 与系统内核交互,创建 Namespaces 和 Cgroups +1. **CLI** 发送请求给 **Dockerd**2。**Dockerd** 解析请求,调用 **Containerd**3。**Containerd** 准备镜像,转换为 OCI Bundle +4. **Containerd** 创建 **Shim** 进程 +5. **Shim** 调用 **Runc**6。**Runc** 与系统内核交互,创建 Namespaces 和 Cgroups 7. **Runc** 启动 nginx 进程后退出 8. **Shim** 接管容器 IO 和生命周期监控 @@ -108,7 +108,7 @@ flowchart TD 从 Docker Engine v29 (2025/2026) 开始,架构进一步简化和标准化: - **Containerd 镜像存储 (Image Store)**:默认启用。Docker 直接使用 Containerd 的镜像管理能力,不再维护自己的一套 graphdriver。 - - **优势**:多平台镜像支持更好、镜像拉取更快(lazy pulling)、与 K8s 共享镜像。 + - **优势**:多平台镜像支持更好、镜像拉取更快 (lazy pulling)、与 K8s 共享镜像。 --- @@ -127,8 +127,8 @@ flowchart TD end ``` -- 使用轻量级虚拟机(Apple Virtualization / WSL 2)运行 Linux 内核 -- 文件挂载(Bind Mount)需要跨越 VM 边界(这也是文件 I/O 慢的原因) +- 使用轻量级虚拟机 (Apple Virtualization / WSL 2) 运行 Linux 内核 +- 文件挂载 (Bind Mount) 需要跨越 VM 边界 (这也是文件 I/O 慢的原因) - 网络端口需要从宿主机转发到 VM --- diff --git a/14_implementation/14.2_namespace.md b/14_implementation/14.2_namespace.md index dd011f9..c9951df 100644 --- a/14_implementation/14.2_namespace.md +++ b/14_implementation/14.2_namespace.md @@ -1,8 +1,8 @@ -命名空间(Namespace)是 Linux 内核的一个强大特性,为容器提供了隔离的运行环境。 +命名空间 (Namespace) 是 Linux 内核的一个强大特性,为容器提供了隔离的运行环境。 -### 什么是 Namespace +## 什么是 Namespace -> **Namespace 是 Linux 内核提供的资源隔离机制,它让容器内的进程仿佛运行在独立的操作系统中。**Namespace 是容器技术的核心基础之一。它回答了一个关键问题:**如何让一个进程"以为"自己独占整个系统?** +> **Namespace 是 Linux 内核提供的资源隔离机制,它让容器内的进程仿佛运行在独立的操作系统中。**Namespace 是容器技术的核心基础之一。它回答了一个关键问题:**如何让一个进程 “以为” 自己独占整个系统?** ```mermaid flowchart LR @@ -71,7 +71,7 @@ PID USER COMMAND - 容器内的 PID 1 进程特殊重要——它是容器的主进程,退出则容器停止 - 容器内无法看到宿主机或其他容器的进程 -- 宿主机可以看到所有容器内的进程(但 PID 不同) +- 宿主机可以看到所有容器内的进程 (但 PID 不同) --- @@ -85,6 +85,8 @@ NET Namespace 负责网络栈的隔离,包括网卡、路由表和 iptables #### NET 隔离效果 +如下代码块所示,展示了相关示例: + ```mermaid flowchart LR subgraph Host ["宿主机"] @@ -105,7 +107,7 @@ flowchart LR #### NET 关键点 - 每个容器有独立的网卡、IP、路由表、iptables 规则 -- 多个容器可以监听相同端口(如都监听 80) +- 多个容器可以监听相同端口 (如都监听 80) - Docker 使用 veth pair 连接容器网络和宿主机网桥 --- @@ -120,6 +122,8 @@ MNT Namespace 负责文件系统挂载点的隔离,确保容器看到独立的 #### MNT 隔离效果 +如下代码块所示,展示了相关示例: + ``` 宿主机文件系统: 容器内看到的: / / ← 容器的根目录 @@ -167,7 +171,7 @@ $ docker run --hostname mycontainer ubuntu hostname mycontainer ``` -UTS = "UNIX Time-sharing System",是历史遗留的名称。 +UTS = “UNIX Time-sharing System”,是历史遗留的名称。 --- @@ -181,14 +185,14 @@ IPC Namespace 用于隔离进程间通信资源,如 System V IPC 和 POSIX 消 #### 隔离的资源 -- 信号量(semaphores) -- 消息队列(message queues) -- 共享内存(shared memory) +- 信号量 (semaphores) +- 消息队列 (message queues) +- 共享内存 (shared memory) #### IPC 关键点 - 同一容器内的进程可以通过 IPC 通信 -- 不同容器的进程无法通过 IPC 通信(除非显式共享) +- 不同容器的进程无法通过 IPC 通信 (除非显式共享) --- @@ -202,6 +206,8 @@ USER Namespace 允许将容器内的用户 ID 映射到宿主机的不同用户 #### USER 隔离效果 +如下代码块所示,展示了相关示例: + ```mermaid flowchart LR subgraph Container ["容器内"] diff --git a/14_implementation/14.3_cgroups.md b/14_implementation/14.3_cgroups.md index 8f9f12a..a428dd0 100644 --- a/14_implementation/14.3_cgroups.md +++ b/14_implementation/14.3_cgroups.md @@ -1,10 +1,10 @@ ## 14.3 控制组 -控制组(Cgroups)是 Linux 内核提供的另一种关键机制,主要用于资源的限制和审计。 +控制组 (Cgroups) 是 Linux 内核提供的另一种关键机制,主要用于资源的限制和审计。 ### 什么是控制组 -控制组(Control Groups,简称 cgroups)是 Linux 内核的一个特性,用于**限制、记录和隔离**进程组的资源使用(CPU、内存、磁盘 I/O、网络等)。 +控制组 (Control Groups,简称 cgroups) 是 Linux 内核的一个特性,用于**限制、记录和隔离**进程组的资源使用 (CPU、内存、磁盘 I/O、网络等)。 > **核心作用**:让多个容器公平共享宿主机资源,防止单个容器耗尽系统资源。 @@ -163,6 +163,8 @@ $ docker inspect mycontainer --format '{{json .HostConfig}}' | jq ### 资源限制的效果 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 内存超限 运行以下命令: @@ -213,6 +215,10 @@ $ docker run --rm --cpus=1 stress --cpu 4 | PSI(压力监控) | ❌ | ✅ | | rootless 容器 | 部分支持 | 完整支持 | +#### 概述 + +总体概述了以下内容。 + #### 检查系统使用的版本 运行以下命令: @@ -235,7 +241,7 @@ nodev cgroup2 ### 在 Compose 中设置限制 -在 Compose 中设置限制 配置如下: +在 Compose 中设置限制配置如下: ```yaml services: @@ -257,7 +263,7 @@ services: 在使用 Cgroups 限制资源时,遵循一些最佳实践可以避免潜在的问题。 -#### 1. 始终设置内存限制 +#### 1。始终设置内存限制 运行以下命令: @@ -267,7 +273,7 @@ services: $ docker run -m 1g myapp ``` -#### 2. 为关键应用设置 CPU 保证 +#### 2。为关键应用设置 CPU 保证 运行以下命令: @@ -275,7 +281,7 @@ $ docker run -m 1g myapp $ docker run --cpus=2 --cpu-shares=2048 critical-app ``` -#### 3. 监控资源使用 +#### 3。监控资源使用 运行以下命令: diff --git a/14_implementation/14.4_ufs.md b/14_implementation/14.4_ufs.md index 56eb678..e79a0a3 100644 --- a/14_implementation/14.4_ufs.md +++ b/14_implementation/14.4_ufs.md @@ -1,10 +1,10 @@ ## 14.4 联合文件系统 -联合文件系统(UnionFS)是 Docker 镜像分层存储的基础,它允许将多个目录挂载为同一个虚拟文件系统。 +联合文件系统 (UnionFS) 是 Docker 镜像分层存储的基础,它允许将多个目录挂载为同一个虚拟文件系统。 ### 什么是联合文件系统 -联合文件系统(UnionFS)是一种**分层、轻量级**的文件系统,它将多个目录"联合"挂载到同一个虚拟目录,形成一个统一的文件系统视图。 +联合文件系统 (UnionFS) 是一种**分层、轻量级**的文件系统,它将多个目录 “联合” 挂载到同一个虚拟目录,形成一个统一的文件系统视图。 > **核心思想**:将多个只读层叠加,最上层可写,形成完整的文件系统。 @@ -28,7 +28,9 @@ flowchart TD Docker 选择联合文件系统作为其存储驱动,主要基于以下几个核心优势。 -#### 1. 镜像分层复用 +#### 1。镜像分层复用 + +如下代码块所示,展示了相关示例: ```mermaid flowchart TD @@ -38,7 +40,7 @@ flowchart TD 多个镜像共享相同的底层,节省磁盘空间。 -#### 2. 快速构建 +#### 2。快速构建 每个 Dockerfile 指令创建一层,只有变化的层需要重建: @@ -49,9 +51,9 @@ RUN npm install # 层3:安装依赖 COPY . . # 层4:应用代码 ``` -代码变化时,只需重建层4,层1-3 使用缓存。 +代码变化时,只需重建层 4,层 1-3 使用缓存。 -#### 3. 容器启动快 +#### 3。容器启动快 容器启动时不需要复制镜像,只需: 1. 在镜像层上创建一个薄的可写层 @@ -59,7 +61,7 @@ COPY . . # 层4:应用代码 --- -### Copy-on-Write(写时复制) +### Copy-on-Write (写时复制) 当容器修改只读层中的文件时: @@ -141,11 +143,15 @@ flowchart TD OverlayFS --> Lower1 ``` -- **lowerdir**:只读的镜像层(可以有多个) +- **lowerdir**:只读的镜像层 (可以有多个) - **upperdir**:可写的容器层 - **workdir**:OverlayFS 的工作目录 - **merged**:联合挂载后的视图 +#### 概述 + +总体概述了以下内容。 + #### 文件操作行为 | 操作 | 行为 | @@ -190,7 +196,9 @@ $ docker inspect nginx:alpine --format '{{json .GraphDriver.Data}}' | jq 为了构建高效、轻量的镜像,我们在使用联合文件系统时应注意以下几点。 -#### 1. 减少镜像层数 +#### 1。减少镜像层数 + +如下代码块所示,展示了相关示例: ```docker ## ❌ 每条命令创建一层 @@ -206,13 +214,13 @@ RUN apt-get update && \ rm -rf /var/lib/apt/lists/* ``` -#### 2. 避免在容器中写入大量数据 +#### 2。避免在容器中写入大量数据 容器层的写入性能低于直接写入。大量数据应使用: -- 数据卷(Volume) -- 绑定挂载(Bind Mount) +- 数据卷 (Volume) +- 绑定挂载 (Bind Mount) -#### 3. 使用 .dockerignore +#### 3。使用。dockerignore 排除不需要的文件可以: - 减小构建上下文 diff --git a/14_implementation/14.6_network.md b/14_implementation/14.6_network.md index 7c81a49..138843b 100644 --- a/14_implementation/14.6_network.md +++ b/14_implementation/14.6_network.md @@ -1,15 +1,15 @@ ## 14.6 Docker 网络实现 -Docker 的网络实现其实就是利用了 Linux 上的网络命名空间和虚拟网络设备(特别是 veth pair)。建议先熟悉了解这两部分的基本概念再阅读本章。 +Docker 的网络实现其实就是利用了 Linux 上的网络命名空间和虚拟网络设备 (特别是 veth pair)。建议先熟悉了解这两部分的基本概念再阅读本章。 ### 基本原理 -首先,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)来收发数据包;此外,如果不同子网之间要进行通信,需要路由机制。 +首先,要实现网络通信,机器需要至少一个网络接口 (物理接口或虚拟接口) 来收发数据包;此外,如果不同子网之间要进行通信,需要路由机制。 Docker 中的网络接口默认都是虚拟的接口。虚拟接口的优势之一是转发效率较高。 Linux 通过在内核中进行数据复制来实现虚拟接口之间的数据转发,发送接口的发送缓存中的数据包被直接复制到接收接口的接收缓存中。对于本地系统和容器内系统看来就像是一个正常的以太网卡,只是它不需要真正同外部网络设备通信,速度要快很多。 -Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通(这样的一对接口叫做 `veth pair`)。 +Docker 容器网络就利用了这项技术。它在本地主机和容器内分别创建一个虚拟接口,并让它们彼此连通 (这样的一对接口叫做 `veth pair`)。 ### 创建网络参数 @@ -21,7 +21,7 @@ Docker 创建一个容器的时候,会执行如下操作: 完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。 -可以在 `docker run` 的时候通过 `--net` 参数来指定容器的网络配置,有4个可选值: +可以在 `docker run` 的时候通过 `--net` 参数来指定容器的网络配置,有 4 个可选值: * `--net=bridge` 这个是默认值,连接到默认的网桥。 * `--net=host` 告诉 Docker 不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如 D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用 `--privileged=true`,容器会被允许直接配置主机的网络堆栈。 * `--net=container:NAME_or_ID` 让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过 `lo` 环回接口通信。 @@ -57,7 +57,7 @@ $ sudo ip link add A type veth peer name B $ sudo brctl addif docker0 A $ 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/14_implementation/README.md b/14_implementation/README.md index 18bdc98..9a985f5 100644 --- a/14_implementation/README.md +++ b/14_implementation/README.md @@ -1,16 +1,16 @@ -# 第十四章 底层实现 +# 第十四章底层实现 -Docker 底层的核心技术包括 Linux 上的命名空间(Namespaces)、控制组(Control groups)、Union 文件系统(Union file systems)和容器格式(Container format)。 +Docker 底层的核心技术包括 Linux 上的命名空间 (Namespaces)、控制组 (Control groups)、Union 文件系统 (Union file systems) 和容器格式 (Container format)。 我们知道,传统的虚拟机通过在宿主主机中运行 hypervisor 来模拟一整套完整的硬件环境提供给虚拟机的操作系统。虚拟机系统看到的环境是可限制的,也是彼此隔离的。 这种直接的做法实现了对资源最完整的封装,但很多时候往往意味着系统资源的浪费。 例如,以宿主机和虚拟机系统都为 Linux 系统为例,虚拟机中运行的应用其实可以利用宿主机系统中的运行环境。 我们知道,在操作系统中,包括内核、文件系统、网络、PID、UID、IPC、内存、硬盘、CPU 等等,所有的资源都是应用进程直接共享的。 -要想实现虚拟化,除了要实现对内存、CPU、网络IO、硬盘IO、存储空间等的限制外,还要实现文件系统、网络、PID、UID、IPC等等的相互隔离。 +要想实现虚拟化,除了要实现对内存、CPU、网络 IO、硬盘 IO、存储空间等的限制外,还要实现文件系统、网络、PID、UID、IPC 等等的相互隔离。 前者相对容易实现一些,后者则需要宿主机系统的深入支持。 -随着 Linux 系统对于命名空间功能的完善实现,程序员已经可以实现上面的所有需求,让某些进程在彼此隔离的命名空间中运行。大家虽然都共用一个内核和某些运行时环境(例如一些系统命令和系统库),但是彼此却看不到,都以为系统中只有自己的存在。这种机制就是容器(Container),利用命名空间来做权限的隔离控制,利用 cgroups 来做资源分配。 +随着 Linux 系统对于命名空间功能的完善实现,程序员已经可以实现上面的所有需求,让某些进程在彼此隔离的命名空间中运行。大家虽然都共用一个内核和某些运行时环境 (例如一些系统命令和系统库),但是彼此却看不到,都以为系统中只有自己的存在。这种机制就是容器 (Container),利用命名空间来做权限的隔离控制,利用 cgroups 来做资源分配。 * [基本架构](14.1_arch.md) * [命名空间](14.2_namespace.md) diff --git a/14_implementation/summary.md b/14_implementation/summary.md index 7f88018..acc4a23 100644 --- a/14_implementation/summary.md +++ b/14_implementation/summary.md @@ -11,7 +11,7 @@ ### 延伸阅读 -- [控制组(Cgroups)](14.3_cgroups.md):资源限制机制 +- [控制组 (Cgroups)](14.3_cgroups.md):资源限制机制 - [联合文件系统](14.4_ufs.md):分层存储的实现 - [安全](../11_ops/security/README.md):容器安全实践 - [Linux Namespace 官方文档](https://man7.org/linux/man-pages/man7/namespaces.7.html) diff --git a/15_cases/README.md b/15_cases/README.md index 20ca701..102a49e 100644 --- a/15_cases/README.md +++ b/15_cases/README.md @@ -1,4 +1,4 @@ -# 第十五章 实战案例 +# 第十五章实战案例 本章将介绍 Docker 在不同场景下的实战案例。 diff --git a/15_cases/ci/README.md b/15_cases/ci/README.md index 8f33f8c..7dc25b8 100644 --- a/15_cases/ci/README.md +++ b/15_cases/ci/README.md @@ -1,6 +1,6 @@ # CI/CD -**持续集成(Continuous integration)**是一种软件开发实践,每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。**持续部署(continuous deployment)** 是通过自动化的构建、测试和部署循环来快速交付高质量的产品。 +**持续集成 (Continuous integration)**是一种软件开发实践,每次集成都通过自动化的构建 (包括编译,发布,自动化测试) 来验证,从而尽早地发现集成错误。**持续部署 (continuous deployment)** 是通过自动化的构建、测试和部署循环来快速交付高质量的产品。 与 `Jenkins` 不同的是,基于 Docker 的 CI/CD 每一步都运行在 Docker 容器中,所以理论上支持所有的编程语言。 diff --git a/15_cases/ci/actions/README.md b/15_cases/ci/actions/README.md index 2048652..302e0e3 100644 --- a/15_cases/ci/actions/README.md +++ b/15_cases/ci/actions/README.md @@ -23,6 +23,10 @@ jobs: args: go version ``` +## 概述 + +总体概述了以下内容。 + ## 参考资料 * [Actions Docs](https://docs.github.com/en/actions) diff --git a/15_cases/ci/devops_workflow.md b/15_cases/ci/devops_workflow.md index c9798a3..26aa575 100644 --- a/15_cases/ci/devops_workflow.md +++ b/15_cases/ci/devops_workflow.md @@ -1,20 +1,22 @@ ## DevOps 工作流完整示例 -本章将演示一个基于 Docker, Kubernetes 和 Jenkins/GitLab CI 的完整 DevOps 工作流。 +本章将演示一个基于 Docker,Kubernetes 和 Jenkins/GitLab CI 的完整 DevOps 工作流。 ### 工作流概览 -1. **Code**: 开发人员提交代码到 GitLab。 -2. **Build**: GitLab CI 触发构建任务。 -3. **Test**: 运行单元测试和集成测试。 -4. **Package**: 构建 Docker 镜像并推送到 Harbor/Registry。 -5. **Deploy (Staging)**: 自动部署到测试环境 Kubernetes 集群。 -6. **Verify**: 人工或自动化验证。 -7. **Release (Production)**: 审批后自动部署到生产环境。 +1. **Code**:开发人员提交代码到 GitLab。 +2. **Build**:GitLab CI 触发构建任务。 +3. **Test**:运行单元测试和集成测试。 +4. **Package**:构建 Docker 镜像并推送到 Harbor/Registry。 +5. **Deploy (Staging)**:自动部署到测试环境 Kubernetes 集群。 +6. **Verify**:人工或自动化验证。 +7. **Release (Production)**:审批后自动部署到生产环境。 ### 关键配置示例 -#### 1. Dockerfile 多阶段构建 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 1。Dockerfile 多阶段构建 使用 Docker 多阶段构建可以有效减小镜像体积。 @@ -37,9 +39,9 @@ COPY --from=builder /app/main . CMD ["./main"] ``` -#### 2. GitLab CI 配置 +#### 2。GitLab CI 配置 -GitLab CI(.gitlab-ci.yml)配置如下: +GitLab CI (。gitlab-ci.yml) 配置如下: ```yaml @@ -79,6 +81,6 @@ deploy_staging: ### 最佳实践 -1. **不可变基础设施**: 一旦镜像构建完成,在各个环境(Dev, Staging, Prod)中都应该使用同一个镜像 tag (通常是 commit hash),而不是重新构建。 -2. **配置分离**: 使用 ConfigMap 和 Secret 管理环境特定的配置,不要打包进镜像。 -3. **GitOps**: 考虑引入 ArgoCD,将部署配置也作为代码存储在 Git 中,实现 Git 驱动的部署同步。 +1. **不可变基础设施**:一旦镜像构建完成,在各个环境 (Dev,Staging,Prod) 中都应该使用同一个镜像 tag (通常是 commit hash),而不是重新构建。 +2. **配置分离**:使用 ConfigMap 和 Secret 管理环境特定的配置,不要打包进镜像。 +3. **GitOps**:考虑引入 ArgoCD,将部署配置也作为代码存储在 Git 中,实现 Git 驱动的部署同步。 diff --git a/15_cases/ci/drone/README.md b/15_cases/ci/drone/README.md index 8357437..80c7063 100644 --- a/15_cases/ci/drone/README.md +++ b/15_cases/ci/drone/README.md @@ -10,7 +10,7 @@ 在 Github 新建一个名为 `drone-demo` 的仓库。 -打开我们已经 [部署好的 Drone 网站](install.md) 或者 [Drone Cloud](https://cloud.drone.io),使用 GitHub 账号登录,在界面中关联刚刚新建的 `drone-demo` 仓库。 +打开我们已经[部署好的 Drone 网站](install.md)或者 [Drone Cloud](https://cloud.drone.io),使用 GitHub 账号登录,在界面中关联刚刚新建的 `drone-demo` 仓库。 ## 编写项目源代码 diff --git a/15_cases/ci/drone/demo/README.md b/15_cases/ci/drone/demo/README.md index d7cb1cd..2942921 100644 --- a/15_cases/ci/drone/demo/README.md +++ b/15_cases/ci/drone/demo/README.md @@ -4,9 +4,9 @@ ## 目录结构 -* `app.go`: 简单的 Go Web 服务器代码。 -* `.drone.yml`: Drone CI 的配置文件,定义了构建和测试流程。 -* `Dockerfile`: 定义了如何将该应用构建为 Docker 镜像。 +* `app.go`:简单的 Go Web 服务器代码。 +* `.drone.yml`:Drone CI 的配置文件,定义了构建和测试流程。 +* `Dockerfile`:定义了如何将该应用构建为 Docker 镜像。 ## 如何运行 diff --git a/15_cases/ci/drone/install.md b/15_cases/ci/drone/install.md index 1e0025f..93376aa 100644 --- a/15_cases/ci/drone/install.md +++ b/15_cases/ci/drone/install.md @@ -1,5 +1,7 @@ ## 部署 Drone +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 要求 * 拥有公网 IP、域名 (如果你不满足要求,可以尝试在本地使用 Gogs + Drone) @@ -22,7 +24,7 @@ ### 配置 Drone -我们通过使用 `Docker Compose` 来启动 `Drone`,编写 `compose.yaml`(或 `docker-compose.yml`)文件。 +我们通过使用 `Docker Compose` 来启动 `Drone`,编写 `compose.yaml` (或 `docker-compose.yml`) 文件。 ```yaml services: @@ -80,6 +82,10 @@ DRONE_GITHUB_CLIENT_ID= DRONE_GITHUB_CLIENT_SECRET= ``` +#### 概述 + +总体概述了以下内容。 + #### 启动 Drone 运行以下命令: diff --git a/15_cases/ide/vsCode.md b/15_cases/ide/vsCode.md index a85a280..446b480 100644 --- a/15_cases/ide/vsCode.md +++ b/15_cases/ide/vsCode.md @@ -1,5 +1,11 @@ ## VS Code 中使用 Docker +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +### 概述 + +总体概述了以下内容。 + ### 将 Docker 容器作为远程开发环境 -无需本地安装开发工具,直接将 Docker 容器作为开发环境,具体参考 [官方文档](https://code.visualstudio.com/docs/remote/containers)。 +无需本地安装开发工具,直接将 Docker 容器作为开发环境,具体参考[官方文档](https://code.visualstudio.com/docs/remote/containers)。 diff --git a/15_cases/os/alpine.md b/15_cases/os/alpine.md index d6d1e85..7918b95 100644 --- a/15_cases/os/alpine.md +++ b/15_cases/os/alpine.md @@ -1,16 +1,20 @@ ## Alpine +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 简介 +下图直观地展示了本节内容: + ![Alpine Linux 操作系统](../../_images/alpinelinux-logo.png) `Alpine` 操作系统是一个面向安全的轻型 `Linux` 发行版。它不同于通常 `Linux` 发行版,`Alpine` 采用了 `musl libc` 和 `busybox` 以减小系统的体积和运行时资源消耗,但功能上比 `busybox` 又完善的多,因此得到开源社区越来越多的青睐。在保持瘦身的同时,`Alpine` 还提供了自己的包管理工具 `apk`,可以通过 [Alpine Packages](https://pkgs.alpinelinux.org/packages) 网站上查询包信息,也可以直接通过 `apk` 命令直接查询和安装各种软件。 -`Alpine` 由非商业组织维护的,支持广泛场景的 `Linux`发行版,它特别为资深/重度`Linux`用户而优化,关注安全,性能和资源效能。`Alpine` 镜像可以适用于更多常用场景,并且是一个优秀的可以适用于生产的基础系统/环境。 +`Alpine` 由非商业组织维护的,支持广泛场景的 `Linux` 发行版,它特别为资深/重度 `Linux` 用户而优化,关注安全,性能和资源效能。`Alpine` 镜像可以适用于更多常用场景,并且是一个优秀的可以适用于生产的基础系统/环境。 -`Alpine` Docker 镜像也继承了 `Alpine Linux` 发行版的这些优势。相比于其他 `Docker` 镜像,它的容量非常小,仅仅只有 **5 MB** 左右(对比 `Ubuntu` 系列镜像接近 `200 MB`),且拥有非常友好的包管理机制。官方镜像来自 `docker-alpine` 项目。 +`Alpine` Docker 镜像也继承了 `Alpine Linux` 发行版的这些优势。相比于其他 `Docker` 镜像,它的容量非常小,仅仅只有 **5 MB** 左右 (对比 `Ubuntu` 系列镜像接近 `200 MB`),且拥有非常友好的包管理机制。官方镜像来自 `docker-alpine` 项目。 目前 Docker 官方已开始推荐使用 `Alpine` 替代之前的 `Ubuntu` 做为基础镜像环境。这样会带来多个好处。包括镜像下载速度加快,镜像安全性提高,主机之间的切换更方便,占用更少磁盘空间等。 diff --git a/15_cases/os/busybox.md b/15_cases/os/busybox.md index f10fe09..f135b7b 100644 --- a/15_cases/os/busybox.md +++ b/15_cases/os/busybox.md @@ -1,13 +1,17 @@ ## Busybox +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 简介 +下图直观地展示了本节内容: + ![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` 等。 ### 获取官方镜像 diff --git a/15_cases/os/centos.md b/15_cases/os/centos.md index 2fb0d21..05c875b 100644 --- a/15_cases/os/centos.md +++ b/15_cases/os/centos.md @@ -1,5 +1,7 @@ ## CentOS 和 Fedora +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### CentOS 系统简介 `CentOS` 和 `Fedora` 都是基于 `Redhat` 的常见 Linux 分支。`CentOS` 是目前企业级服务器的常用操作系统;`Fedora` 则主要面向个人桌面用户。 @@ -7,14 +9,18 @@ ![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 官方镜像 CentOS 官方镜像的使用非常简单。 -**注意:CentOS 8 已于 2021 年 12 月 31 日停止维护(EOL)。对于新部署,推荐使用 CentOS Stream,或 Rocky Linux、AlmaLinux 等替代发行版。** +**注意:CentOS 8 已于 2021 年 12 月 31 日停止维护 (EOL)。对于新部署,推荐使用 CentOS Stream,或 Rocky Linux、AlmaLinux 等替代发行版。** 使用 `docker run` 直接运行 `CentOS 7` 镜像,并登录 `bash`。 @@ -31,11 +37,17 @@ CentOS Linux release 7.9.2009 (Core) ### Fedora 系统简介 +下图直观地展示了本节内容: + ![Fedora 操作系统](../../_images/fedora-logo.png) `Fedora` 由 `Fedora Project` 社区开发,红帽公司赞助的 `Linux` 发行版。它的目标是创建一套新颖、多功能并且自由和开源的操作系统。`Fedora` 的功能对于用户而言,它是一套功能完备的,可以更新的免费操作系统,而对赞助商 `Red Hat` 而言,它是许多新技术的测试平台。被认为可用的技术最终会加入到 `Red Hat Enterprise Linux` 中。 +#### 概述 + +总体概述了以下内容。 + #### 使用 Fedora 官方镜像 使用 `docker run` 命令直接运行 `Fedora` 官方镜像,并登录 `bash`。 diff --git a/15_cases/os/debian.md b/15_cases/os/debian.md index 1b06498..d6a174e 100644 --- a/15_cases/os/debian.md +++ b/15_cases/os/debian.md @@ -1,18 +1,24 @@ ## Debian Ubuntu -`Debian` 和 `Ubuntu` 都是目前较为流行的 **Debian 系** 的服务器操作系统,十分适合研发场景。`Docker Hub` 上提供了官方镜像,国内各大容器云服务也基本都提供了相应的支持。 +`Debian` 和 `Ubuntu` 都是目前较为流行的 **Debian 系**的服务器操作系统,十分适合研发场景。`Docker Hub` 上提供了官方镜像,国内各大容器云服务也基本都提供了相应的支持。 ### Debian 系统简介 +下图直观地展示了本节内容: + ![Debian 操作系统](../../_images/debian-logo.png) -`Debian` 是由 `GPL` 和其他自由软件许可协议授权的自由软件组成的操作系统,由 **Debian 计划(Debian Project)**组织维护。**Debian 计划** 是一个独立的、分散的组织,由 `3000` 人志愿者组成,接受世界多个非盈利组织的资金支持,`Software in the Public Interest` 提供支持并持有商标作为保护机构。`Debian` 以其坚守 `Unix` 和自由软件的精神,以及其给予用户的众多选择而闻名。现时 `Debian` 包括了超过 `25,000` 个软件包并支持 `12` 个计算机系统结构。 +`Debian` 是由 `GPL` 和其他自由软件许可协议授权的自由软件组成的操作系统,由 **Debian 计划 (Debian Project)**组织维护。**Debian 计划**是一个独立的、分散的组织,由 `3000` 人志愿者组成,接受世界多个非盈利组织的资金支持,`Software in the Public Interest` 提供支持并持有商标作为保护机构。`Debian` 以其坚守 `Unix` 和自由软件的精神,以及其给予用户的众多选择而闻名。现时 `Debian` 包括了超过 `25,000` 个软件包并支持 `12` 个计算机系统结构。 `Debian` 作为一个大的系统组织框架,其下有多种不同操作系统核心的分支计划,主要为采用 `Linux` 核心的 `Debian GNU/Linux` 系统,其他还有采用 `GNU Hurd` 核心的 `Debian GNU/Hurd` 系统、采用 `FreeBSD` 核心的 `Debian GNU/kFreeBSD` 系统,以及采用 `NetBSD` 核心的 `Debian GNU/NetBSD` 系统。甚至还有利用 `Debian` 的系统架构和工具,采用 `OpenSolaris` 核心构建而成的 `Nexenta OS` 系统。在这些 `Debian` 系统中,以采用 `Linux` 核心的 `Debian GNU/Linux` 最为著名。 众多的 `Linux` 发行版,例如 `Ubuntu`、`Knoppix` 和 `Linspire` 及 `Xandros` 等,都基于 `Debian GNU/Linux`。 +#### 概述 + +总体概述了以下内容。 + #### 使用 Debian 官方镜像 Debian 是一个也是一个常用的基础镜像。 @@ -30,10 +36,16 @@ Debian GNU/Linux 8 ### Ubuntu 系统简介 +下图直观地展示了本节内容: + ![Ubuntu 操作系统](../../_images/ubuntu-logo.jpg) -`Ubuntu` 是一个以桌面应用为主的 `GNU/Linux` 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词(官方译名“友帮拓”,另有“吾帮托”、“乌班图”、“有奔头”或“乌斑兔”等译名)。`Ubuntu` 意思是“人性”以及“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。 `Ubuntu` 基于 `Debian` 发行版和 `GNOME/Unity` 桌面环境,与 `Debian` 的不同在于它每 6 个月会发布一个新版本,每 2 年推出一个长期支持 **(Long Term Support,LTS)** 版本,一般支持 3 年时间。 +`Ubuntu` 是一个以桌面应用为主的 `GNU/Linux` 操作系统,其名称来自非洲南部祖鲁语或豪萨语的 “ubuntu” 一词 (官方译名 “友帮拓”,另有 “吾帮托”、“乌班图”、“有奔头” 或 “乌斑兔” 等译名)。`Ubuntu` 意思是 “人性” 以及 “我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的 “仁爱” 思想。`Ubuntu` 基于 `Debian` 发行版和 `GNOME/Unity` 桌面环境,与 `Debian` 的不同在于它每 6 个月会发布一个新版本,每 2 年推出一个长期支持 **(Long Term Support,LTS)** 版本,一般支持 3 年时间。 + +#### 概述 + +总体概述了以下内容。 #### 使用 Ubuntu 官方镜像 diff --git a/15_cases/os/summary.md b/15_cases/os/summary.md index 4b31465..227bcdf 100644 --- a/15_cases/os/summary.md +++ b/15_cases/os/summary.md @@ -6,6 +6,6 @@ 读者可以根据具体情况来选择。一般来说: -* 官方镜像体积都比较小,只带有一些基本的组件。 精简的系统有利于安全、稳定和高效的运行,也适合进行个性化定制。 +* 官方镜像体积都比较小,只带有一些基本的组件。精简的系统有利于安全、稳定和高效的运行,也适合进行个性化定制。 * 出于安全考虑,几乎所有官方制作的镜像都没有安装 SSH 服务,无法通过用户名和密码直接登录到容器中。 diff --git a/16_appendix/16.1_best_practices.md b/16_appendix/16.1_best_practices.md index 1f13072..f0a9ba6 100644 --- a/16_appendix/16.1_best_practices.md +++ b/16_appendix/16.1_best_practices.md @@ -4,9 +4,11 @@ ### 一般性的指南和建议 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 容器应该是短暂的 -通过 `Dockerfile` 构建的镜像所启动的容器应该尽可能短暂(生命周期短)。「短暂」意味着可以停止和销毁容器,并且创建一个新容器并部署好所需的设置和配置工作量应该是极小的。 +通过 `Dockerfile` 构建的镜像所启动的容器应该尽可能短暂 (生命周期短)。“短暂” 意味着可以停止和销毁容器,并且创建一个新容器并部署好所需的设置和配置工作量应该是极小的。 #### 使用 `.dockerignore` 文件 @@ -14,7 +16,7 @@ #### 使用多阶段构建 -在 Docker 17.05 以上版本中,你可以使用 [多阶段构建](../07_dockerfile/7.17_multistage_builds.md) 来减少所构建镜像的大小。 +在 Docker 17.05 以上版本中,你可以使用[多阶段构建](../07_dockerfile/7.17_multistage_builds.md)来减少所构建镜像的大小。 #### 避免安装不必要的包 @@ -22,17 +24,17 @@ #### 一个容器只运行一个进程 -应该保证在一个容器中只运行一个进程。将多个应用解耦到不同容器中,保证了容器的横向扩展和复用。例如 web 应用应该包含三个容器:web应用、数据库、缓存。 +应该保证在一个容器中只运行一个进程。将多个应用解耦到不同容器中,保证了容器的横向扩展和复用。例如 web 应用应该包含三个容器:web 应用、数据库、缓存。 -如果容器互相依赖,你可以使用 [Docker 自定义网络](../08_data_network/network/README.md) 来把这些容器连接起来。 +如果容器互相依赖,你可以使用 [Docker 自定义网络](../08_data_network/network/README.md)来把这些容器连接起来。 #### 镜像层数尽可能少 -你需要在 `Dockerfile` 可读性(也包括长期的可维护性)和减少层数之间做一个平衡。 +你需要在 `Dockerfile` 可读性 (也包括长期的可维护性) 和减少层数之间做一个平衡。 #### 将多行参数排序 -将多行参数按字母顺序排序(比如要安装多个包时)。这可以帮助你避免重复包含同一个包,更新包列表时也更容易。也便于 `PRs` 阅读和审查。建议在反斜杠符号 `\` 之前添加一个空格,以增加可读性。 +将多行参数按字母顺序排序 (比如要安装多个包时)。这可以帮助你避免重复包含同一个包,更新包列表时也更容易。也便于 `PRs` 阅读和审查。建议在反斜杠符号 `\` 之前添加一个空格,以增加可读性。 下面是来自 `buildpack-deps` 镜像的例子: @@ -51,7 +53,7 @@ RUN apt-get update && apt-get install -y \ 但是,如果你想在构建的过程中使用缓存,你得明白什么时候会,什么时候不会找到匹配的镜像,遵循的基本规则如下: -* 从一个基础镜像开始(`FROM` 指令指定),下一条指令将和该基础镜像的所有子镜像进行匹配,检查这些子镜像被创建时使用的指令是否和被检查的指令完全一样。如果不是,则缓存失效。 +* 从一个基础镜像开始 (`FROM` 指令指定),下一条指令将和该基础镜像的所有子镜像进行匹配,检查这些子镜像被创建时使用的指令是否和被检查的指令完全一样。如果不是,则缓存失效。 * 在大多数情况下,只需要简单地对比 `Dockerfile` 中的指令和子镜像。然而,有些指令需要更多的检查和解释。 * 对于 `ADD` 和 `COPY` 指令,镜像中对应文件的内容也会被检查,每个文件都会计算出一个校验和。文件的最后修改时间和最后访问时间不会纳入校验。在缓存的查找过程中,会将这些校验和和已存在镜像中的文件校验和进行对比。如果文件有任何改变,比如内容和元数据,则缓存失效。 * 除了 `ADD` 和 `COPY` 指令,缓存匹配过程不会查看临时容器中的文件来决定缓存是否匹配。例如,当执行完 `RUN apt-get -y update` 指令后,容器中一些文件被更新,但 Docker 不会检查这些文件。这种情况下,只有指令字符串本身被用来匹配缓存。 @@ -64,7 +66,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 @@ -102,11 +104,15 @@ LABEL vendor=ACME\ Incorporated \ 为了保持 `Dockerfile` 文件的可读性,可理解性,以及可维护性,建议将长的或复杂的 `RUN` 指令用反斜杠 `\` 分割成多行。 +##### 概述 + +总体概述了以下内容。 + ##### apt-get `RUN` 指令最常见的用法是安装包用的 `apt-get`。因为 `RUN apt-get` 指令会安装包,所以有几个问题需要注意。 -不要使用 `RUN apt-get upgrade` 或 `dist-upgrade`,因为许多基础镜像中的「必须」包不会在一个非特权容器中升级。如果基础镜像中的某个包过时了,你应该联系它的维护者。如果你确定某个特定的包,比如 `foo`,需要升级,使用 `apt-get install -y foo` 就行,该指令会自动升级 `foo` 包。 +不要使用 `RUN apt-get upgrade` 或 `dist-upgrade`,因为许多基础镜像中的 “必须” 包不会在一个非特权容器中升级。如果基础镜像中的某个包过时了,你应该联系它的维护者。如果你确定某个特定的包,比如 `foo`,需要升级,使用 `apt-get install -y foo` 就行,该指令会自动升级 `foo` 包。 永远将 `RUN apt-get update` 和 `apt-get install` 组合成一条 `RUN` 声明,例如: @@ -174,9 +180,9 @@ 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"]` 形式的命令。我们建议任何服务镜像都使用这种形式的命令。 -多数情况下,`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 @@ -206,7 +212,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` 所有文件,这将保证每个步骤的构建缓存只在特定的文件变化时失效。例如: @@ -245,9 +251,9 @@ RUN mkdir -p /usr/src/things \ #### ENTRYPOINT -`ENTRYPOINT` 的最佳用处是设置镜像的主命令,允许将镜像当成命令本身来运行(用 `CMD` 提供默认选项)。 +`ENTRYPOINT` 的最佳用处是设置镜像的主命令,允许将镜像当成命令本身来运行 (用 `CMD` 提供默认选项)。 -例如,下面的示例镜像提供了命令行工具 `s3cmd`: +例如,下面的示例镜像提供了命令行工具 `s3cmd`: ```docker ENTRYPOINT ["s3cmd"] @@ -330,7 +336,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/16_appendix/16.2_debug.md b/16_appendix/16.2_debug.md index 74055d1..b5418a7 100644 --- a/16_appendix/16.2_debug.md +++ b/16_appendix/16.2_debug.md @@ -1,8 +1,10 @@ ## 16.2 如何调试 Docker +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 开启 Debug 模式 -在 dockerd 配置文件 daemon.json(默认位于 /etc/docker/)中添加 +在 dockerd 配置文件 daemon.json (默认位于 /etc/docker/) 中添加 ```json { @@ -45,7 +47,7 @@ $ sudo kill -SIGUSR1 $(pidof dockerd) $ docker system prune ``` -如果你只是想“恢复出厂设置”,在 Docker Desktop 里也提供了相应入口。 +如果你只是想 “恢复出厂设置”,在 Docker Desktop 里也提供了相应入口。 ```bash $ sudo rm -rf /var/lib/docker @@ -53,32 +55,36 @@ $ sudo rm -rf /var/lib/docker ### 常见故障排查 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + #### 容器启动失败 如果容器启动后立即退出,可以使用 `docker logs` 查看原因。 -* **Exit Code 1**: 应用程序错误。通常是配置错误或依赖缺失。 -* **Exit Code 137**: OOM (Out Of Memory)。容器内存不足被内核杀掉。 +* **Exit Code 1**:应用程序错误。通常是配置错误或依赖缺失。 +* **Exit Code 137**:OOM (Out Of Memory)。容器内存不足被内核杀掉。 * 检查宿主机内存。 * 调整容器内存限制 (`--memory`)。 -* **Exit Code 127**: 命令未找到。可能是 `ENTRYPOINT` 或 `CMD` 指定的命令不存在。 +* **Exit Code 127**:命令未找到。可能是 `ENTRYPOINT` 或 `CMD` 指定的命令不存在。 #### 网络连接问题 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ##### 容器内部无法联网 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`,只有容器内部能访问,映射到宿主机外部也无法被外部请求访问。 #### 镜像拉取失败 -* **connection refused**: 检查网络或代理设置。 -* **image not found**: 检查镜像名称和 Tag 拼写。 -* **EOF / timeout**: 网络不稳定,尝试配置镜像加速器。 +* **connection refused**:检查网络或代理设置。 +* **image not found**:检查镜像名称和 Tag 拼写。 +* **EOF / timeout**:网络不稳定,尝试配置镜像加速器。 diff --git a/16_appendix/16.3_resources.md b/16_appendix/16.3_resources.md index 37c40c1..e5be1f4 100644 --- a/16_appendix/16.3_resources.md +++ b/16_appendix/16.3_resources.md @@ -1,5 +1,7 @@ ## 16.3 资源链接 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 官方网站 * Docker 官方主页:https://www.docker.com @@ -19,7 +21,7 @@ ### 技术交流 -* Docker 邮件列表: https://groups.google.com/forum/#!forum/docker-user +* Docker 邮件列表:https://groups.google.com/forum/#!forum/docker-user * Docker 社区 Slack:https://dockercommunity.slack.com/ * Docker Community Discord: https://discord.gg/docker * Docker 的 X (Twitter) 主页:https://twitter.com/docker diff --git a/16_appendix/16.4_terminology.md b/16_appendix/16.4_terminology.md index cff3f17..f80bfb8 100644 --- a/16_appendix/16.4_terminology.md +++ b/16_appendix/16.4_terminology.md @@ -1,4 +1,4 @@ -## 16.4 术语词表(出版统一版) +## 16.4 术语词表 (出版统一版) 本词表用于统一全书术语、缩写和命令表达,适用于最终出版前清稿。 @@ -27,7 +27,7 @@ ### 清稿执行规则 -1. 术语首次出现采用“中文(英文)”格式,例如“注册服务器(Registry)”。 +1. 术语首次出现采用 “中文 (英文)” 格式,例如 “注册服务器 (Registry)”。 2. 命令、文件名、配置键统一使用反引号包裹。 3. 同一章节中,术语只保留一种主写法,不混用同义词。 -4. 若引用历史名词(如 `docker-compose.yml`),需显式标注“历史文件名”。 +4. 若引用历史名词 (如 `docker-compose.yml`),需显式标注 “历史文件名”。 diff --git a/16_appendix/16.5_editorial_style.md b/16_appendix/16.5_editorial_style.md index 9cdd65a..89918bb 100644 --- a/16_appendix/16.5_editorial_style.md +++ b/16_appendix/16.5_editorial_style.md @@ -1,4 +1,4 @@ -## 16.5 出版清稿规范(图号与章节风格) +## 16.5 出版清稿规范 (图号与章节风格) 本规范用于最终出版前清稿,确保全书图号、图题、章节结构与行文风格一致。 @@ -6,22 +6,22 @@ 1. 图号格式统一为:`图 <章号>-<序号> <图题>`,例如 `图 10-2 Rails + PostgreSQL 的 Compose 架构`。 2. 图号在同一章内按出现顺序连续编号,不重复、不跳号。 -3. 正文引用图片统一写法:`如图 <章号>-<序号> 所示`,不使用“下图/上图/示意图如下”。 -4. 所有图片必须提供有意义的 alt 文本,不使用空 alt(`![](...)`)。 +3. 正文引用图片统一写法:`如图 <章号>-<序号> 所示`,不使用 “下图/上图/示意图如下”。 +4. 所有图片必须提供有意义的 alt 文本,不使用空 alt (`![](...)`)。 5. 图题单独成行,放在图片下方。 ### 章节风格规范 1. 小节标题统一使用编号体例:`## 10.6 ...`、`### 步骤 1:...`。 -2. 步骤型内容统一使用“步骤 N:”中文格式,不使用 `Step N:`。 +2. 步骤型内容统一使用 “步骤 N:” 中文格式,不使用 `Step N:`。 3. 命令行示例统一以 `bash` 代码块展示,提示符统一为 `$`。 -4. 关键提醒统一使用引用块(`> 注意/提示/警告`),避免正文中混杂多种强调样式。 -5. 章节内术语使用需遵循《[术语词表(出版统一版)](16.4_terminology.md)》。 +4. 关键提醒统一使用引用块 (`> 注意/提示/警告`),避免正文中混杂多种强调样式。 +5. 章节内术语使用需遵循《[术语词表 (出版统一版)](16.4_terminology.md)》。 ### 出版前自检清单 -1. 是否仍存在“下图/上图/示意图如下”等相对指代。 +1. 是否仍存在 “下图/上图/示意图如下” 等相对指代。 2. 是否存在未编号或编号冲突的图题。 3. 是否存在 `kubernetes`、`compose` 等正文大小写不统一写法。 -4. 是否存在 `Step N:` 与“步骤 N:”混用。 +4. 是否存在 `Step N:` 与 “步骤 N:” 混用。 5. 是否存在未加反引号的命令、文件名和配置键名。 diff --git a/16_appendix/README.md b/16_appendix/README.md index d8a8174..3c8168a 100644 --- a/16_appendix/README.md +++ b/16_appendix/README.md @@ -1,14 +1,18 @@ -# 第十六章 附录 +# 第十六章附录 本章包含了 Docker 相关的参考资料、常见问题解答以及最佳实践指南,旨在为读者提供便捷的查阅工具。 +## 概述 + +总体概述了以下内容。 + ## 目录 * [**常见问题总结 (FAQ)**](faq/README.md):汇总了学习和使用 Docker 过程中的常见问题与错误解决方案。 -* [**热门镜像介绍**](repo/README.md):详细介绍了 Nginx, MySQL, Redis 等常用官方镜像的使用方法。 +* [**热门镜像介绍**](repo/README.md):详细介绍了 Nginx,MySQL,Redis 等常用官方镜像的使用方法。 * [**Docker 命令查询**](command/README.md):速查 Docker 客户端和服务端的常用命令。 * [**Dockerfile 最佳实践**](16.1_best_practices.md):提供编写高效、安全 Dockerfile 的指导原则。 * [**如何调试 Docker**](16.2_debug.md):介绍 Docker 调试技巧和工具。 * [**资源链接**](16.3_resources.md):推荐更多 Docker 相关的学习资源。 -* [**术语词表(出版统一版)**](16.4_terminology.md):统一全书中英文术语、缩写与命令写法。 -* [**出版清稿规范(图号与章节风格)**](16.5_editorial_style.md):统一图号命名、图题写法与章节风格。 +* [**术语词表 (出版统一版)**](16.4_terminology.md):统一全书中英文术语、缩写与命令写法。 +* [**出版清稿规范 (图号与章节风格)**](16.5_editorial_style.md):统一图号命名、图题写法与章节风格。 diff --git a/16_appendix/command/README.md b/16_appendix/command/README.md index 5bea731..d94c5fb 100644 --- a/16_appendix/command/README.md +++ b/16_appendix/command/README.md @@ -1,5 +1,11 @@ # Docker 命令查询 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +## 概述 + +总体概述了以下内容。 + ## 基本语法 Docker 命令有两大类,客户端命令和服务端命令。前者是主要的操作接口,后者用来启动 Docker Daemon。 diff --git a/16_appendix/command/docker.md b/16_appendix/command/docker.md index 2cd995d..0a6f109 100644 --- a/16_appendix/command/docker.md +++ b/16_appendix/command/docker.md @@ -1,5 +1,7 @@ ## 客户端命令 - docker +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 客户端命令选项 * `--config=""`:指定客户端配置文件,默认为 `~/.docker`; @@ -27,7 +29,7 @@ * `export`:导出容器内容为一个 `tar` 包; * `history`:显示一个镜像的历史信息; * `images`:列出存在的镜像; -* `import`:导入一个文件(典型为 `tar` 包)路径或目录来创建一个本地镜像; +* `import`:导入一个文件 (典型为 `tar` 包) 路径或目录来创建一个本地镜像; * `info`:显示一些相关的系统信息; * `inspect`:显示一个容器的具体配置信息; * `kill`:关闭一个运行中的容器 (包括进程和所有相关资源); @@ -40,7 +42,7 @@ * `pause`:暂停一个容器中的所有进程; * `port`:查找一个 nat 到一个私有网口的公共口; * `ps`:列出主机上的容器; -* `pull`:从一个Docker的仓库服务器下拉一个镜像或仓库; +* `pull`:从一个 Docker 的仓库服务器下拉一个镜像或仓库; * `push`:将一个镜像或者仓库推送到一个 Docker 的注册服务器; * `rename`:重命名一个容器; * `restart`:重启一个运行中的容器; @@ -51,7 +53,7 @@ * `search`:在 Docker index 中搜索一个镜像; * `service`:管理 Docker 所启动的应用服务,包括创建、更新、删除等; * `start`:启动一个容器; -* `stats`:输出(一个或多个)容器的资源使用统计信息; +* `stats`:输出 (一个或多个) 容器的资源使用统计信息; * `stop`:终止一个运行中的容器; * `swarm`:管理 Docker swarm 集群,包括创建、加入、退出、更新等; * `tag`:为一个镜像打标签; diff --git a/16_appendix/command/dockerd.md b/16_appendix/command/dockerd.md index 82f7dc2..b1b7521 100644 --- a/16_appendix/command/dockerd.md +++ b/16_appendix/command/dockerd.md @@ -1,19 +1,21 @@ -## 服务端命令(dockerd) +## 服务端命令 + +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: ### 使用说明 `dockerd` 参数会随版本变化。建议优先在目标机器上执行 `dockerd --help`,并以 `daemon.json` 为主进行持久化配置。 -### 常用选项(Docker Engine 29.x) +### 常用选项 (Docker Engine 29.x) * `--config-file="/etc/docker/daemon.json"`:指定 daemon 配置文件路径; -* `--data-root=""`:Docker 数据目录(默认 `/var/lib/docker`); -* `-H, --host=[]`:指定 daemon 监听地址(Unix socket / TCP); +* `--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 +25,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/16_appendix/faq/README.md b/16_appendix/faq/README.md index 8b02ccc..e47d2e7 100644 --- a/16_appendix/faq/README.md +++ b/16_appendix/faq/README.md @@ -1,7 +1,11 @@ # 附录一:常见问题总结 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ## 镜像相关 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 如何批量清理临时镜像文件? 答:可以使用 `docker image prune` 命令。 @@ -23,7 +27,7 @@ * 安装各个软件时候要指定准确的版本号,并避免引入不需要的依赖; * 从安全角度考虑,应用要尽量使用系统的库和依赖; * 如果安装应用时候需要配置一些特殊的环境变量,在安装后要还原不需要保持的变量值; -* 使用 Dockerfile 创建镜像时候要添加 .dockerignore 文件或使用干净的工作目录。 +* 使用 Dockerfile 创建镜像时候要添加。dockerignore 文件或使用干净的工作目录。 更多内容请查看 [Dockerfile 最佳实践](../16.1_best_practices.md) @@ -33,9 +37,11 @@ ## 容器相关 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 容器退出后,通过 docker container ls 命令查看不到,数据会丢失么? -答:容器退出后会处于终止(exited)状态,此时可以通过 `docker container ls -a` 查看。其中的数据也不会丢失,还可以通过 `docker start` 命令来启动它。只有删除掉容器才会清除所有数据。 +答:容器退出后会处于终止 (exited) 状态,此时可以通过 `docker container ls -a` 查看。其中的数据也不会丢失,还可以通过 `docker start` 命令来启动它。只有删除掉容器才会清除所有数据。 ### 如何停止所有正在运行的容器? @@ -75,7 +81,7 @@ $ docker run --network=my-net --ip=172.25.3.3 -itd --name=my-container busybox 答:按 `Ctrl-p Ctrl-q`。如果按 `Ctrl-c` 往往会让容器内应用进程终止,进而会终止容器。 -### 使用 `docker port` 命令映射容器的端口时,系统报错“Error: No public port '80' published for xxx”? +### 使用 `docker port` 命令映射容器的端口时,系统报错 “Error:No public port ‘80’ published for xxx”? 答: @@ -86,13 +92,19 @@ $ docker run --network=my-net --ip=172.25.3.3 -itd --name=my-container busybox 答:一般并不推荐在同一个容器内运行多个应用进程。如果有类似需求,可以通过一些额外的进程管理机制,比如 `supervisord` 来管理所运行的进程。可以参考 https://docs.docker.com/engine/containers/multi-service_container/ 。 -### 如何控制容器占用系统资源(CPU、内存)的份额? +### 如何控制容器占用系统资源 (CPU、内存) 的份额? 答:在使用 `docker create` 命令创建容器或使用 `docker run` 创建并启动容器的时候,可以使用 -c|--cpu-shares\[=0] 参数来调整容器使用 CPU 的权重;使用 -m|--memory\[=MEMORY] 参数来调整容器使用内存的大小。 ## 仓库相关 -### 仓库(Repository)、注册服务器(Registry)、注册索引(Index) 有何关系? +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +### 概述 + +总体概述了以下内容。 + +### 仓库、注册服务器、注册索引有何关系? 首先,仓库是存放一组关联镜像的集合,比如同一个应用的不同版本的镜像。 @@ -100,9 +112,11 @@ $ 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 的默认存储位置? @@ -127,31 +141,33 @@ lrwxrwxrwx. 1 root root 15 11月 17 13:43 docker -> /storage/docker [root@s26 lib]# service docker start ``` -### 使用内存和 swap 限制启动容器时候报警告:"WARNING: Your kernel does not support cgroup swap limit. WARNING: Your kernel does not support swap limit capabilities. Limitation discarded."? +### 使用内存和 swap 限制启动容器时候报警告:“WARNING:Your kernel does not support cgroup swap limit。WARNING:Your kernel does not support swap limit capabilities。Limitation discarded。”? 答:这是因为系统默认没有开启对内存和 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` * 重启系统,即可。 ## Docker 与虚拟化 -### Docker 与 LXC(Linux Container)有何不同? +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +### Docker 与 LXC 有何不同? 答:LXC 利用 Linux 上相关技术实现了容器。Docker 则在如下的几个方面进行了改进: * 移植性:通过抽象容器配置,容器可以实现从一个平台移植到另一个平台; * 镜像系统:基于 OverlayFS 的镜像系统为容器的分发带来了很多的便利,同时共同的镜像层只需要存储一份,实现高效率的存储; -* 版本管理:类似于Git的版本管理理念,用户可以更方便的创建、管理镜像文件; +* 版本管理:类似于 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 适合用来管理应用环境。 @@ -166,9 +182,11 @@ lrwxrwxrwx. 1 root root 15 11月 17 13:43 docker -> /storage/docker ## 其它 -### Docker 能在非 Linux 平台(比如 Windows 或 macOS )上运行么? +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: -答:完全可以。安装方法请查看 [安装 Docker](../../03_install/README.md) 一节 +### Docker 能在非 Linux 平台 (比如 Windows 或 macOS) 上运行么? + +答:完全可以。安装方法请查看[安装 Docker](../../03_install/README.md) 一节 ### 如何将一台宿主主机的 Docker 环境迁移到另外一台宿主主机? diff --git a/16_appendix/repo/centos.md b/16_appendix/repo/centos.md index 255d469..98dc3d2 100644 --- a/16_appendix/repo/centos.md +++ b/16_appendix/repo/centos.md @@ -1,27 +1,29 @@ ## [CentOS] +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本信息 [CentOS](https://en.wikipedia.org/wiki/CentOS) 是流行的 Linux 发行版,其软件包大多跟 RedHat 系列保持一致。 -> ⚠️ **重要提示**:CentOS 8 已于 2021 年 12 月 31 日停止维护(EOL),CentOS 7 也已于 2024 年 6 月 30 日**完全结束支持**。Docker Hub 上的 CentOS 官方镜像**已停止更新**且存在未修复的安全漏洞。 +> ⚠️ **重要提示**:CentOS 8 已于 2021 年 12 月 31 日停止维护 (EOL),CentOS 7 也已于 2024 年 6 月 30 日**完全结束支持**。Docker Hub 上的 CentOS 官方镜像**已停止更新**且存在未修复的安全漏洞。 > > 2026 年了,对于任何新项目,**强烈建议**使用以下生产级替代方案: > - [Rocky Linux](https://hub.docker.com/_/rockylinux):CentOS 原创始人发起的社区驱动项目,目前主流为 Rocky Linux 9。 > - [AlmaLinux](https://hub.docker.com/_/almalinux):由 CloudLinux 支持的企业级发行版,提供长期支持。 -> - [CentOS Stream](https://hub.docker.com/r/centos/centos):RHEL 的上游开发分支(适合开发测试,不建议用于生产环境)。 +> - [CentOS Stream](https://hub.docker.com/r/centos/centos):RHEL 的上游开发分支 (适合开发测试,不建议用于生产环境)。 -该仓库位于 `https://hub.docker.com/_/centos`,提供了 CentOS 从 5 ~ 8 各个版本的镜像(仅作为历史归档,不再更新)。 +该仓库位于 `https://hub.docker.com/_/centos`,提供了 CentOS 从 5 ~ 8 各个版本的镜像 (仅作为历史归档,不再更新)。 ### 使用方法 -使用 Rocky Linux 9 替代(**推荐**): +使用 Rocky Linux 9 替代 (**推荐**): ```bash $ docker run --name rocky -it rockylinux:9 bash ``` -使用旧版 CentOS 7(**仅用于维护旧项目,不推荐**): +使用旧版 CentOS 7 (**仅用于维护旧项目,不推荐**): ```bash $ docker run --name centos -it centos:7 bash diff --git a/16_appendix/repo/minio.md b/16_appendix/repo/minio.md index 8c28ce7..91d9cfb 100644 --- a/16_appendix/repo/minio.md +++ b/16_appendix/repo/minio.md @@ -2,7 +2,7 @@ **MinIO** 是一个基于 Apache License v2.0 开源协议的对象存储服务。它兼容亚马逊 S3 云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几 kb 到最大 5T 不等。 -MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。 +MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS,Redis 或者 MySQL。 [官方文档](https://docs.min.io/) @@ -20,13 +20,13 @@ $ docker run -d -p 9000:9000 -p 9090:9090 minio/minio server /data --console-add #### 导出镜像 -在有公网资源的服务器上下载好`minio/minio`镜像 +在有公网资源的服务器上下载好 `minio/minio` 镜像 ```bash $ docker save -o minio.tar minio/minio:latest ``` -> 使用docker save 的时候,也可以使用image id 来导出,但是那样导出的时候,就会丢失原来的镜像名称,推荐,还是使用镜像名字+tag来导出镜像 +> 使用 docker save 的时候,也可以使用 image id 来导出,但是那样导出的时候,就会丢失原来的镜像名称,推荐,还是使用镜像名字+tag 来导出镜像 #### 导入镜像 @@ -41,8 +41,8 @@ $ docker load -i minio.tar - 把 `/mnt/data` 改成要替换的数据目录 - 替换 `MINIO_ROOT_USER` 的值 - 替换 `MINIO_ROOT_PASSWORD` 的值 -- 替换 name,minio1(可选) -- 如果 9000、9090 端口冲突,替换端口前面的如 `9009:9000` +- 替换 name,minio1 (可选) +- 如果 9000、9090 端口冲突,替换端口前面的如 `9009:9000` ```bash $ sudo docker run -d -p 9000:9000 -p 9090:9090 --name minio1 \ diff --git a/16_appendix/repo/mongodb.md b/16_appendix/repo/mongodb.md index 2c363f9..e2e5c0e 100644 --- a/16_appendix/repo/mongodb.md +++ b/16_appendix/repo/mongodb.md @@ -1,5 +1,7 @@ ## [MongoDB] +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本信息 [MongoDB](https://en.wikipedia.org/wiki/MongoDB) 是开源的 NoSQL 数据库实现。 diff --git a/16_appendix/repo/mysql.md b/16_appendix/repo/mysql.md index bdad284..11fa2c1 100644 --- a/16_appendix/repo/mysql.md +++ b/16_appendix/repo/mysql.md @@ -1,5 +1,7 @@ ## [MySQL] +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本信息 [MySQL](https://en.wikipedia.org/wiki/MySQL) 是开源的关系数据库实现。 diff --git a/16_appendix/repo/nginx.md b/16_appendix/repo/nginx.md index 0d45f43..2e894e4 100644 --- a/16_appendix/repo/nginx.md +++ b/16_appendix/repo/nginx.md @@ -1,5 +1,7 @@ ## [Nginx] +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本信息 [Nginx](https://en.wikipedia.org/wiki/Nginx) 是开源的高效的 Web 服务器实现,支持 HTTP、HTTPS、SMTP、POP3、IMAP 等协议。 @@ -34,7 +36,7 @@ $ docker run --name some-nginx -d some-content-nginx $ docker run --name some-nginx -d -p 8080:80 some-content-nginx ``` -Nginx的默认配置文件路径为 `/etc/nginx/nginx.conf`,可以通过映射它来使用本地的配置文件,例如 +Nginx 的默认配置文件路径为 `/etc/nginx/nginx.conf`,可以通过映射它来使用本地的配置文件,例如 ```bash $ docker run -d \ diff --git a/16_appendix/repo/nodejs.md b/16_appendix/repo/nodejs.md index 0253bdd..e22c936 100644 --- a/16_appendix/repo/nodejs.md +++ b/16_appendix/repo/nodejs.md @@ -1,5 +1,7 @@ ## [Node.js] +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本信息 [Node.js](https://en.wikipedia.org/wiki/Node.js) 是基于 JavaScript 的可扩展服务端和网络软件开发平台。 diff --git a/16_appendix/repo/php.md b/16_appendix/repo/php.md index cddbe35..9f9570e 100644 --- a/16_appendix/repo/php.md +++ b/16_appendix/repo/php.md @@ -1,8 +1,10 @@ ## [PHP] +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本信息 -[PHP](https://en.wikipedia.org/wiki/Php)(Hypertext Preprocessor 超文本预处理器的字母缩写)是一种被广泛应用的开放源代码的多用途脚本语言,它可嵌入到 HTML 中,尤其适合 web 开发。 +[PHP](https://en.wikipedia.org/wiki/Php) (Hypertext Preprocessor 超文本预处理器的字母缩写) 是一种被广泛应用的开放源代码的多用途脚本语言,它可嵌入到 HTML 中,尤其适合 web 开发。 该仓库位于 `https://hub.docker.com/_/php/`。具体可用版本以 Docker Hub 上的 tags 列表为准。 diff --git a/16_appendix/repo/redis.md b/16_appendix/repo/redis.md index c32971b..873d2b7 100644 --- a/16_appendix/repo/redis.md +++ b/16_appendix/repo/redis.md @@ -1,5 +1,7 @@ ## [Redis] +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本信息 [Redis](https://en.wikipedia.org/wiki/Redis) 是开源的内存 Key-Value 数据库实现。 @@ -14,7 +16,7 @@ $ docker run --name some-redis -d -p 6379:6379 redis ``` -另外还可以启用 [持久存储](https://redis.io/topics/persistence)。 +另外还可以启用[持久存储](https://redis.io/topics/persistence)。 ```bash $ docker run --name some-redis -d -p 6379:6379 redis redis-server --appendonly yes diff --git a/16_appendix/repo/ubuntu.md b/16_appendix/repo/ubuntu.md index d9340c5..3064c93 100644 --- a/16_appendix/repo/ubuntu.md +++ b/16_appendix/repo/ubuntu.md @@ -1,5 +1,7 @@ ## [Ubuntu] +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本信息 [Ubuntu](https://en.wikipedia.org/wiki/Ubuntu) 是流行的 Linux 发行版,其自带软件版本往往较新一些。 diff --git a/16_appendix/repo/wordpress.md b/16_appendix/repo/wordpress.md index f7fb23c..535f844 100644 --- a/16_appendix/repo/wordpress.md +++ b/16_appendix/repo/wordpress.md @@ -1,5 +1,7 @@ ## [WordPress] +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 基本信息 [WordPress](https://en.wikipedia.org/wiki/WordPress) 是开源的 Blog 和内容管理系统框架,它基于 PHP 和 MySQL。 @@ -27,10 +29,10 @@ $ docker run --name some-wordpress -d --network my-wordpress-net -e WORDPRESS_DB 启动 WordPress 容器时可以指定的一些环境变量包括: -* `WORDPRESS_DB_HOST`: MySQL 服务的主机名 -* `WORDPRESS_DB_USER`: MySQL 数据库的用户名 -* `WORDPRESS_DB_PASSWORD`: MySQL 数据库的密码 -* `WORDPRESS_DB_NAME`: WordPress 要使用的数据库名 +* `WORDPRESS_DB_HOST`:MySQL 服务的主机名 +* `WORDPRESS_DB_USER`:MySQL 数据库的用户名 +* `WORDPRESS_DB_PASSWORD`:MySQL 数据库的密码 +* `WORDPRESS_DB_NAME`:WordPress 要使用的数据库名 ### Dockerfile