Use a better structure

This commit is contained in:
Baohua Yang
2026-02-09 09:32:05 -08:00
parent fdb879dcf2
commit e669ee0fe8
167 changed files with 2462 additions and 2462 deletions

View File

@@ -1,12 +1,12 @@
# Docker 镜像
## Docker 镜像
## 一句话理解镜像
### 一句话理解镜像
> **Docker 镜像是一个只读的模板包含了运行应用所需的一切代码运行时环境变量和配置文件**
如果用一个类比**镜像就像是一张光盘或 ISO 文件**你可以用同一张光盘在不同电脑上安装系统而光盘本身不会被修改同样一个镜像可以创建多个容器而镜像本身保持不变
## 镜像与操作系统的关系
### 镜像与操作系统的关系
我们都知道操作系统分为**内核****用户空间**
@@ -27,7 +27,7 @@
例如官方镜像 `ubuntu:24.04` 包含了一套完整的 Ubuntu 24.04 最小系统的 root 文件系统**不包含 Linux 内核**因为容器共享宿主机的内核
## 镜像包含什么
### 镜像包含什么
Docker 镜像是一个特殊的文件系统包含
@@ -44,9 +44,9 @@ Docker 镜像是一个特殊的文件系统,包含:
- 镜像**不包含**动态数据
- 镜像构建后**内容不会改变**
## 分层存储镜像的核心设计
### 分层存储镜像的核心设计
### 为什么需要分层
#### 为什么需要分层
笔者认为分层存储是 Docker 最巧妙的设计之一
@@ -76,7 +76,7 @@ Docker 分层方式:
总计620MB
```
### 分层是如何工作的
#### 分层是如何工作的
笔者用一个实际的 Dockerfile 来解释分层
@@ -106,24 +106,24 @@ COPY app.conf /etc/nginx/ # 第 4 层:复制配置文件
- **可共享**多个镜像可以共享相同的层
- **有缓存**未变化的层不会重新构建
### 分层存储的"陷阱"
#### 分层存储的"陷阱"
> **笔者特别提醒**理解这一点可以帮你避免构建出臃肿的镜像
**关键原理**每一层的文件变化会被记录**删除操作只是标记不会真正减小镜像体积**
```docker
# 错误示范
## 错误示范
FROM ubuntu:24.04
RUN apt-get update
RUN apt-get install -y build-essential # 安装编译工具 200MB
RUN make && make install # 编译应用
RUN apt-get remove build-essential # 试图删除编译工具
# 结果镜像仍然包含 200MB 的编译工具
## 结果镜像仍然包含 200MB 的编译工具
```
```docker
# 正确做法
## 正确做法
FROM ubuntu:24.04
RUN apt-get update && \
apt-get install -y build-essential && \
@@ -131,13 +131,13 @@ RUN apt-get update && \
apt-get remove -y build-essential && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/*
# 在同一层完成安装使用清理
## 在同一层完成安装使用清理
```
### 查看镜像的分层
#### 查看镜像的分层
```bash
# 查看镜像的历史每层的构建记录
## 查看镜像的历史每层的构建记录
$ docker history nginx:latest
IMAGE CREATED CREATED BY SIZE
@@ -149,27 +149,27 @@ a6bd71f48f68 2 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B
...
```
## 镜像的标识
### 镜像的标识
Docker 镜像有多种标识方式
### 1. 镜像名称和标签
#### 1. 镜像名称和标签
格式`[仓库地址/]仓库名[:标签]`
```bash
# 完整格式
## 完整格式
registry.example.com/myproject/myapp:v1.2.3
# 简写使用 Docker Hub
## 简写使用 Docker Hub
nginx:1.25
ubuntu:24.04
# 省略标签默认使用 latest
## 省略标签默认使用 latest
nginx # 等同于 nginx:latest
```
### 2. 镜像 IDContent-Addressable
#### 2. 镜像 IDContent-Addressable
每个镜像有一个基于内容计算的唯一 ID
@@ -180,7 +180,7 @@ nginx latest a6bd71f48f68 2 weeks ago 187MB
ubuntu 24.04 ca2b0f26964c 3 weeks ago 78.1MB
```
### 3. 镜像摘要Digest
#### 3. 镜像摘要Digest
更精确的标识基于镜像内容的 SHA256 哈希
@@ -192,7 +192,7 @@ nginx latest sha256:6db391d1c0cfb30588ba0bf72ea999404f2764184d8b8d10d89e8
> 💡 笔者建议在生产环境使用镜像摘要而非标签因为标签可以被覆盖但摘要是不可变的
## 镜像的来源
### 镜像的来源
Docker 镜像可以通过以下方式获取
@@ -203,7 +203,7 @@ Docker 镜像可以通过以下方式获取:
| **从容器提交** | 保存容器状态不推荐 | `docker commit` |
| **从文件导入** | 离线传输 | `docker load < image.tar` |
## 本章小结
### 本章小结
| 概念 | 要点 |
|------|------|
@@ -212,11 +212,11 @@ Docker 镜像可以通过以下方式获取:
| **只读特性** | 构建后不可修改保证一致性 |
| **层的陷阱** | 删除操作只是标记不减小体积 |
理解了镜像接下来让我们学习[容器](container.md)镜像的运行实例
理解了镜像接下来让我们学习[容器](2.2_container.md)镜像的运行实例
## 延伸阅读
### 延伸阅读
- [获取镜像](../04_image/pull.md) Registry 下载镜像
- [使用 Dockerfile 定制镜像](../04_image/build.md)创建自己的镜像
- [Dockerfile 最佳实践](../15_appendix/best_practices.md)构建高质量镜像的技巧
- [底层实现 - 联合文件系统](../13_implementation/ufs.md)深入理解分层存储的技术原理
- [获取镜像](../04_image/4.1_pull.md) Registry 下载镜像
- [使用 Dockerfile 定制镜像](../04_image/4.5_build.md)创建自己的镜像
- [Dockerfile 最佳实践](../15_appendix/15.1_best_practices.md)构建高质量镜像的技巧
- [底层实现 - 联合文件系统](../13_implementation/13.4_ufs.md)深入理解分层存储的技术原理

View File

@@ -1,6 +1,6 @@
# Docker 容器
## Docker 容器
## 一句话理解容器
### 一句话理解容器
> **容器是镜像的运行实例如果把镜像比作程序那么容器就是进程**
@@ -10,7 +10,7 @@
- 每个容器相互独立互不影响
- 容器可以被创建启动停止删除暂停
## 容器的本质
### 容器的本质
> 💡 **笔者认为理解这一点是理解 Docker 的关键**
@@ -38,7 +38,7 @@
这种隔离是通过 Linux 内核的 **Namespace** 技术实现的
## 容器 vs 虚拟机核心区别
### 容器 vs 虚拟机核心区别
很多初学者会混淆容器和虚拟机笔者用一张图来说明
@@ -67,9 +67,9 @@
| **性能损耗** | 几乎为零 | 5-20% |
| **内核** | 共享宿主机内核 | 各自独立内核 |
## 容器的存储层
### 容器的存储层
### 镜像层 + 容器层
#### 镜像层 + 容器层
当容器运行时Docker 会在镜像的只读层之上创建一个**可写层**容器存储层
@@ -88,7 +88,7 @@
```
### Copy-on-Write写时复制
#### Copy-on-Write写时复制
当容器需要修改镜像层中的文件时
@@ -101,25 +101,25 @@
修改文件复制到容器层然后修改只有这个容器能看到修改
```
### 容器存储层的生命周期
#### 容器存储层的生命周期
> **笔者特别强调**这是新手最容易踩的坑
**容器存储层与容器生命周期绑定容器删除数据就没了**
```bash
# 创建容器写入数据
## 创建容器写入数据
$ docker run -it ubuntu bash
root@abc123:/# echo "important data" > /data.txt
root@abc123:/# exit
# 删除容器
## 删除容器
$ docker rm abc123
# 数据丢了没有任何办法恢复
## 数据丢了没有任何办法恢复
```
### 正确的数据持久化方式
#### 正确的数据持久化方式
按照 Docker 最佳实践容器存储层应该保持**无状态**需要持久化的数据应该使用
@@ -129,16 +129,16 @@ $ docker rm abc123
| **[绑定挂载Bind Mount](../07_data_network/data/bind-mounts.md)** | 挂载宿主机目录 | 开发时共享代码 |
```bash
# 使用数据卷推荐
## 使用数据卷推荐
$ docker run -v mydata:/var/lib/mysql mysql
# 使用绑定挂载
## 使用绑定挂载
$ docker run -v /host/path:/container/path nginx
```
这些位置的读写**会跳过容器存储层**直接写入宿主机性能更好也不会随容器删除而丢失
## 容器的生命周期
### 容器的生命周期
```
@@ -167,51 +167,51 @@ $ docker run -v /host/path:/container/path nginx
```
### 常用生命周期命令
#### 常用生命周期命令
```bash
# 创建并启动容器最常用
## 创建并启动容器最常用
$ docker run nginx
# 分步操作
## 分步操作
$ docker create nginx # 创建容器不启动
$ docker start abc123 # 启动容器
# 停止容器
## 停止容器
$ docker stop abc123 # 优雅停止发送 SIGTERM等待后发送 SIGKILL
$ docker kill abc123 # 强制停止直接发送 SIGKILL
# 暂停/恢复不常用但有时有用
## 暂停/恢复不常用但有时有用
$ docker pause abc123 # 暂停容器内所有进程
$ docker unpause abc123 # 恢复
# 删除容器
## 删除容器
$ docker rm abc123 # 删除已停止的容器
$ docker rm -f abc123 # 强制删除运行中的容器
```
## 容器与进程的关系
### 容器与进程的关系
> **核心概念**容器的生命周期 = 主进程PID 1的生命周期
```bash
# 主进程运行容器运行
# 主进程退出容器停止
## 主进程运行容器运行
## 主进程退出容器停止
```
这就是为什么
```bash
# 这个容器会立即退出bash 没有输入就退出了
## 这个容器会立即退出bash 没有输入就退出了
$ docker run ubuntu
# 这个容器会持续运行nginx 作为守护进程持续运行
## 这个容器会持续运行nginx 作为守护进程持续运行
$ docker run nginx
```
详细解释请参考[后台运行](../05_container/daemon.md)章节
详细解释请参考[后台运行](../05_container/5.2_daemon.md)章节
## 容器的隔离性
### 容器的隔离性
Docker 容器通过以下 Namespace 实现隔离
@@ -224,9 +224,9 @@ Docker 容器通过以下 Namespace 实现隔离:
| **IPC** | 进程间通信 | 独立的信号量消息队列 |
| **USER** | 用户 | 独立的用户和组 ID |
> 想深入了解请阅读[底层实现 - 命名空间](../13_implementation/namespace.md)
> 想深入了解请阅读[底层实现 - 命名空间](../13_implementation/13.2_namespace.md)
## 本章小结
### 本章小结
| 概念 | 要点 |
|------|------|
@@ -236,11 +236,11 @@ Docker 容器通过以下 Namespace 实现隔离:
| **数据持久化** | 使用 Volume Bind Mount |
| **生命周期** | 与主进程PID 1绑定 |
理解了镜像和容器接下来让我们学习[仓库](repository.md)存储和分发镜像的服务
理解了镜像和容器接下来让我们学习[仓库](2.3_repository.md)存储和分发镜像的服务
## 延伸阅读
### 延伸阅读
- [启动容器](../05_container/run.md)详细的容器启动选项
- [后台运行](../05_container/daemon.md)理解容器为什么会"立即退出"
- [进入容器](../05_container/attach_exec.md)如何操作运行中的容器
- [启动容器](../05_container/5.1_run.md)详细的容器启动选项
- [后台运行](../05_container/5.2_daemon.md)理解容器为什么会"立即退出"
- [进入容器](../05_container/5.4_attach_exec.md)如何操作运行中的容器
- [数据管理](../07_data_network/README.md)Volume 和数据持久化详解

View File

@@ -1,14 +1,14 @@
# Docker Registry
## Docker Registry
## 一句话理解 Registry
### 一句话理解 Registry
> **Docker Registry 是存储和分发 Docker 镜像的服务类似于代码的 GitHub 或包管理的 npm**
镜像构建完成后可以在当前机器上运行但如果需要在其他服务器上使用这个镜像就需要一个集中的存储和分发服务这就是 Docker Registry
## 核心概念
### 核心概念
### Registry仓库标签的关系
#### Registry仓库标签的关系
```
@@ -37,7 +37,7 @@
| **Repository仓库** | 同一软件的镜像集合 | `nginx``mysql``mycompany/myapp` |
| **Tag标签** | 仓库内的版本标识 | `latest``1.25``alpine` |
### 镜像的完整名称
#### 镜像的完整名称
```
[registry地址/][用户名/]仓库名[:标签]
@@ -46,7 +46,7 @@
示例
```bash
# 完整格式
## 完整格式
registry.example.com/mycompany/myapp:v1.2.3
标签
@@ -54,23 +54,23 @@ registry.example.com/mycompany/myapp:v1.2.3
用户名/组织名
Registry 地址
# Docker Hub 官方镜像省略 registry 和用户名
## Docker Hub 官方镜像省略 registry 和用户名
nginx:1.25
ubuntu:24.04
# Docker Hub 用户镜像
## Docker Hub 用户镜像
jwilder/nginx-proxy:latest
# 其他 Registry
## 其他 Registry
ghcr.io/username/myapp:v1.0
gcr.io/google-containers/pause:3.6
```
> 💡 **笔者提示**如果不指定 Registry 地址默认使用 Docker Hub如果不指定标签默认使用 `latest`
## 公共 Registry 服务
### 公共 Registry 服务
### Docker Hub默认
#### Docker Hub默认
[Docker Hub](https://hub.docker.com/) 是最大的公共 Registry也是 Docker 的默认 Registry。
@@ -80,16 +80,16 @@ gcr.io/google-containers/pause:3.6
- 付费账户支持私有仓库
```bash
# Docker Hub 拉取镜像
## Docker Hub 拉取镜像
$ docker pull nginx # 官方镜像
$ docker pull bitnami/redis # 第三方镜像
# 推送镜像到 Docker Hub
## 推送镜像到 Docker Hub
$ docker login
$ docker push username/myapp:v1.0
```
### 其他公共 Registry
#### 其他公共 Registry
| Registry | 地址 | 说明 |
|----------|------|------|
@@ -99,7 +99,7 @@ $ docker push username/myapp:v1.0
| **阿里云容器镜像服务** | registry.cn-*.aliyuncs.com | 国内访问快 |
| **腾讯云容器镜像服务** | ccr.ccs.tencentyun.com | 国内访问快 |
## 镜像加速器
### 镜像加速器
由于网络原因在国内直接访问 Docker Hub 可能会很慢可以配置**镜像加速器**Registry Mirror来加速下载
@@ -112,38 +112,38 @@ $ docker push username/myapp:v1.0
}
```
详细配置方法请参考[镜像加速器](../install/mirror.md)章节
详细配置方法请参考[镜像加速器](../install/3.9_mirror.md)章节
> **笔者提醒**镜像加速器的可用性经常变化使用前建议先测试是否可用
## 私有 Registry
### 私有 Registry
对于企业用户通常需要搭建私有 Registry 来存储内部镜像
### 官方 Registry 镜像
#### 官方 Registry 镜像
Docker 官方提供了 [registry](https://hub.docker.com/_/registry/) 镜像,可以快速搭建私有 Registry
```bash
# 启动一个本地 Registry
## 启动一个本地 Registry
$ docker run -d -p 5000:5000 --name registry registry:2
# 推送镜像到本地 Registry
## 推送镜像到本地 Registry
$ docker tag myapp:v1.0 localhost:5000/myapp:v1.0
$ docker push localhost:5000/myapp:v1.0
# 从本地 Registry 拉取
## 从本地 Registry 拉取
$ docker pull localhost:5000/myapp:v1.0
```
### 企业级解决方案
#### 企业级解决方案
官方 Registry 功能较为基础企业环境常用以下方案
| 方案 | 特点 |
|------|------|
| **[Harbor](https://goharbor.io/)** | CNCF 项目,功能全面(用户管理、漏洞扫描、镜像签名) |
| **[Nexus Repository](../repository/nexus3_registry.md)** | 支持多种制品类型DockerMavennpm |
| **[Nexus Repository](../repository/6.4_nexus3_registry.md)** | 支持多种制品类型DockerMavennpm |
| **云厂商服务** | 阿里云 ACR腾讯云 TCRAWS ECR |
笔者建议
@@ -151,9 +151,9 @@ $ docker pull localhost:5000/myapp:v1.0
- 中大型团队推荐 Harbor功能完善且开源免费
- 已使用云服务直接用云厂商的 Registry 服务更省心
## 镜像的推送和拉取
### 镜像的推送和拉取
### 完整工作流程
#### 完整工作流程
```
开发者机器 Registry 生产服务器
@@ -171,66 +171,66 @@ $ docker pull localhost:5000/myapp:v1.0
运行容器
```
### 常用命令
#### 常用命令
```bash
# 登录 Registry
## 登录 Registry
$ docker login # 登录 Docker Hub
$ docker login registry.example.com # 登录其他 Registry
# 拉取镜像
## 拉取镜像
$ docker pull nginx:1.25
# 标记镜像准备推送
## 标记镜像准备推送
$ docker tag myapp:latest registry.example.com/myteam/myapp:v1.0
# 推送镜像
## 推送镜像
$ docker push registry.example.com/myteam/myapp:v1.0
# 登出
## 登出
$ docker logout
```
## 镜像的安全性
### 镜像的安全性
### 使用官方镜像
#### 使用官方镜像
Docker Hub [官方镜像](https://hub.docker.com/search?q=&type=image&image_filter=official)(标有 "Official Image" 标识)经过 Docker 团队审核,相对更安全。
```bash
# 官方镜像示例
## 官方镜像示例
nginx # 官方
mysql # 官方
redis # 官方
# 第三方镜像需要自行评估可信度
## 第三方镜像需要自行评估可信度
bitnami/redis # 需要评估
someuser/myapp # 需要评估
```
### 镜像签名
#### 镜像签名
使用 Docker Content Trust (DCT) 验证镜像来源
```bash
# 启用镜像签名验证
## 启用镜像签名验证
$ export DOCKER_CONTENT_TRUST=1
# 此后的 pull/push 会验证签名
## 此后的 pull/push 会验证签名
$ docker pull nginx:latest
```
### 漏洞扫描
#### 漏洞扫描
```bash
# 使用 Docker Scout 扫描镜像漏洞
## 使用 Docker Scout 扫描镜像漏洞
$ docker scout cves nginx:latest
# 使用 Trivy开源工具
## 使用 Trivy开源工具
$ trivy image nginx:latest
```
## 本章小结
### 本章小结
| 概念 | 要点 |
|------|------|
@@ -240,11 +240,11 @@ $ trivy image nginx:latest
| **Docker Hub** | 默认的公共 Registry |
| **私有 Registry** | 企业内部使用推荐 Harbor |
现在你已经了解了 Docker 的三个核心概念[镜像](image.md)[容器](container.md)和仓库接下来让我们开始[安装 Docker](../install/README.md)动手实践
现在你已经了解了 Docker 的三个核心概念[镜像](2.1_image.md)[容器](2.2_container.md)和仓库接下来让我们开始[安装 Docker](../install/README.md)动手实践
## 延伸阅读
### 延伸阅读
- [Docker Hub](../repository/dockerhub.md)Docker Hub 的详细使用
- [私有仓库](../repository/registry.md)搭建私有 Registry
- [私有仓库高级配置](../repository/registry_auth.md)认证TLS 配置
- [镜像加速器](../install/mirror.md)配置镜像加速
- [Docker Hub](../repository/6.1_dockerhub.md)Docker Hub 的详细使用
- [私有仓库](../repository/6.2_registry.md)搭建私有 Registry
- [私有仓库高级配置](../repository/6.3_registry_auth.md)认证TLS 配置
- [镜像加速器](../install/3.9_mirror.md)配置镜像加速

View File

@@ -1,4 +1,4 @@
# 基本概念
# 第二章 基本概念
**Docker** 包括三个基本概念