Fix grammar

This commit is contained in:
Baohua Yang
2026-02-17 22:17:02 -08:00
parent f68795f34c
commit 063c3f1381
62 changed files with 117 additions and 161 deletions

View File

@@ -94,6 +94,7 @@ This document serves as the single source of truth for all formatting, structure
本节介绍 XXX 的相关内容包括子章节A和子章节B两个方面。
### 2.1.1 子章节A
```
## 3. Content Rules
@@ -122,7 +123,7 @@ print("Hello")
## 4. Validation
Run `python check_project_rules.py` to validate all markdown files against these rules.
Run `python check_rules.py` to validate all markdown files against these rules.
Available options:
- `--verbose` or `-v`: Show all scanned files

View File

@@ -1,6 +1,6 @@
<!--
Thanks for your contribution.
See [CONTRIBUTING](CONTRIBUTING.md) for contribution guidelines.
See [CONTRIBUTING](../CONTRIBUTING.md) for contribution guidelines.
-->
**Proposed changes (Mandatory)**

View File

@@ -106,7 +106,7 @@ module.exports = config({
},
{
text: '安装 Docker',
link: '/install/',
link: '/03_install/',
},
{
text: 'Docker 入门',
@@ -114,23 +114,23 @@ module.exports = config({
},
{
text: 'Docker 实战',
link: '/cases/os/'
link: '/15_cases/os/'
},
{
text: 'CI/CD',
link: '/cases/ci/'
link: '/15_cases/ci/'
},
{
text: 'Compose',
link: '/compose/',
link: '/10_compose/',
},
{
text: 'Kubernetes',
link: '/kubernetes/',
link: '/12_orchestration/kubernetes/',
},
{
text: "云计算",
link: "/cloud/",
link: "/13_ecosystem/cloud/",
},
// {
// text: 'GitHub',

View File

@@ -4,9 +4,7 @@ Docker 是彻底改变了软件开发和交付方式的革命性技术。本节
### 一句话理解 Docker
> **Docker 是一种轻量级的虚拟化技术它让应用程序及其依赖环境可以被打包成一个标准化的单元在任何地方都能一致地运行**
如果用一个生活中的类比**Docker 之于软件就像集装箱之于货物**
> **Docker 是一种轻量级的虚拟化技术它让应用程序及其依赖环境可以被打包成一个标准化的单元在任何地方都能一致地运行**如果用一个生活中的类比**Docker 之于软件就像集装箱之于货物**
在集装箱发明之前货物的运输是一件麻烦的事情不同的货物需要不同的包装不同的装卸方式换一种运输工具就要重新装卸集装箱的出现改变了这一切无论里面装的是什么集装箱的外形是标准的可以用同样的方式装卸堆放和运输
@@ -41,9 +39,7 @@ Docker 做的事情类似:无论你的应用是用 Python、Java、Node.js 还
### Docker vs 虚拟机
很多人第一次接触 Docker 时会问**"这不就是虚拟机吗?"**
答案是**不是而且差别很大**
很多人第一次接触 Docker 时会问**"这不就是虚拟机吗?"**答案是**不是而且差别很大**
#### 传统虚拟机

View File

@@ -218,8 +218,6 @@ Docker 主要面向服务端应用。桌面 GUI 应用的容器化虽然可行
### 本章小结
Docker 的核心价值可以用一句话概括**让应用的开发测试部署保持一致同时极大提高资源利用效率**
笔者认为对于现代软件开发者来说Docker 已经不是"要不要学"的问题而是**必备技能**无论你是前端后端运维还是全栈开发者掌握 Docker 都能让你的工作更高效
Docker 的核心价值可以用一句话概括**让应用的开发测试部署保持一致同时极大提高资源利用效率**笔者认为对于现代软件开发者来说Docker 已经不是"要不要学"的问题而是**必备技能**无论你是前端后端运维还是全栈开发者掌握 Docker 都能让你的工作更高效
接下来让我们学习 Docker [基本概念](../02_basic_concept/README.md)

View File

@@ -4,7 +4,6 @@
## 本章内容
* [快速上手](1.1_quickstart.md)
* 通过一个简单的 Web 应用例子带你快速体验 Docker 的核心流程构建镜像运行容器

View File

@@ -4,9 +4,7 @@ Docker 镜像作为容器运行的基石,其设计理念和实现机制至关
### 一句话理解镜像
> **Docker 镜像是一个只读的模板包含了运行应用所需的一切代码运行时环境变量和配置文件**
如果用一个类比**镜像就像是一张光盘或 ISO 文件**你可以用同一张光盘在不同电脑上安装系统而光盘本身不会被修改同样一个镜像可以创建多个容器而镜像本身保持不变
> **Docker 镜像是一个只读的模板包含了运行应用所需的一切代码运行时环境变量和配置文件**如果用一个类比**镜像就像是一张光盘或 ISO 文件**你可以用同一张光盘在不同电脑上安装系统而光盘本身不会被修改同样一个镜像可以创建多个容器而镜像本身保持不变
### 镜像与操作系统的关系
@@ -39,16 +37,13 @@ Docker 镜像是一个特殊的文件系统,包含:
| **库文件** | libcOpenSSL各种依赖库 |
| **配置文件** | nginx.confmy.cnf |
| **环境变量** | PATHLANG 等预设值 |
| **元数据** | 启动命令暴露端口数据卷定义 |
**关键特性**
| **元数据**| 启动命令暴露端口数据卷定义 |**关键特性**
- 镜像是**只读**
- 镜像**不包含**动态数据
- 镜像构建后**内容不会改变**
### 分层存储镜像的核心设计
镜像的分层存储机制是 Docker 最具创新性的特性之一通过 Union FS 技术Docker 能够高效地构建和管理镜像
#### 为什么需要分层
@@ -113,9 +108,7 @@ COPY app.conf /etc/nginx/ # 第 4 层:复制配置文件
#### 分层存储的"陷阱"
> **笔者特别提醒**理解这一点可以帮你避免构建出臃肿的镜像
**关键原理**每一层的文件变化会被记录**删除操作只是标记不会真正减小镜像体积**
> **笔者特别提醒**理解这一点可以帮你避免构建出臃肿的镜像**关键原理**每一层的文件变化会被记录**删除操作只是标记不会真正减小镜像体积**
```docker
## 错误示范 ❌
@@ -126,6 +119,7 @@ RUN apt-get install -y build-essential # 安装编译工具(约 200MB
RUN make && make install # 编译应用
RUN apt-get remove build-essential # 试图删除编译工具
## 结果:镜像仍然包含 200MB 的编译工具!
```
```docker
@@ -139,6 +133,7 @@ RUN apt-get update && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*
## 在同一层完成安装、使用、清理
```
#### 查看镜像的分层

View File

@@ -4,9 +4,7 @@
### 一句话理解容器
> **容器是镜像的运行实例如果把镜像比作程序那么容器就是进程**
用面向对象编程的术语来说**镜像是类Class容器是对象Instance**
> **容器是镜像的运行实例如果把镜像比作程序那么容器就是进程**用面向对象编程的术语来说**镜像是类Class容器是对象Instance**
- 一个镜像可以创建多个容器
- 每个容器相互独立互不影响
@@ -14,9 +12,7 @@
### 容器的本质
> 💡 **笔者认为理解这一点是理解 Docker 的关键**
**容器的本质是一个特殊的进程**
> 💡 **笔者认为理解这一点是理解 Docker 的关键****容器的本质是一个特殊的进程**
```
┌─────────────────────────────────────────────────────────────┐
@@ -71,7 +67,6 @@
### 容器的存储层
理解容器的存储层机制对于数据的持久化和镜像的优化至关重要本节将介绍容器的可写层以及 Copy-on-Write 机制
#### 镜像层 + 容器层
@@ -108,9 +103,7 @@
#### 容器存储层的生命周期
> **笔者特别强调**这是新手最容易踩的坑
**容器存储层与容器生命周期绑定容器删除数据就没了**
> **笔者特别强调**这是新手最容易踩的坑**容器存储层与容器生命周期绑定容器删除数据就没了**
```bash
## 创建容器,写入数据
@@ -124,6 +117,7 @@ root@abc123:/# exit
$ docker rm abc123
## 数据丢了!没有任何办法恢复!
```
#### 正确的数据持久化方式
@@ -149,7 +143,6 @@ $ docker run -v /host/path:/container/path nginx
### 容器的生命周期
掌握容器的生命周期对于管理和调试 Docker 应用非常重要下图展示了容器从创建到删除的完整状态流转
```
@@ -217,6 +210,7 @@ $ docker rm -f abc123 # 强制删除运行中的容器
## 主进程运行,容器运行
## 主进程退出,容器停止
```
这就是为什么

View File

@@ -44,6 +44,7 @@ Docker Registry 中可以包含多个 Repository每个 Repository 可以包
| **Tag标签** | 仓库内的版本标识 | `latest``1.25``alpine` |
#### 镜像的完整名称
一个完整的 Docker 镜像名称由 Registry 地址用户名/组织名仓库名和标签组成了解其结构有助于我们更准确地定位镜像
```
@@ -81,7 +82,6 @@ gcr.io/google-containers/pause:3.6
### 公共 Registry 服务
公共 Registry 服务为开发者提供了便捷的镜像获取途径其中最著名的是 Docker Hub
#### Docker Hub默认
@@ -138,7 +138,6 @@ $ docker push username/myapp:v1.0
#### 官方 Registry 镜像
Docker 官方提供了 [registry](https://hub.docker.com/_/registry/) 镜像,可以快速搭建私有 Registry
```bash
@@ -224,7 +223,6 @@ $ docker logout
### 镜像的安全性
在使用公共镜像或维护私有镜像时安全性是不容忽视的重要环节
#### 使用官方镜像

View File

@@ -6,7 +6,6 @@ Ubuntu 是 Docker 最常用的运行环境之一。本节将介绍如何在 Ubun
### 准备工作
在开始安装之前我们需要确认系统版本是否满足要求并清理可能存在的旧版本
#### 系统要求
@@ -64,6 +63,7 @@ $ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo gpg --
## 官方源
## $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
```
然后我们需要向 `sources.list` 中添加 Docker 软件源
@@ -80,8 +80,7 @@ $ echo \
## "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
## $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
## $ stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
@@ -110,7 +109,6 @@ $ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 的稳定(stable)版本安装在系统中

View File

@@ -6,7 +6,6 @@ Debian 以其稳定性著称,是 Docker 的理想宿主系统。本节将指
### 准备工作
安装前请仔细检查 Debian 版本支持情况并卸载旧版本以避免冲突
#### 系统要求
@@ -54,7 +53,6 @@ $ curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo gpg --
## $ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
```
然后我们需要向 `sources.list` 中添加 Docker 软件源
@@ -73,8 +71,7 @@ $ echo \
## "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
## $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
## $ stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
@@ -103,7 +100,6 @@ $ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 的稳定(stable)版本安装在系统中

View File

@@ -6,7 +6,6 @@ Fedora 作为技术前沿的 Linux 发行版,对 Docker 有着良好的支持
### 准备工作
确保你的 Fedora 版本在支持列表中并清理旧版本
#### 系统要求
@@ -36,7 +35,6 @@ $ sudo dnf remove docker \
### 使用 dnf 安装
使用 dnf 包管理器安装是推荐的方式便于后续的更行和管理
执行以下命令安装依赖包
@@ -64,7 +62,6 @@ $ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.r
## https://download.docker.com/linux/fedora/docker-ce.repo
```
如果需要测试版本的 Docker 请使用以下命令
@@ -111,7 +108,6 @@ $ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 最新稳定(stable)版本安装在系统中

View File

@@ -6,7 +6,6 @@ CentOS及其替代品 Rocky Linux、AlmaLinux是企业级服务器常用
### 准备工作
安装前请确认系统版本和内核版本满足 Docker 的运行要求
#### 系统要求
@@ -38,7 +37,6 @@ $ sudo yum remove docker \
### 使用 yum 安装
使用 yum/dnf 安装是管理 Docker 生命周期的标准方式
执行以下命令安装依赖包
@@ -56,7 +54,7 @@ $ sudo dnf config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
$ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/dnf.repos.d/docker-ce.repo
$ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo
## 官方源
@@ -66,13 +64,12 @@ $ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/dnf.r
## https://download.docker.com/linux/centos/docker-ce.repo
```
如果需要测试版本的 Docker 请执行以下命令
```bash
$ sudo dnf config-manager --enable docker-ce-test
$ sudo dnf config-manager --set-enabled docker-ce-test
```
#### 安装 Docker
@@ -116,7 +113,6 @@ $ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 的稳定(stable)版本安装在系统中

View File

@@ -48,9 +48,10 @@ $ sudo chmod a+r /etc/apt/keyrings/docker.gpg
## 官方源
## $ sudo install -m 0755 -d /etc/apt/keyrings
## $ curl -fsSL https://download.docker.com/linux/raspbian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
## $ sudo chmod a+r /etc/apt/keyrings/docker.gpg
## $ curl -fsSL https://download.docker.com/linux/raspbian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
## $ sudo chmod a+r /etc/apt/keyrings/docker.gpg
```
@@ -65,9 +66,10 @@ $ echo \
## 官方源
## $ echo \
## "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/raspbian \
## $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
## "deb [arch=$ signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/raspbian \
## $ stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
@@ -98,8 +100,7 @@ $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docke
## 官方源
## $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/raspbian $(lsb_release -cs) stable" | sudo tee -a /etc/apt/sources.list
## $ echo "deb [arch=$ signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/raspbian $ stable" | sudo tee -a /etc/apt/sources.list
```
@@ -126,7 +127,6 @@ $ curl -fsSL get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh --mirror Aliyun
## $ sudo sh get-docker.sh --mirror AzureChinaCloud
```
执行这个命令后脚本就会自动的将一切准备工作做好并且把 Docker 的稳定(stable)版本安装在系统中

View File

@@ -158,7 +158,7 @@ sudo yum versionlock delete all
```bash
## 删除其他网络源
rm -f /etc/yum.repo.d/*
rm -f /etc/yum.repos.d/*
## 挂载光盘或者iso镜像
mount /dev/cdrom /mnt
@@ -171,7 +171,7 @@ cat >/etc/yum.repos.d/local_files.repo<< EOF
[Local_Files]
name=Local_Files
baseurl=file:///mnt
enable=1
enabled=1
gpgcheck=0
gpgkey=file:///mnt/RPM-GPG-KEY-CentOS-7
EOF
@@ -201,7 +201,7 @@ mkdir /var/www/html/base
## 复制光盘内的文件到刚才新建的目录
cp -R /mnt/Packages/* /var/www/html/base/
createrepo /var/www/html/centos/
createrepo /var/www/html/base/
systemctl enable httpd
systemctl start httpd
```
@@ -243,22 +243,22 @@ createrepo /var/www/html/docker-ce/
运行以下命令
```bash
rm -f /etc/yum.repo.d/*
rm -f /etc/yum.repos.d/*
cat >/etc/yum.repos.d/local_files.repo<< EOF
[local_base]
name=local_base
## 改成B服务器地址
baseurl=http://x.x.x.x/base
enable=1
enabled=1
gpgcheck=0
proxy=_none_
[docker_ce]
name=docker_ce
## 改成B服务器地址
baseurl=http://x.x.x.x/base
enable=1
baseurl=http://x.x.x.x/docker-ce
enabled=1
gpgcheck=0
proxy=_none_
EOF

View File

@@ -16,4 +16,3 @@ Docker 分为 `stable` `test` 和 `nightly` 三个更新频道。
* [Windows 10/11](3.8_windows.md)
* [镜像加速器](3.9_mirror.md)
* [开启实验特性](3.10_experimental.md)

View File

@@ -12,7 +12,6 @@ docker pull [选项] [Registry地址/]仓库名[:标签]
#### 镜像名称格式
Docker 镜像名称由 Registry 地址用户名仓库名和标签组成其标准格式如下
```
@@ -179,6 +178,7 @@ $ sudo systemctl restart docker # Linux
## 或在 Docker Desktop 中重启
## 或在 Docker Desktop 中重启
```
详见 [镜像加速器](../03_install/3.9_mirror.md) 章节

View File

@@ -94,7 +94,6 @@ Deleted: sha256:32770d1dcf835f192cafd6b9263b7b597a1778a403a109e2cc2ee866f74adf23
#### 删除流程
Docker 会检测镜像是否有容器依赖或其他标签指向只有在确认为无用资源时才会真正删除存储层
```

View File

@@ -72,7 +72,7 @@ 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` 等指令进行详细讲解

View File

@@ -38,7 +38,7 @@ Docker 镜像并不是一个单纯的文件,而是由一组文件系统叠加
```
* **读取文件**当容器需要读取文件时Docker 会从最上层容器层开始向下层镜像层寻找直到找到该文件为止
* **修改文件**当容器需要修改某个文件时Docker 会从下层镜像中将该文件复制到上层的容器层然后对副本进行修改这被称为 **写时复制Copy-on-Write, CoW** 策略
* **修改文件**当容器需要修改某个文件时Docker 会从下层镜像中将该文件复制到上层的容器层然后对副本进行修改这被称为**写时复制Copy-on-Write, CoW** 策略
* **删除文件**当容器删除某个文件时Docker 并不是真的去下层删除它因为下层是只读的而是在容器层创建一个特殊的白障Whiteout文件用来标记该文件已被删除从而在容器视图中隐藏它
这就是为什么
@@ -54,10 +54,10 @@ Docker 镜像的每一层都有一个唯一的 ID这个 ID 是根据该层的
* **安全性**确保了镜像内容的完整性下载过程中如果数据损坏ID 校验就会失败
* **去重**如果两个不同的镜像甚至是不同来源的镜像包含相同的层ID 相同Docker 引擎在本地只会存储一份绝不重复下载
### 联合文件系统 (Union FS)
### 联合文件系统
Docker 使用联合文件系统Union FS来实现这种分层挂载常见的驱动包括 `overlay2`目前推荐`aufs`早期使用`btrfs``zfs`
虽然实现细节不同但它们都遵循上述的 **分层 + CoW** 模型
> 想要深入了解 Overlay2 等文件系统的具体实现原理包括 WorkDirUpperDirLowerDir 等底层细节请阅读 **[第十四章 底层实现](../14_implementation/README.md)** 中的 **[联合文件系统](../14_implementation/14.4_ufs.md)** 章节
> 想要深入了解 Overlay2 等文件系统的具体实现原理包括 WorkDirUpperDirLowerDir 等底层细节请阅读 **[第十四章 底层实现](../14_implementation/README.md)**中的**[联合文件系统](../14_implementation/14.4_ufs.md)** 章节

View File

@@ -199,6 +199,7 @@ $ docker logs -t myapp
```bash
$ docker ps -a --filter "name=mycontainer"
# 查看 STATUS 列,如 "Exited (1)" 表示异常退出
```
2. **查看容器日志**
@@ -210,6 +211,7 @@ $ docker logs -t myapp
```bash
$ docker run -it myimage:latest /bin/sh
# 进入容器手动执行命令,查找问题
```
#### Q: 容器在后台运行但无法访问服务

View File

@@ -12,6 +12,3 @@
* [进入容器](5.4_attach_exec.md)
* [导出和导入容器](5.5_import_export.md)
* [删除容器](5.6_rm.md)

View File

@@ -13,9 +13,7 @@ HEALTHCHECK NONE
### 为什么需要 HEALTHCHECK
在没有 HEALTHCHECK 之前Docker 只能通过**进程退出码**来判断容器状态
**问题场景**
在没有 HEALTHCHECK 之前Docker 只能通过**进程退出码**来判断容器状态**问题场景**
- Web 服务死锁无法响应请求但进程仍在运行
- 数据库正在启动中尚未准备好接受连接
- 应用陷入死循环CPU 爆满但进程存活

View File

@@ -47,8 +47,11 @@ server {
include fastcgi.conf;
# fastcgi_connect_timeout 300;
# fastcgi_send_timeout 300;
# fastcgi_read_timeout 300;
}
}
```

View File

@@ -104,11 +104,7 @@ 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
@@ -122,11 +118,7 @@ RUN export MY_VAR=hello
RUN echo $MY_VAR
```
**结果**输出为空
**原因**同上环境变量只在当前 `RUN` 有效
**解决**使用 `ENV` 指令或在同一行 `RUN` 中导出
**结果**输出为空**原因**同上环境变量只在当前 `RUN` 有效**解决**使用 `ENV` 指令或在同一行 `RUN` 中导出
```docker
ENV MY_VAR=hello

View File

@@ -78,7 +78,6 @@ COPY app[0-9].js /app/ # app0.js ~ app9.js
### 目标路径
#### 绝对路径
```docker

View File

@@ -50,8 +50,7 @@ CMD echo $HOME
CMD ["sh", "-c", "echo $HOME"]
```
**优点**可以使用环境变量管道等 shell 特性
**缺点**主进程是 sh信号无法正确传递给应用
**优点**可以使用环境变量管道等 shell 特性**缺点**主进程是 sh信号无法正确传递给应用
---

View File

@@ -183,8 +183,10 @@ services:
image: postgres:15
volumes:
# 命名卷(推荐)
- postgres_data:/var/lib/postgresql/data
# Bind Mount
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:

View File

@@ -8,4 +8,3 @@
* [数据卷](volume.md)
* [挂载主机目录](bind-mounts.md)

View File

@@ -86,18 +86,14 @@ $ docker run -h myweb nginx
#### Q: 容器无法解析域名
**现象**`ping www.baidu.com` 失败 `ping 8.8.8.8` 成功
**解决**
**现象**`ping www.baidu.com` 失败 `ping 8.8.8.8` 成功**解决**
1. 宿主机的 `/etc/resolv.conf` 可能有问题例如使用了本地回环地址 127.0.0.53特别是 Ubuntu 系统Docker 可能会尝试修复但有时会失败
2. 尝试手动指定 DNS`docker run --dns 8.8.8.8 ...`
3. 检查防火墙是否拦截了 UDP 53 端口
#### Q: 无法通过容器名通信
**现象**`ping db` 提示 `bad address 'db'`
**原因**
**现象**`ping db` 提示 `bad address 'db'`**原因**
- 你可能在使用**默认的 bridge 网络**默认 bridge 网络**不支持**通过容器名进行 DNS 解析这是一个历史遗留设计
- **解决**使用自定义网络 (`docker network create ...`)

View File

@@ -16,6 +16,7 @@ BuildKit 引入了多项新指令,旨在优化构建缓存和安全性。以
```docker
## syntax=docker/dockerfile:1
```
这将使用最新的稳定版语法解析器确保你可以使用所有最新特性
@@ -79,6 +80,7 @@ FROM nginx:alpine
RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
# --mount=type=cache,target/tmp/dist,from=my_app_dist,sharing=locked \
mkdir -p /app/dist && cp -r /tmp/dist/* /app/dist
```

View File

@@ -46,7 +46,7 @@ Docker Compose version v2.40.3
运行以下命令
```bash
$ curl -L https://raw.githubusercontent.com/docker/compose/v2.40.3/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose
$ curl -L https://raw.githubusercontent.com/docker/compose/v2.40.3/contrib/completion/bash/docker-compose | sudo tee /etc/bash_completion.d/docker-compose > /dev/null
```
### 卸载

View File

@@ -291,9 +291,7 @@ $ docker compose exec db psql -U django_user -d django_db
#### Q1: 数据库连接失败
**错误信息**`django.db.utils.OperationalError: could not connect to server`
**可能原因与解决方案**
**错误信息**`django.db.utils.OperationalError: could not connect to server`**可能原因与解决方案**
| 原因 | 解决方案 |
|------|---------|
@@ -336,9 +334,7 @@ $ sudo chown -R $USER:$USER .
| **DEBUG** | `True` | `False` |
| **密码管理** | 明文写在配置 | 使用 Docker Secrets 或环境变量 |
| **Volume** | 挂载代码目录 | 代码直接 COPY 进镜像 |
| **ALLOWED_HOSTS** | `['*']` | 具体域名 |
**生产环境 Compose 文件示例**
| **ALLOWED_HOSTS**| `['*']` | 具体域名 |**生产环境 Compose 文件示例**
```yaml
## compose.prod.yaml
@@ -348,10 +344,12 @@ services:
build: .
command: gunicorn mysite.wsgi:application --bind 0.0.0.0:8000
# 不挂载代码,使用镜像内的代码
environment:
DEBUG: 'False'
ALLOWED_HOSTS: 'example.com,www.example.com'
# ...
```
### 延伸阅读

View File

@@ -23,12 +23,14 @@ wordpress/
```yaml
services:
# 数据库服务
db:
image: mysql:8.0
container_name: wordpress_db
restart: always
command:
# 使用原生密码认证(旧版 WP 兼容性)
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
@@ -43,6 +45,7 @@ services:
- wp_net
# WordPress 服务
wordpress:
image: wordpress:latest
container_name: wordpress_app
@@ -57,6 +60,7 @@ services:
volumes:
- wp_data:/var/www/html
# 增加上传文件大小限制
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
depends_on:
- db
@@ -185,9 +189,7 @@ WordPress 支持 Redis 缓存以提高性能。
#### Q: 数据库连接错误
**现象**访问页面显示 "Error establishing a database connection"
**排查**
**现象**访问页面显示 "Error establishing a database connection"**排查**
1. 检查 `docker compose logs wordpress`
2. 确认 `.env` 中的密码与 YAML 文件引用一致
3. 确认 `WORDPRESS_DB_HOST` 也是 `db`服务名

View File

@@ -13,4 +13,3 @@
* [实战 Rails](10.7_rails.md)
* [实战 WordPress](10.8_wordpress.md)
* [实战 LNMP](10.9_lnmp.md)

View File

@@ -1,6 +1,5 @@
## ELK/EFK 堆栈
ELK (Elasticsearch, Logstash, Kibana) 是目前业界最流行的开源日志解决方案而在容器领域由于 Fluentd 更加轻量级且对容器支持更好EFK (Elasticsearch, Fluentd, Kibana) 组合也变得非常流行
### 方案架构
@@ -14,7 +13,6 @@ ELK (Elasticsearch, Logstash, Kibana) 是目前业界最流行的开源日志解
### 部署流程
我们将使用 Docker Compose 来一键部署整个日志堆栈
#### 1. 编写 Compose 文件

View File

@@ -1,6 +1,5 @@
## Prometheus + Grafana
Prometheus Grafana 是目前最流行的开源监控组合前者负责数据采集与存储后者负责数据可视化
[Prometheus](https://prometheus.io/) 是一个开源的系统监控和报警工具包。它受 Google Borgmon 的启发,由 SoundCloud 在 2012 年创建。
@@ -16,7 +15,6 @@ Prometheus 的主要组件包括:
### 快速部署
我们可以使用 Docker Compose 快速部署一套 Prometheus + Grafana 监控环境
#### 1. 准备配置文件

View File

@@ -1,6 +1,5 @@
## 内核能力机制
Docker 利用 Linux 的能力机制Capabilities来限制容器的权限从而提高系统的安全性
[能力机制Capability](https://man7.org/linux/man-pages/man7/capabilities.7.html) 是 Linux 内核一个强大的特性,可以提供细粒度的权限访问控制。

View File

@@ -1,6 +1,5 @@
## 内核命名空间
命名空间Namespace Linux 容器隔离的基础它确保了容器内的进程无法干扰主机或其他容器
Docker 容器和 LXC 容器很相似所提供的安全特性也差不多当用 `docker run` 启动一个容器时在后台 Docker 为容器创建了一个独立的命名空间和控制组集合

View File

@@ -1,6 +1,5 @@
## 其它安全特性
除了上述机制Linux 内核还提供了一系列安全增强功能可以进一步保护容器环境
除了能力机制之外还可以利用一些现有的安全机制来增强使用 Docker 的安全性例如 TOMOYO, AppArmor, Seccomp, SELinux, GRSEC

View File

@@ -1,6 +1,5 @@
## 总结
Docker 的安全性依赖于多层隔离机制的协同工作同时需要用户遵循最佳实践
总体来看Docker 容器还是十分安全的特别是在容器内不使用 root 权限来运行进程的话

View File

@@ -67,7 +67,7 @@ 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

View File

@@ -10,7 +10,7 @@
参考 [安装 Docker](../../03_install/README.md) 一节安装 Docker
### 安装 **kubelet** **kubeadm** **kubectl**
### 安装 **kubelet****kubeadm****kubectl**
需要在每台机器上安装以下的软件包
@@ -80,6 +80,7 @@ kubelet 默认要求禁用 swap否则可能导致初始化失败或节点无
$ sudo swapoff -a
## 如需永久禁用,可在 /etc/fstab 中注释 swap 对应行
```
运行以下命令
@@ -232,6 +233,7 @@ $ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.26.1/
$ kubectl taint nodes --all node-role.kubernetes.io/master-
## 部分较新版本使用 control-plane taint
## $ kubectl taint nodes --all node-role.kubernetes.io/control-plane-
## 恢复默认值

View File

@@ -78,8 +78,10 @@ oom_score = 0
tcp_tls_cert = ""
tcp_tls_key = ""
# socket uid
uid = 0
# socket gid
gid = 0
max_recv_message_size = 16777216
max_send_message_size = 16777216
@@ -121,6 +123,7 @@ oom_score = 0
sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.10"
stats_collect_period = 10
# systemd_cgroup = false
enable_tls_streaming = false
max_container_log_line_size = 16384
disable_cgroup = false
@@ -147,36 +150,50 @@ oom_score = 0
base_runtime_spec = ""
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
# SystemdCgroup enables systemd cgroups.
SystemdCgroup = true
# BinaryName is the binary name of the runc binary.
# BinaryName = "runc"
# BinaryName = "crun"
# NoPivotRoot disables pivot root when creating a container.
# NoPivotRoot = false
# NoNewKeyring disables new keyring for the container.
# NoNewKeyring = false
# ShimCgroup places the shim in a cgroup.
# ShimCgroup = ""
# IoUid sets the I/O's pipes uid.
# IoUid = 0
# IoGid sets the I/O's pipes gid.
# IoGid = 0
# Root is the runc root directory.
Root = ""
# CriuPath is the criu binary path.
# CriuPath = ""
# CriuImagePath is the criu image path
# CriuImagePath = ""
# CriuWorkPath is the criu work path.
# CriuWorkPath = ""
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "/opt/cni/bin"
conf_dir = "/etc/cni/net.d"
@@ -186,6 +203,7 @@ oom_score = 0
config_path = "/etc/cri-containerd/certs.d"
[plugins."io.containerd.grpc.v1.cri".registry.headers]
# Foo = ["bar"]
[plugins."io.containerd.grpc.v1.cri".image_decryption]
key_model = ""
[plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
@@ -210,7 +228,7 @@ oom_score = 0
async_remove = false
```
### 安装 **kubelet** **kubeadm** **kubectl** **cri-tools** **kubernetes-cni**
### 安装 **kubelet****kubeadm****kubectl****cri-tools****kubernetes-cni**
需要在每台机器上安装以下的软件包
@@ -280,6 +298,7 @@ kubelet 默认要求禁用 swap否则可能导致初始化失败或节点无
$ sudo swapoff -a
## 如需永久禁用,可在 /etc/fstab 中注释 swap 对应行
```
运行以下命令
@@ -448,6 +467,7 @@ $ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.26.1/
$ kubectl taint nodes --all node-role.kubernetes.io/master-
## 部分较新版本使用 control-plane taint
## $ kubectl taint nodes --all node-role.kubernetes.io/control-plane-
## 恢复默认值

View File

@@ -95,12 +95,9 @@ flowchart TD
Shim -.-> |8. Monitor IO/Exit| Container
```
1. **CLI**发送请求给**Dockerd**
2. **Dockerd**解析请求调用**Containerd**
3. **Containerd** 准备镜像转换为 OCI Bundle
1. **CLI**发送请求给**Dockerd**2.**Dockerd**解析请求调用**Containerd**3.**Containerd** 准备镜像转换为 OCI Bundle
4. **Containerd**创建**Shim** 进程
5. **Shim**调用**Runc**
6. **Runc** 与系统内核交互创建 Namespaces Cgroups
5. **Shim**调用**Runc**6.**Runc** 与系统内核交互创建 Namespaces Cgroups
7. **Runc** 启动 nginx 进程后退出
8. **Shim** 接管容器 IO 和生命周期监控

View File

@@ -2,9 +2,7 @@
### 什么是 Namespace
> **Namespace Linux 内核提供的资源隔离机制它让容器内的进程仿佛运行在独立的操作系统中**
Namespace 是容器技术的核心基础之一它回答了一个关键问题**如何让一个进程"以为"自己独占整个系统**
> **Namespace Linux 内核提供的资源隔离机制它让容器内的进程仿佛运行在独立的操作系统中**Namespace 是容器技术的核心基础之一它回答了一个关键问题**如何让一个进程"以为"自己独占整个系统**
```
宿主机视角: 容器内视角:

View File

@@ -18,4 +18,3 @@ Docker 底层的核心技术包括 Linux 上的命名空间Namespaces
* [联合文件系统](14.4_ufs.md)
* [容器格式](14.5_container_format.md)
* [网络](14.6_network.md)

View File

@@ -1,9 +1,6 @@
# CI/CD
**持续集成Continuous integration** 是一种软件开发实践每次集成都通过自动化的构建包括编译发布自动化测试来验证从而尽早地发现集成错误
**持续部署continuous deployment** 是通过自动化的构建测试和部署循环来快速交付高质量的产品
**持续集成Continuous integration**是一种软件开发实践每次集成都通过自动化的构建包括编译发布自动化测试来验证从而尽早地发现集成错误**持续部署continuous deployment** 是通过自动化的构建测试和部署循环来快速交付高质量的产品
`Jenkins` 不同的是基于 Docker CI/CD 每一步都运行在 Docker 容器中所以理论上支持所有的编程语言

View File

@@ -1,6 +1,5 @@
## VS Code 中使用 Docker
### Docker 容器作为远程开发环境
无需本地安装开发工具直接将 Docker 容器作为开发环境具体参考 [官方文档](https://code.visualstudio.com/docs/remote/containers)。

View File

@@ -7,4 +7,3 @@
使用 Docker读者只需要一个命令就能快速获取一个 Linux 发行版镜像这是以往包括各种虚拟化技术都难以实现的这些镜像一般都很精简但是可以支持完整 Linux 系统的大部分功能
本章将介绍如何使用 Docker 安装和使用 `Busybox``Alpine``Debian/Ubuntu``CentOS/Fedora` 等操作系统

View File

@@ -35,7 +35,6 @@ $ docker run alpine echo '123'
### 迁移至 Alpine 基础镜像
目前大部分 Docker 官方镜像都已经支持 `Alpine` 作为基础镜像可以很容易进行迁移
例如

View File

@@ -1,6 +1,5 @@
## CentOS Fedora
### CentOS 系统简介
`CentOS` `Fedora` 都是基于 `Redhat` 的常见 Linux 分支`CentOS` 是目前企业级服务器的常用操作系统`Fedora` 则主要面向个人桌面用户

View File

@@ -1,4 +1,4 @@
## [CentOS](https://hub.docker.com/_/centos)
## [CentOS]
### 基本信息

View File

@@ -1,4 +1,4 @@
## [MongoDB](https://hub.docker.com/_/mongo/)
## [MongoDB]
### 基本信息

View File

@@ -1,4 +1,4 @@
## [MySQL](https://hub.docker.com/_/mysql/)
## [MySQL]
### 基本信息

View File

@@ -1,4 +1,4 @@
## [Nginx](https://hub.docker.com/_/nginx/)
## [Nginx]
### 基本信息

View File

@@ -1,4 +1,4 @@
## [Node.js](https://hub.docker.com/_/node/)
## [Node.js]
### 基本信息
@@ -29,7 +29,8 @@ $ docker run -it --rm --name my-running-app my-nodejs-app
```bash
$ docker run -it --rm \
--name my-running-script \
# -v "$(pwd)":/usr/src/myapp \
# -v "$ ":/usr/src/myapp \
--mount type=bind,src="$(pwd)",target=/usr/src/myapp \
-w /usr/src/myapp \
node:12-alpine \

View File

@@ -1,4 +1,4 @@
## [PHP](https://hub.docker.com/_/php/)
## [PHP]
### 基本信息

View File

@@ -1,4 +1,4 @@
## [Redis](https://hub.docker.com/_/redis/)
## [Redis]
### 基本信息

View File

@@ -1,4 +1,4 @@
## [Ubuntu](https://hub.docker.com/_/ubuntu/)
## [Ubuntu]
### 基本信息

View File

@@ -1,4 +1,4 @@
## [WordPress](https://hub.docker.com/_/wordpress/)
## [WordPress]
### 基本信息

View File

@@ -7,15 +7,16 @@
"chalk": "^4.1.1",
"commander": "^7.2.0",
"esm": "^3.0.0",
"honkit": "^5.1.0",
"vuepress": "1.8.2",
"vuepress-plugin-container": "^2.1.5",
"vuepress-theme-hope": "^1.0.0"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"gitbook:help": "gitbook help",
"gitbook:build": "gitbook build",
"gitbook:serve": "gitbook serve",
"honkit:help": "npx honkit help",
"honkit:build": "npx honkit build",
"honkit:serve": "npx honkit serve",
"vuepress:build": "npx vuepress build",
"vuepress": "npx vuepress"
},