Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion 01_introduction/1.3_why.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ $ docker compose up

Docker 容器共享宿主机内核,无需为每个应用运行完整的操作系统。以一台 64GB 内存的物理服务器为例:
- **传统虚拟机方案**:每个虚拟机都需要运行完整的操作系统(每个额外占用如 2GB 内存),产生大量资源开销,实际可用于应用的内存可能只有约 18GB。
- **Docker 方案**:容器直接共享宿主机系统,只需付出很少的基础开销(OS及引擎约 4GB),即可将约 60GB 的内存全部用于实际应用。
- **Docker 方案**:容器直接共享宿主机系统,只需付出很少的基础开销(OS 及引擎约 4GB),即可将约 60GB 的内存全部用于实际应用。

```mermaid
flowchart TD
Expand Down
2 changes: 1 addition & 1 deletion 01_introduction/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

本章将带领你进入 **Docker** 的世界。

> **版本提示**:本书内容及示例基于 **Docker Engine v29.x** 及以上版本。值得注意的是,自 Docker Engine v29 起,官方在全新安装场景下**默认启用了 `containerd image store` 作为镜像存储后端**(取代了传统的经典存储引擎如 overlay2 graph driver)。这项底层革新极大增强了 Docker 对多架构镜像(Multi-platform)、以及软件供应链安全元数据(Attestations, SBOM, Provenance)的本地支持原生性。
> **版本提示**:本书内容及示例基于 **Docker Engine v29.x** 及以上版本。值得注意的是,自 Docker Engine v29 起,官方在全新安装场景下 **默认启用了 `containerd image store` 作为镜像存储后端**(取代了传统的经典存储引擎如 overlay2 graph driver)。这项底层革新极大增强了 Docker 对多架构镜像(Multi-platform)、以及软件供应链安全元数据(Attestations, SBOM, Provenance)的本地支持原生性。

## 本章内容

Expand Down
2 changes: 1 addition & 1 deletion 02_basic_concept/2.3_repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ flowchart TB
一个完整的 Docker 镜像名称由 Registry 地址、用户名/组织名、仓库名和标签组成。了解其结构有助于我们更准确地定位镜像。基本格式如下:

```bash
[registry地址/][用户名/]仓库名[:标签]
[registry 地址/][用户名/]仓库名[:标签]
```

示例:
Expand Down
6 changes: 6 additions & 0 deletions 02_basic_concept/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@
* **仓库** (`Repository`):镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。

理解了这三个概念,就理解了 **Docker** 的整个生命周期。

## 本章内容

* [Docker 镜像](2.1_image.md)
* [Docker 容器](2.2_container.md)
* [Docker 仓库](2.3_repository.md)
2 changes: 1 addition & 1 deletion 02_basic_concept/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
- [Dockerfile 最佳实践](../appendix/best_practices.md):构建高质量镜像的技巧
- [底层实现 - 联合文件系统](../12_implementation/12.4_ufs.md):深入理解分层存储的技术原理
- [启动容器](../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/README.md):Volume 和数据持久化详解
- [Docker Hub](../06_repository/6.1_dockerhub.md):Docker Hub 的详细使用
Expand Down
2 changes: 1 addition & 1 deletion 03_install/3.8_windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

下载好之后双击 `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
Expand Down
Binary file modified 03_install/3.9_mirror.md
Binary file not shown.
Binary file modified 04_image/4.5_build.md
Binary file not shown.
5 changes: 3 additions & 2 deletions 06_repository/6.1_dockerhub.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ $ docker push username/myapp:v1
| **免费账户** (已登录) | 每 6 小时 200 次请求 |
| **Pro/Team 账户** | 无限制 |

#### 滥用限流 (Abuse Rate Limit)
#### 滥用限流

除了上述针对特定账号拉取镜像数量的 Pull Rate Limit 之外,Docker Hub 对所有用户(包含已认证及付费用户)还实施了**滥用保护限流 (Abuse Rate Limiting)**。它是根据网络出口 IP (IPv4 或 IPv6 /64 子网) 计算整体请求频率,阈值动态触发(通常为每分钟数千级别请求)。
除了上述针对特定账号拉取镜像数量的 Pull Rate Limit 之外,Docker Hub 对所有用户(包含已认证及付费用户)还实施了 **滥用保护限流 (Abuse Rate Limiting)**。它是根据网络出口 IP (IPv4 或 IPv6 /64 子网) 计算整体请求频率,阈值动态触发(通常为每分钟数千级别请求)。

**两类的差异与排查方法**:
- **Pull Rate Limit**:针对拉取量达到上限。报错返回 `429 Too Many Requests`,并且 HTTP 返回体/CLI 错误提示中会带有明确的 `toomanyrequests: You have reached your pull rate limit` 提示,常附有账户升级链接。
Expand All @@ -102,6 +102,7 @@ $ docker push username/myapp:v1
在 Account Settings -> Security 中启用 2FA,保护账号安全。启用后,CLI 登录需要使用 **Access Token** 而非密码。

#### 2. 使用 Access Token

> **⚠️ 警告**:绝不要在脚本或 CI/CD 系统中,直接使用 `-p` 参数传递密码或 Token (类似 `docker login -p xxx`)!这会导致凭证直接暴露在系统的命令历史、进程列表和终端输出中。

1. 在 Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token (PAT)。
Expand Down
Binary file modified 06_repository/6.2_registry.md
Binary file not shown.
Binary file modified 06_repository/6.4_nexus3_registry.md
Binary file not shown.
2 changes: 1 addition & 1 deletion 06_repository/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
| 功能 | 说明 |
|------|------|
| **官方镜像** | 优先使用的基础镜像 |
| **拉取限制** | 匿名 100次/6h,登录 200次/6h |
| **拉取限制** | 匿名 100 次/6h,登录 200 次/6h |
| **安全** | 推荐开启 2FA 并使用 Access Token |
| **自动化** | 支持 Webhooks 和自动构建 |

Expand Down
35 changes: 32 additions & 3 deletions 07_dockerfile/7.16_references.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
## 7.16 参考文档

* `Dockerfile` 官方文档:https://docs.docker.com/engine/reference/builder/
### 官方文档

* `Dockerfile` 最佳实践文档:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
* `Dockerfile` 官方参考手册:https://docs.docker.com/engine/reference/builder/

* `Docker` 官方镜像 `Dockerfile`:https://github.com/docker-library/docs
* `Dockerfile` 最佳实践指南:https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

* `Docker` 官方镜像 `Dockerfile` 库:https://github.com/docker-library/docs

### 常用指令总结

Dockerfile 中的常用指令包括:

- **FROM**: 指定基础镜像,必须是第一条指令
- **RUN**: 在镜像中执行命令,用于安装软件包等
- **WORKDIR**: 设置工作目录
- **COPY/ADD**: 复制文件到镜像中
- **EXPOSE**: 声明容器监听的端口
- **ENV**: 设置环境变量
- **ENTRYPOINT**: 容器启动时的入口点
- **CMD**: 容器默认执行的命令

### 最佳实践建议

1. 使用具体的基础镜像版本标签而非 latest
2. 最小化镜像层数,合并 RUN 指令
3. 使用 .dockerignore 文件排除不必要的文件
4. 安装必要的软件包后清理缓存
5. 使用多阶段构建减小最终镜像体积
6. 避免以 root 身份运行容器应用

### 相关资源

- Docker 官方镜像库:https://hub.docker.com/
- Docker 镜像构建最佳实践:https://docs.docker.com/build/building/best-practices/
6 changes: 3 additions & 3 deletions 07_dockerfile/7.17_multistage_builds.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
```

## 7.17 使用多阶段构建
### 7.17.3 使用多阶段构建

为解决以上问题,Docker v17.05 开始支持多阶段构建 (`multistage builds`)。使用多阶段构建我们就可以很容易解决前面提到的问题,并且只需要编写一个 `Dockerfile`:

Expand Down Expand Up @@ -167,7 +167,7 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB

很明显使用多阶段构建的镜像体积小,同时也完美解决了上边提到的问题。

### 7.17.1 只构建某一阶段的镜像
### 7.17.4 只构建某一阶段的镜像

我们可以使用 `as` 来为某一阶段命名,例如

Expand All @@ -181,7 +181,7 @@ FROM golang:alpine as builder
$ docker build --target builder -t username/imagename:tag .
```

### 7.17.2 构建时从其他镜像复制文件
### 7.17.5 构建时从其他镜像复制文件

上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件,我们也可以复制任意镜像中的文件。

Expand Down
9 changes: 9 additions & 0 deletions 07_dockerfile/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像
* [LABEL 为镜像添加元数据](7.14_label.md)
* [SHELL 指令](7.15_shell.md)

### 高级特性

本章还将介绍 Dockerfile 的高级特性:

* [多阶段构建](7.17_multistage_builds.md)
* [多阶段构建实战:Laravel 应用](7.18_multistage_builds_laravel.md)

### 参考与最佳实践

此外,我们还将介绍 Dockerfile 的最佳实践和常见问题。

* [参考文档](7.16_references.md)
Expand Down
4 changes: 2 additions & 2 deletions 08_data/8.1_volume.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ $ docker run -d \
|------|---------|-----|
| 语法 | 键值对,更清晰 | 冒号分隔,更简洁 |
| **数据卷 (Volume)** 挂载行为 | 卷不存在会自动创建,与 `-v` 结果一致 | 卷不存在会自动创建 |
| **绑定挂载 (Bind Mount)** 行为 | ⭐ **宿主机路径不存在会报错**,不会自动创建 | 宿主机路径不存在会**自动创建为目录** |
| **绑定挂载 (Bind Mount)** 行为 | ⭐**宿主机路径不存在会报错**,不会自动创建 | 宿主机路径不存在会 **自动创建为目录** |
| 推荐程度 | ✅ 推荐 (更明确安全,避免误创建)| 常用 (更简洁)|

> **提示**:官方更推荐使用 `--mount`。除了语法格式可读性更好之外,最重要的行为差异发生在 **绑定挂载 (Bind Mount)** 时:如果挂载的宿主机源路径尚未存在,`-v` 会擅自将其自动创建为一个空目录;而 `--mount` 则会严格检查并直接报错。这能有效避免因路径拼写错误而在宿主机上留下垃圾目录(以及导致的容器访问空目录问题)。而对于本节的**数据卷 (Volume)** 挂载而言,两者在目标指定的卷不存在时皆会自动创建卷,产生的结果是**完全一致**的。
> **提示**:官方更推荐使用 `--mount`。除了语法格式可读性更好之外,最重要的行为差异发生在 **绑定挂载 (Bind Mount)** 时:如果挂载的宿主机源路径尚未存在,`-v` 会擅自将其自动创建为一个空目录;而 `--mount` 则会严格检查并直接报错。这能有效避免因路径拼写错误而在宿主机上留下垃圾目录(以及导致的容器访问空目录问题)。而对于本节的 **数据卷 (Volume)** 挂载而言,两者在目标指定的卷不存在时皆会自动创建卷,产生的结果是 **完全一致** 的。

#### 只读挂载

Expand Down
4 changes: 2 additions & 2 deletions 08_data/8.2_bind-mounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ $ docker run -d \
| 特性 | --mount | -v |
|------|---------|-----|
| 语法 | 键值对,更清晰 | 冒号分隔,更简洁 |
| 路径不存在时 | 直接报错 (Fail Fast) | 静默自动创建**目录** |
| 路径不存在时 | 直接报错 (Fail Fast) | 静默自动创建 **目录** |
| 推荐程度 | ✅ 推荐 | 常用 |

> **⚠️ 陷阱**:如果不小心挂载了一个不存在的宿主机路径,使用 `-v` 会在宿主机上静默创建一个**空目录**(即使你本来想挂载的是一个文件),这常常会导致权限错误或应用无法正常读取。这也正是为什么 Docker 官方更推荐使用 `--mount` 的原因:它会遵循“Fail Fast”原则直接报错,避免弄巧成拙。
> **⚠️ 陷阱**:如果不小心挂载了一个不存在的宿主机路径,使用 `-v` 会在宿主机上静默创建一个 **空目录**(即使你本来想挂载的是一个文件),这常常会导致权限错误或应用无法正常读取。这也正是为什么 Docker 官方更推荐使用 `--mount` 的原因:它会遵循“Fail Fast”原则直接报错,避免弄巧成拙。

---

Expand Down
2 changes: 1 addition & 1 deletion 09_network/9.1_dns.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Docker 1.10.0 以后,内建了一个 DNS 服务器,使得容器可以直接
Docker 容器的 DNS 配置有两种情况:

1. **默认 Bridge 网络**:继承宿主机的 DNS 配置 (`/etc/resolv.conf`)。
2. **自定义网络** (推荐):使用 Docker 嵌入式 DNS 服务器 (Embedded DNS),支持通过 **容器名** 进行服务发现。
2. **自定义网络**(推荐):使用 Docker 嵌入式 DNS 服务器 (Embedded DNS),支持通过 **容器名** 进行服务发现。

---

Expand Down
10 changes: 5 additions & 5 deletions 09_network/9.3_custom_network.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

在生产环境中,推荐使用用户自定义网络代替默认的 bridge 网络。自定义网络提供了更好的隔离性和服务发现能力。

### 9.4.1 为什么要用自定义网络
### 9.3.1 为什么要用自定义网络

默认 bridge 网络存在以下局限,而自定义网络可以很好地解决这些问题:

Expand All @@ -12,7 +12,7 @@
| 所有容器在同一网络 | 更好的隔离性 |
| 需要 --link (已废弃)| 原生支持服务发现 |

### 9.4.2 创建自定义网络
### 9.3.2 创建自定义网络

使用 `docker network create` 命令可以创建自定义网络:

Expand All @@ -26,7 +26,7 @@ $ docker network create mynet
$ docker network inspect mynet
```

### 9.4.3 使用自定义网络
### 9.3.3 使用自定义网络

启动容器时通过 `--network` 参数指定连接的网络:

Expand All @@ -43,7 +43,7 @@ PING db (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.083 ms
```

### 9.4.4 容器名 DNS 解析
### 9.3.4 容器名 DNS 解析

自定义网络自动提供 DNS 服务。Docker 守护进程在 `127.0.0.11` 运行了一个嵌入式 DNS 服务器,容器内的 DNS 请求会被转发到这里:

Expand All @@ -58,7 +58,7 @@ flowchart LR
end
```

### 9.4.5 常用网络命令
### 9.3.5 常用网络命令

以下是 Docker 网络管理中常用的命令:

Expand Down
6 changes: 3 additions & 3 deletions 09_network/9.4_container_linking.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

容器之间的网络通信是 Docker 网络的核心功能之一。本节介绍容器互联的几种方式。

### 9.5.1 同一网络内的容器
### 9.4.1 同一网络内的容器

同一自定义网络内的容器可以直接通过容器名通信,这是推荐的容器互联方式:

Expand All @@ -21,7 +21,7 @@ $ docker run -d --name app --network app-net myapp
...
```

### 9.5.2 连接到多个网络
### 9.4.2 连接到多个网络

一个容器可以同时连接到多个网络,这对于需要跨网络通信的中间件容器特别有用:

Expand All @@ -39,7 +39,7 @@ $ docker network connect backend multi-net-container
$ docker inspect multi-net-container --format '{{json .NetworkSettings.Networks}}'
```

### 9.5.3 ⚠️ --link 已废弃
### 9.4.3 ⚠️ --link 已废弃

`--link` 是 Docker 早期用于容器互联的方式,**已经被废弃**,不建议在新项目中使用。请使用自定义网络替代:

Expand Down
10 changes: 5 additions & 5 deletions 09_network/9.5_port_mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

容器运行在自己的隔离网络环境中 (通常是 Bridge 模式)。为了让外部网络访问容器内的服务,我们需要将容器的端口映射到宿主机的端口。

### 9.6.1 为什么要映射端口
### 9.5.1 为什么要映射端口

容器的网络访问规则如下:

Expand All @@ -21,7 +21,7 @@ flowchart TD

---

### 9.6.2 端口映射方式
### 9.5.2 端口映射方式

Docker 提供了多种方式来指定端口映射。

Expand Down Expand Up @@ -66,7 +66,7 @@ abc123456 0.0.0.0:49153->80/tcp

---

### 9.6.3 查看端口映射
### 9.5.3 查看端口映射

可以使用以下命令查看容器的端口映射:

Expand All @@ -92,7 +92,7 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web

---

### 9.6.4 最佳实践与安全
### 9.5.4 最佳实践与安全

在配置端口映射时,需要注意以下安全事项:

Expand Down Expand Up @@ -127,7 +127,7 @@ $ docker run -d -p 53:53/udp dns-server

---

### 9.6.5 实现原理
### 9.5.5 实现原理

Docker 使用 `docker-proxy` 进程 (用户态) 或 `iptables` DNAT 规则 (内核态) 来实现端口转发。

Expand Down
8 changes: 4 additions & 4 deletions 09_network/9.6_network_isolation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Docker 网络提供了天然的隔离能力,不同网络之间的容器默认无法通信。这是 Docker 网络安全的重要基础。

### 9.7.1 网络隔离原理
### 9.6.1 网络隔离原理

不同网络之间默认隔离,容器只能与同一网络中的容器直接通信:

Expand All @@ -26,7 +26,7 @@ $ docker exec web ping db
ping: db: Name or service not known
```

### 9.7.2 安全优势
### 9.6.2 安全优势

这种隔离机制带来以下安全优势:

Expand All @@ -37,7 +37,7 @@ ping: db: Name or service not known
| **多租户** | 不同租户的容器在不同网络中完全隔离 |
| **最小权限** | 容器只能访问必要的网络资源 |

### 9.7.3 跨网络通信
### 9.6.3 跨网络通信

如果确实需要某个容器跨网络通信,可以将其同时连接到多个网络:

Expand All @@ -52,7 +52,7 @@ $ docker network connect backend api

这种方式让你可以精确控制哪些容器可以跨网络通信,遵循最小权限原则。

### 9.7.4 典型网络架构
### 9.6.4 典型网络架构

一个典型的多层应用网络架构如下:

Expand Down
Loading