diff --git a/.zhlintignore b/.zhlintignore new file mode 100644 index 0000000..d2d66a7 --- /dev/null +++ b/.zhlintignore @@ -0,0 +1,3 @@ +node_modules/ +.vuepress/ +.git/ diff --git a/01_introduction/1.2_what.md b/01_introduction/1.2_what.md index 3b22e07..e3d4233 100644 --- a/01_introduction/1.2_what.md +++ b/01_introduction/1.2_what.md @@ -60,6 +60,8 @@ flowchart LR #### 关键区别 +相关信息如下表: + | 特性 | Docker 容器 | 传统虚拟机 | |------|-------------|------------| | **启动速度** | 秒级 | 分钟级 | diff --git a/01_introduction/1.3_why.md b/01_introduction/1.3_why.md index 7decc08..c7c94e2 100644 --- a/01_introduction/1.3_why.md +++ b/01_introduction/1.3_why.md @@ -19,6 +19,7 @@ ``` 笔者统计过,这个问题通常由以下原因导致: + - Python/Node/Java 版本不一致 - 依赖库版本不一致 - 操作系统配置不一致 @@ -109,6 +110,7 @@ $ docker compose up | 完整 Web 应用 | ~120 秒 | ~5 秒 | 这个差异对以下场景尤为重要: + - **CI/CD 流水线**:每次构建节省几分钟,一天累积下来就是几小时 - **弹性扩容**:流量高峰时能快速启动更多实例 - **开发体验**:快速重启服务进行调试 @@ -156,6 +158,7 @@ flowchart LR ``` 使用 [Dockerfile](../04_image/4.5_build.md) 定义镜像构建过程,使得: + - 构建过程**可重复、可追溯** - 任何人都能从代码重建完全相同的镜像 - 配合 [GitHub Actions](../15_cases/ci/actions/README.md) 等 CI 系统实现自动化 @@ -163,6 +166,7 @@ flowchart LR #### 5。轻松迁移 Docker 可以在几乎任何平台上运行: + - ✅ 本地开发机 (macOS、Windows、Linux) - ✅ 公有云 (AWS、Azure、GCP、阿里云、腾讯云) - ✅ 私有云和自建数据中心 @@ -222,6 +226,8 @@ Docker 主要面向服务端应用。桌面 GUI 应用的容器化虽然可行 ### 与传统虚拟机的对比总结 +相关信息如下表: + | 特性 | Docker 容器 | 传统虚拟机 | |:------|:-----------|:-----------| | 启动速度 | 秒级 | 分钟级 | diff --git a/02_basic_concept/2.1_image.md b/02_basic_concept/2.1_image.md index 887b6f8..ef79cca 100644 --- a/02_basic_concept/2.1_image.md +++ b/02_basic_concept/2.1_image.md @@ -103,6 +103,7 @@ flowchart TD ``` 每一层的特点: + - **只读**:构建完成后不可修改 - **可共享**:多个镜像可以共享相同的层 - **有缓存**:未变化的层不会重新构建 @@ -209,5 +210,5 @@ Docker 镜像可以通过以下方式获取: |------|------|------| | **从 Registry 拉取** | 最常用的方式 | `docker pull nginx` | | **从 Dockerfile 构建** | 自定义镜像 | `docker build -t myapp .` | -| **从容器提交** | 保存容器状态(不推荐) | `docker commit` | +| **从容器提交** | 保存容器状态 (不推荐)| `docker commit` | | **从文件导入** | 离线传输 | `docker load < image.tar` | diff --git a/02_basic_concept/2.2_container.md b/02_basic_concept/2.2_container.md index 67de7cb..4f97259 100644 --- a/02_basic_concept/2.2_container.md +++ b/02_basic_concept/2.2_container.md @@ -66,8 +66,8 @@ flowchart TD | 特性 | 容器 | 虚拟机 | |------|------|--------| -| **隔离级别** | 进程级(Namespace) | 硬件级(Hypervisor) | -| **启动时间** | 秒级(甚至毫秒) | 分钟级 | +| **隔离级别** | 进程级 (Namespace)| 硬件级 (Hypervisor)| +| **启动时间** | 秒级 (甚至毫秒)| 分钟级 | | **资源占用** | MB 级别 | GB 级别 | | **性能损耗** | 几乎为零 | 5-20% | | **内核** | 共享宿主机内核 | 各自独立内核 | @@ -129,8 +129,8 @@ $ docker rm abc123 | 方式 | 说明 | 适用场景 | |------|------|---------| -| **[数据卷(Volume)](../08_data_network/data/volume.md)** | Docker 管理的存储 | 数据库、应用数据 | -| **[绑定挂载(Bind Mount)](../08_data_network/data/bind-mounts.md)** | 挂载宿主机目录 | 开发时共享代码 | +| **[数据卷 (Volume) ](../08_data_network/data/volume.md)** | Docker 管理的存储 | 数据库、应用数据 | +| **[绑定挂载 (Bind Mount) ](../08_data_network/data/bind-mounts.md)** | 挂载宿主机目录 | 开发时共享代码 | ```bash ## 使用数据卷(推荐) diff --git a/02_basic_concept/2.3_repository.md b/02_basic_concept/2.3_repository.md index 63a354a..0b575cb 100644 --- a/02_basic_concept/2.3_repository.md +++ b/02_basic_concept/2.3_repository.md @@ -48,8 +48,8 @@ flowchart TB | 概念 | 说明 | 示例 | |------|------|------| | **Registry** | 存储镜像的服务 | Docker Hub、ghcr.io | -| **Repository(仓库)** | 同一软件的镜像集合 | `nginx`、`mysql`、`mycompany/myapp` | -| **Tag(标签)** | 仓库内的版本标识 | `latest`、`1.25`、`alpine` | +| **Repository (仓库) ** | 同一软件的镜像集合 | `nginx`、`mysql`、`mycompany/myapp` | +| **Tag (标签) ** | 仓库内的版本标识 | `latest`、`1.25`、`alpine` | #### 镜像的完整名称 @@ -172,8 +172,8 @@ $ docker pull localhost:5000/myapp:v1.0 | 方案 | 特点 | |------|------| -| **[Harbor](https://goharbor.io/)** | CNCF 项目,功能全面(用户管理、漏洞扫描、镜像签名) | -| **[Nexus Repository](../06_repository/6.4_nexus3_registry.md)** | 支持多种制品类型(Docker、Maven、npm 等) | +| **[Harbor](https://goharbor.io/)** | CNCF 项目,功能全面 (用户管理、漏洞扫描、镜像签名)| +| **[Nexus Repository](../06_repository/6.4_nexus3_registry.md)** | 支持多种制品类型 (Docker、Maven、npm 等)| | **云厂商服务** | 阿里云 ACR、腾讯云 TCR、AWS ECR 等 | 笔者建议: diff --git a/02_basic_concept/summary.md b/02_basic_concept/summary.md index be87c8d..19897e2 100644 --- a/02_basic_concept/summary.md +++ b/02_basic_concept/summary.md @@ -1,5 +1,7 @@ ## 本章小结 +相关信息如下表: + | 概念 | 要点 | |------|------| | **镜像是什么** | 只读的应用模板,包含运行所需的一切 | @@ -22,7 +24,7 @@ | **容器 vs 虚拟机** | 共享内核,更轻量,但隔离性较弱 | | **存储层** | 可写层随容器删除而消失 | | **数据持久化** | 使用 Volume 或 Bind Mount | -| **生命周期** | 与主进程(PID 1)绑定 | +| **生命周期** | 与主进程 (PID 1) 绑定 | 理解了镜像和容器,接下来让我们学习[仓库](2.3_repository.md)——存储和分发镜像的服务。 @@ -36,8 +38,8 @@ | 概念 | 要点 | |------|------| | **Registry** | 存储和分发镜像的服务 | -| **仓库(Repository)** | 同一软件的镜像集合 | -| **标签(Tag)** | 版本标识,默认为 latest | +| **仓库 (Repository) ** | 同一软件的镜像集合 | +| **标签 (Tag) ** | 版本标识,默认为 latest | | **Docker Hub** | 默认的公共 Registry | | **私有 Registry** | 企业内部使用,推荐 Harbor | diff --git a/03_install/_images/image-20200412202617411.png b/03_install/_images/image-20200412202617411.png deleted file mode 100644 index fb5caf2..0000000 Binary files a/03_install/_images/image-20200412202617411.png and /dev/null differ diff --git a/03_install/_images/install-mac-apps.png b/03_install/_images/install-mac-apps.png deleted file mode 100644 index 206ecd1..0000000 Binary files a/03_install/_images/install-mac-apps.png and /dev/null differ diff --git a/03_install/_images/install-mac-dmg.png b/03_install/_images/install-mac-dmg.png deleted file mode 100644 index 5c251db..0000000 Binary files a/03_install/_images/install-mac-dmg.png and /dev/null differ diff --git a/03_install/_images/install-mac-example-nginx.png b/03_install/_images/install-mac-example-nginx.png deleted file mode 100644 index 586293f..0000000 Binary files a/03_install/_images/install-mac-example-nginx.png and /dev/null differ diff --git a/03_install/_images/install-mac-menu.png b/03_install/_images/install-mac-menu.png deleted file mode 100644 index b330f08..0000000 Binary files a/03_install/_images/install-mac-menu.png and /dev/null differ diff --git a/03_install/_images/install-mac-menubar.png b/03_install/_images/install-mac-menubar.png deleted file mode 100644 index c883009..0000000 Binary files a/03_install/_images/install-mac-menubar.png and /dev/null differ diff --git a/03_install/_images/install-win-docker-app-search.png b/03_install/_images/install-win-docker-app-search.png deleted file mode 100644 index 42361f6..0000000 Binary files a/03_install/_images/install-win-docker-app-search.png and /dev/null differ diff --git a/03_install/_images/install-win-taskbar-circle.png b/03_install/_images/install-win-taskbar-circle.png deleted file mode 100644 index d4c6cc5..0000000 Binary files a/03_install/_images/install-win-taskbar-circle.png and /dev/null differ diff --git a/04_image/4.1_pull.md b/04_image/4.1_pull.md index 80c300e..9738c7a 100644 --- a/04_image/4.1_pull.md +++ b/04_image/4.1_pull.md @@ -24,8 +24,8 @@ Registry地址 用户名 仓库名 标签 | 组成部分 | 说明 | 默认值 | |---------|------|--------| -| Registry 地址 | 镜像仓库地址 | `docker.io`(Docker Hub) | -| 用户名 | 镜像所属用户/组织 | `library`(官方镜像) | +| Registry 地址 | 镜像仓库地址 | `docker.io` (Docker Hub)| +| 用户名 | 镜像所属用户/组织 | `library` (官方镜像)| | 仓库名 | 镜像名称 | 必须指定 | | 标签 | 版本标识 | `latest` | @@ -80,10 +80,12 @@ docker.io/library/ubuntu:24.04 #### 输出解读 +相关信息如下表: + | 输出内容 | 说明 | |---------|------| | `Pulling from library/ubuntu` | 正在从官方 ubuntu 仓库拉取 | -| `92dc2a97ff99: Pull complete` | 各层的下载状态(显示层 ID 前 12 位) | +| `92dc2a97ff99: Pull complete` | 各层的下载状态 (显示层 ID 前 12 位)| | `Digest: sha256:...` | 镜像内容的唯一摘要 | | `docker.io/library/ubuntu:24.04` | 镜像的完整名称 | @@ -233,6 +235,7 @@ Error: pull access denied, repository does not exist ``` 可能原因: + - 镜像名拼写错误 - 私有镜像未登录 (需要 `docker login`) - 镜像确实不存在 diff --git a/04_image/4.2_list.md b/04_image/4.2_list.md index 5ec3c97..dea00b2 100644 --- a/04_image/4.2_list.md +++ b/04_image/4.2_list.md @@ -26,8 +26,8 @@ ubuntu noble 329ed837d508 3 days ago 78MB | 字段 | 说明 | |------|------| | **REPOSITORY** | 仓库名 | -| **TAG** | 标签(版本) | -| **IMAGE ID** | 镜像唯一标识(短 ID,前 12 位) | +| **TAG** | 标签 (版本)| +| **IMAGE ID** | 镜像唯一标识 (短 ID,前 12 位)| | **CREATED** | 创建时间 | | **SIZE** | 本地占用空间 | @@ -47,6 +47,8 @@ Docker 镜像的大小可能与我们通常理解的文件大小有所不同, #### 本地大小 vs Hub 显示大小 +相关信息如下表: + | 位置 | 显示大小 | 说明 | |------|---------|------| | Docker Hub | 29MB | 压缩后的网络传输大小 | @@ -111,6 +113,8 @@ ubuntu 24.04 329ed837d508 78MB #### 使用过滤器 --filter +相关信息如下表: + | 过滤条件 | 说明 | 示例 | |---------|------|------| | `dangling=true` | 虚悬镜像 | `-f dangling=true` | @@ -260,6 +264,8 @@ ubuntu 24.04 78MB #### 可用模板字段 +相关信息如下表: + | 字段 | 说明 | |------|------| | `.ID` | 镜像 ID | diff --git a/04_image/4.3_rm.md b/04_image/4.3_rm.md index 2477908..4c7a2ec 100644 --- a/04_image/4.3_rm.md +++ b/04_image/4.3_rm.md @@ -20,7 +20,7 @@ $ docker image rm [选项] <镜像1> [<镜像2> ...] | 方式 | 说明 | 示例 | |------|------|------| -| **短 ID** | ID 的前几位(通常 3-4 位) | `docker rmi 501` | +| **短 ID** | ID 的前几位 (通常 3-4 位)| `docker rmi 501` | | **长 ID** | 完整的镜像 ID | `docker rmi 501ad78535f0...` | | **镜像名:标签** | 仓库名和标签 | `docker rmi redis:alpine` | | **镜像摘要** | 精确的内容摘要 | `docker rmi nginx@sha256:...` | @@ -87,6 +87,8 @@ Deleted: sha256:32770d1dcf835f192cafd6b9263b7b597a1778a403a109e2cc2ee866f74adf23 #### Untagged vs Deleted +相关信息如下表: + | 操作 | 含义 | |------|------| | **Untagged** | 移除镜像的标签 | @@ -236,6 +238,8 @@ Error: image has dependent child images ### 常用过滤条件 +相关信息如下表: + | 过滤条件 | 说明 | 示例 | |---------|------|------| | `dangling=true` | 虚悬镜像 | `-f dangling=true` | diff --git a/04_image/_images/images-create-nginx-docker.png b/04_image/_images/images-create-nginx-docker.png deleted file mode 100644 index 4da40d1..0000000 Binary files a/04_image/_images/images-create-nginx-docker.png and /dev/null differ diff --git a/04_image/_images/images-mac-example-nginx.png b/04_image/_images/images-mac-example-nginx.png deleted file mode 100644 index 586293f..0000000 Binary files a/04_image/_images/images-mac-example-nginx.png and /dev/null differ diff --git a/04_image/summary.md b/04_image/summary.md index d6e2c29..7291ee9 100644 --- a/04_image/summary.md +++ b/04_image/summary.md @@ -1,5 +1,7 @@ ## 本章小结 +相关信息如下表: + | 操作 | 命令 | |------|------| | 拉取镜像 | `docker pull 镜像名:标签` | diff --git a/05_container/5.1_run.md b/05_container/5.1_run.md index 9921ab5..1412038 100644 --- a/05_container/5.1_run.md +++ b/05_container/5.1_run.md @@ -5,6 +5,7 @@ ### 启动方式概述 启动容器有两种方式: + - **新建并启动**:基于镜像创建新容器 - **重新启动**:将已终止的容器重新运行 @@ -46,8 +47,8 @@ root@af8bae53bdd3:/# | 参数 | 作用 | |------|------| -| `-i` | 保持标准输入(stdin)打开,允许输入 | -| `-t` | 分配伪终端(pseudo-TTY),提供终端界面 | +| `-i` | 保持标准输入 (stdin) 打开,允许输入 | +| `-t` | 分配伪终端 (pseudo-TTY),提供终端界面 | | `-it` | 两者组合使用,获得交互式终端 | 在交互模式下可以执行命令: @@ -87,9 +88,11 @@ flowchart TD #### 基础选项 +相关信息如下表: + | 选项 | 说明 | 示例 | |------|------|------| -| `-d` | 后台运行(detach) | `docker run -d nginx` | +| `-d` | 后台运行 (detach)| `docker run -d nginx` | | `-it` | 交互式终端 | `docker run -it ubuntu bash` | | `--name` | 指定容器名称 | `docker run --name myapp nginx` | | `--rm` | 退出后自动删除容器 | `docker run --rm ubuntu echo hi` | diff --git a/05_container/5.2_daemon.md b/05_container/5.2_daemon.md index b6402c3..42fc04e 100644 --- a/05_container/5.2_daemon.md +++ b/05_container/5.2_daemon.md @@ -28,6 +28,7 @@ hello world ``` 容器会把输出的结果 (STDOUT) 打印到宿主机上面。此时: + - 终端被占用,无法执行其他命令 - 按 `Ctrl+C` 会终止容器 - 关闭终端窗口,容器也会停止 @@ -42,6 +43,7 @@ $ docker run -d ubuntu:24.04 /bin/sh -c "while true; do echo hello world; sleep ``` 使用 `-d` 参数后: + - 容器在后台运行 - 返回容器的完整 ID - 终端立即释放,可以继续执行其他命令 @@ -73,6 +75,7 @@ flowchart TD ``` 当你运行 `docker run -d ubuntu:24.04` 时: + 1. 容器启动 2. 没有指定命令,默认执行 `/bin/bash` 3. 但没有交互式终端 (没有 `-it` 参数),bash 发现没有输入源 @@ -80,11 +83,14 @@ flowchart TD 5. 主进程退出,容器停止 **关键理解**: + - ❌ `-d` 参数**不是**让容器 “一直运行” - ✅ `-d` 参数是让容器 “在后台运行”,能运行多久取决于主进程 #### 常见的 “立即退出” 场景 +相关信息如下表: + | 场景 | 原因 | 解决方案 | |------|------|---------| | `docker run -d ubuntu` | 默认 bash 无输入立即退出 | 指定长期运行的命令 | diff --git a/05_container/5.3_stop.md b/05_container/5.3_stop.md index a221e8e..34a1a93 100644 --- a/05_container/5.3_stop.md +++ b/05_container/5.3_stop.md @@ -81,6 +81,8 @@ $ docker kill 容器名或ID #### 与 stop 的区别 +相关信息如下表: + | 命令 | 信号 | 使用场景 | |------|------|---------| | `docker stop` | SIGTERM → SIGKILL | 正常停止,让应用优雅退出 | @@ -135,10 +137,10 @@ c5d3a5e8f7b2 nginx "nginx" Up 5 minutes mynginx | 状态 | 说明 | |------|------| | `Up X minutes` | 运行中 | -| `Exited (0)` | 正常退出(退出码 0) | -| `Exited (1)` | 异常退出(非零退出码) | -| `Exited (137)` | 被 SIGKILL 终止(128 + 9) | -| `Exited (143)` | 被 SIGTERM 终止(128 + 15) | +| `Exited (0)` | 正常退出 (退出码 0)| +| `Exited (1)` | 异常退出 (非零退出码)| +| `Exited (137)` | 被 SIGKILL 终止 (128 + 9)| +| `Exited (143)` | 被 SIGTERM 终止 (128 + 15)| --- @@ -235,6 +237,7 @@ $ docker stop $(docker ps -q) && docker container prune -f 原因:应用没有正确处理 SIGTERM 信号,需要等待超时后强制终止。 解决方案: + 1. 在应用中正确处理 SIGTERM 2. 使用 `docker stop -t 0` 立即终止 3. 检查 Dockerfile 中的 `STOPSIGNAL` 配置 diff --git a/05_container/5.4_attach_exec.md b/05_container/5.4_attach_exec.md index 1683913..246ccb8 100644 --- a/05_container/5.4_attach_exec.md +++ b/05_container/5.4_attach_exec.md @@ -44,12 +44,14 @@ $ docker exec -it 容器名 /bin/sh #### 参数说明 +相关信息如下表: + | 参数 | 作用 | |------|------| -| `-i` | 保持标准输入打开(interactive) | -| `-t` | 分配伪终端(TTY) | +| `-i` | 保持标准输入打开 (interactive)| +| `-t` | 分配伪终端 (TTY)| | `-it` | 两者组合,获得完整交互体验 | -| `-u` | 指定用户(如 `-u root`) | +| `-u` | 指定用户 (如 `-u root`)| | `-w` | 指定工作目录 | | `-e` | 设置环境变量 | @@ -197,6 +199,8 @@ CONTAINER ID IMAGE STATUS NAMES ### exec vs attach 对比 +相关信息如下表: + | 特性 | docker exec | docker attach | |------|-------------|---------------| | **工作方式** | 在容器内启动新进程 | 附加到主进程 | @@ -257,6 +261,7 @@ $ docker exec myapp python manage.py migrate #### 2。生产环境避免进入容器 笔者建议:生产环境应尽量避免进入容器直接操作,而是通过: + - 日志系统查看日志 (如 `docker logs` 或集中式日志) - 监控系统查看状态 - 重新部署而非手动修改 diff --git a/05_container/5.6_rm.md b/05_container/5.6_rm.md index f56965f..9374b6f 100644 --- a/05_container/5.6_rm.md +++ b/05_container/5.6_rm.md @@ -16,6 +16,8 @@ $ docker rm 容器名或ID ### 删除选项 +相关信息如下表: + | 选项 | 说明 | 示例 | |------|------|------| | 无参数 | 删除已停止的容器 | `docker rm mycontainer` | @@ -258,6 +260,7 @@ $ docker rm -f mycontainer #### Q:删除后磁盘空间没释放 可能原因: + 1. 容器的数据卷未删除 (使用 `-v` 参数) 2. 镜像未删除 3. 构建缓存未清理 diff --git a/05_container/summary.md b/05_container/summary.md index 28b9148..86cc5b8 100644 --- a/05_container/summary.md +++ b/05_container/summary.md @@ -1,5 +1,7 @@ ## 本章小结 +相关信息如下表: + | 操作 | 命令 | 说明 | |------|------|------| | 新建并运行 | `docker run` | 最常用的启动方式 | @@ -32,7 +34,7 @@ |------|---------| | 进入容器调试 | `docker exec -it 容器名 bash` | | 执行单条命令 | `docker exec 容器名 命令` | -| 查看主进程输出 | `docker attach 容器名`(慎用) | +| 查看主进程输出 | `docker attach 容器名` (慎用)| ### 延伸阅读 diff --git a/06_repository/6.1_dockerhub.md b/06_repository/6.1_dockerhub.md index b0f9714..51ff191 100644 --- a/06_repository/6.1_dockerhub.md +++ b/06_repository/6.1_dockerhub.md @@ -10,6 +10,7 @@ Docker Hub 是 Docker 的中央镜像仓库,通过它您可以轻松地分享 [Docker Hub](https://hub.docker.com/) 是 Docker 官方维护的公共镜像仓库,也是全球最大的容器镜像库。 它提供了: + - **官方镜像**:由 Docker 官方和软件厂商 (如 Nginx,MySQL,Node.js) 维护的高质量镜像。 - **个人/组织仓库**:用户可以上传自己的镜像。 - **自动构建**:与 GitHub/Bitbucket 集成 (需付费)。 @@ -108,6 +109,7 @@ $ docker push username/myapp:v1 #### 2。使用 Access Token 不要在脚本或 CI/CD 中直接使用登录密码。 + 1. 在 Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token。 2. 使用 Token 作为密码登录: diff --git a/06_repository/summary.md b/06_repository/summary.md index fa1abf7..e317a23 100644 --- a/06_repository/summary.md +++ b/06_repository/summary.md @@ -1,5 +1,7 @@ ## 本章小结 +相关信息如下表: + | 功能 | 说明 | |------|------| | **官方镜像** | 优先使用的基础镜像 | diff --git a/07_dockerfile/7.10_workdir.md b/07_dockerfile/7.10_workdir.md index 9bcf9fc..8e3d765 100644 --- a/07_dockerfile/7.10_workdir.md +++ b/07_dockerfile/7.10_workdir.md @@ -188,6 +188,8 @@ WORKDIR /data ### 与其他指令的关系 +相关信息如下表: + | 指令 | WORKDIR 的影响 | |------|---------------| | `RUN` | 在 WORKDIR 中执行命令 | diff --git a/07_dockerfile/7.11_user.md b/07_dockerfile/7.11_user.md index 98e92c2..c9d3701 100644 --- a/07_dockerfile/7.11_user.md +++ b/07_dockerfile/7.11_user.md @@ -165,6 +165,8 @@ exec gosu redis "$@" #### 为什么不用 su/sudo +相关信息如下表: + | 问题 | su/sudo | gosu | |------|---------|------| | TTY 要求 | 需要 | 不需要 | @@ -298,6 +300,7 @@ RUN mkdir -p /app/data && chown appuser:appuser /app/data 非 root 用户无法绑定 80、443 等端口。 **解决**: + 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 66d8c69..757a66e 100644 --- a/07_dockerfile/7.12_healthcheck.md +++ b/07_dockerfile/7.12_healthcheck.md @@ -18,6 +18,7 @@ HEALTHCHECK NONE ### 为什么需要 HEALTHCHECK 在没有 HEALTHCHECK 之前,Docker 只能通过**进程退出码**来判断容器状态。**问题场景**: + - Web 服务死锁,无法响应请求,但进程仍在运行 - 数据库正在启动中,尚未准备好接受连接 - 应用陷入死循环,CPU 爆满但进程存活 @@ -58,11 +59,13 @@ HEALTHCHECK --interval=30s --timeout=3s --retries=3 \ #### 常用选项 +相关信息如下表: + | 选项 | 说明 | 默认值 | |------|------|--------| | `--interval` | 两次检查的间隔 | 30s | | `--timeout` | 检查命令的超时时间 | 30s | -| `--start-period` | 启动缓冲期(期间失败不计入次数) | 0s | +| `--start-period` | 启动缓冲期 (期间失败不计入次数)| 0s | | `--retries` | 连续失败多少次标记为 unhealthy | 3 | --- diff --git a/07_dockerfile/7.13_onbuild.md b/07_dockerfile/7.13_onbuild.md index 0eb49ec..84ff252 100644 --- a/07_dockerfile/7.13_onbuild.md +++ b/07_dockerfile/7.13_onbuild.md @@ -21,6 +21,7 @@ ONBUILD <其它指令> #### 场景:维护 Node.js 项目 假设你有多个 Node.js 项目,它们的构建流程都一样: + 1. 创建目录 2. 复制 `package.json` 3. 执行 `npm install` @@ -119,6 +120,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/ #### 1。继承性限制 `ONBUILD` 指令**只会继承一次**。 + - 镜像 A (含 ONBUILD) - 镜像 B (FROM A) -> 触发 ONBUILD - 镜像 C (FROM B) -> **不会**再次触发 ONBUILD diff --git a/07_dockerfile/7.15_shell.md b/07_dockerfile/7.15_shell.md index 1cba226..e3d6fa7 100644 --- a/07_dockerfile/7.15_shell.md +++ b/07_dockerfile/7.15_shell.md @@ -11,6 +11,7 @@ SHELL ["executable", "parameters"] ``` `SHELL` 指令允许覆盖 Docker 默认的 shell。 + - **Linux 默认**:`["/bin/sh", "-c"]` - **Windows 默认**:`["cmd", "/S", "/C"]` diff --git a/07_dockerfile/7.1_run.md b/07_dockerfile/7.1_run.md index 6ceaa14..bc3bb0a 100644 --- a/07_dockerfile/7.1_run.md +++ b/07_dockerfile/7.1_run.md @@ -81,6 +81,7 @@ RUN apt-get update && \ RUN apt-get update && apt-get install -y package-bar \ && rm -rf /var/lib/apt/lists/* ``` + - **Alpine**: ```docker RUN apk add --no-cache package-bar diff --git a/07_dockerfile/7.2_copy.md b/07_dockerfile/7.2_copy.md index 2caaa9a..392dd86 100644 --- a/07_dockerfile/7.2_copy.md +++ b/07_dockerfile/7.2_copy.md @@ -147,6 +147,7 @@ COPY --chown=node . /app/ ### 保留文件元数据 COPY 会保留源文件的元数据: + - 读、写、执行权限 - 修改时间 @@ -162,11 +163,13 @@ COPY start.sh /app/ ### COPY vs ADD +相关信息如下表: + | 特性 | COPY | ADD | |------|------|-----| | 复制本地文件 | ✅ | ✅ | | 自动解压 tar | ❌ | ✅ | -| 支持 URL | ❌ | ✅(不推荐) | +| 支持 URL | ❌ | ✅ (不推荐)| | 推荐程度 | ✅ **推荐** | ⚠️ 特殊场景使用 | ```docker @@ -219,6 +222,7 @@ COPY --link --from=builder /app/dist /usr/share/nginx/html ``` `--link` 的优势: + - 更高效利用构建缓存 - 并行化构建过程 - 加速多阶段构建 @@ -241,6 +245,7 @@ Dockerfile ``` 这可以: + - 减小构建上下文大小 - 加速构建 - 避免复制敏感文件 diff --git a/07_dockerfile/7.3_add.md b/07_dockerfile/7.3_add.md index b1fc15a..b10c2ca 100644 --- a/07_dockerfile/7.3_add.md +++ b/07_dockerfile/7.3_add.md @@ -12,6 +12,7 @@ ADD [选项] ["<源路径>", ... "<目标路径>"] ``` `ADD` 在 `COPY` 基础上增加了两个功能: + 1. 自动解压 tar 压缩包 2. 支持从 URL 下载文件 (不推荐) @@ -19,11 +20,13 @@ ADD [选项] ["<源路径>", ... "<目标路径>"] ### ADD vs COPY +相关信息如下表: + | 特性 | COPY | ADD | |------|------|-----| | 复制本地文件 | ✅ | ✅ | | 自动解压 tar | ❌ | ✅ | -| 支持 URL | ❌ | ✅(不推荐) | +| 支持 URL | ❌ | ✅ (不推荐)| | 行为可预测性 | ✅ 高 | ⚠️ 低 | | 推荐程度 | ✅ **优先使用** | 仅解压场景 | @@ -46,6 +49,7 @@ ADD app.tar.gz /app/ ``` ADD 会识别并解压以下格式: + - `.tar` - `.tar.gz` / `.tgz` - `.tar.bz2` / `.tbz2` @@ -95,6 +99,8 @@ ADD https://example.com/app.zip /app/app.zip #### 为什么不推荐 +相关信息如下表: + | 问题 | 说明 | |------|------| | 权限固定 | 下载的文件权限为 600,通常需要额外 RUN 修改 | @@ -118,6 +124,7 @@ RUN curl -fsSL https://example.com/app.tar.gz | tar -xz -C /app ``` 优势: + - 一条 RUN 完成下载、解压、清理 - 减少镜像层数 - 更清晰的构建意图 diff --git a/07_dockerfile/7.4_cmd.md b/07_dockerfile/7.4_cmd.md index be432f1..41e0cc5 100644 --- a/07_dockerfile/7.4_cmd.md +++ b/07_dockerfile/7.4_cmd.md @@ -31,6 +31,7 @@ CMD ["node", "server.js"] ``` **优点**: + - 直接执行指定程序,是容器的 PID 1 - 正确接收信号 (如 SIGTERM) - 无需 shell 解析 @@ -62,6 +63,8 @@ CMD ["sh", "-c", "echo $HOME"] ### exec 格式 vs shell 格式 +相关信息如下表: + | 特性 | exec 格式 | shell 格式 | |------|----------|-----------| | 主进程 | 指定的程序 | `/bin/sh` | @@ -163,6 +166,8 @@ CMD ["nginx", "-g", "daemon off;"] ### CMD vs ENTRYPOINT +相关信息如下表: + | 指令 | 用途 | 运行时行为 | |------|------|-----------| | **CMD**| 默认命令 | `docker run` 参数会**覆盖**它 | diff --git a/07_dockerfile/7.5_entrypoint.md b/07_dockerfile/7.5_entrypoint.md index c818054..2cf3979 100644 --- a/07_dockerfile/7.5_entrypoint.md +++ b/07_dockerfile/7.5_entrypoint.md @@ -12,6 +12,8 @@ ### 语法格式 +相关信息如下表: + | 格式 | 语法 | 推荐程度 | |------|------|---------| | **exec 格式**| `ENTRYPOINT ["可执行文件", "参数1"]` | ✅**推荐** | @@ -35,6 +37,8 @@ ENTRYPOINT nginx -g "daemon off;" #### 核心区别 +相关信息如下表: + | 特性 | ENTRYPOINT | CMD | |------|------------|-----| | **定位** | 固定的入口程序 | 默认参数 | @@ -272,13 +276,15 @@ $ docker run --entrypoint /bin/cat myimage /etc/os-release ### ENTRYPOINT 与 CMD 组合表 +相关信息如下表: + | ENTRYPOINT | CMD | 最终执行命令 | |------------|-----|-------------| -| 无 | 无 | 无(容器无法启动) | +| 无 | 无 | 无 (容器无法启动)| | 无 | `["cmd", "p1"]` | `cmd p1` | | `["ep", "p1"]` | 无 | `ep p1` | | `["ep", "p1"]` | `["cmd", "p2"]` | `ep p1 cmd p2` | -| `ep p1`(shell) | `["cmd", "p2"]` | `/bin/sh -c "ep p1"`(CMD 被忽略) | +| `ep p1` (shell)| `["cmd", "p2"]` | `/bin/sh -c "ep p1"` (CMD 被忽略)| > ⚠️ **注意**:shell 格式的 ENTRYPOINT 会忽略 CMD! diff --git a/07_dockerfile/7.6_env.md b/07_dockerfile/7.6_env.md index 8bcfc27..5fa75f6 100644 --- a/07_dockerfile/7.6_env.md +++ b/07_dockerfile/7.6_env.md @@ -150,12 +150,14 @@ DATABASE_URL=postgres://localhost/mydb ### ENV vs ARG +相关信息如下表: + | 特性 | ENV | ARG | |------|-----|-----| | **生效时间** | 构建时 + 运行时 | 仅构建时 | | **持久性** | 写入镜像,运行时可用 | 构建后消失 | | **覆盖方式** | `docker run -e` | `docker build --build-arg` | -| **适用场景** | 应用配置 | 构建参数(如版本号) | +| **适用场景** | 应用配置 | 构建参数 (如版本号)| #### 概述 diff --git a/07_dockerfile/7.7_arg.md b/07_dockerfile/7.7_arg.md index cdfd342..b7781b5 100644 --- a/07_dockerfile/7.7_arg.md +++ b/07_dockerfile/7.7_arg.md @@ -16,12 +16,14 @@ ARG <参数名>[=<默认值>] ### ARG vs ENV +相关信息如下表: + | 特性 | ARG | ENV | |------|-----|-----| | **生效时间** | 仅构建时 | 构建时 + 运行时 | | **持久性** | 构建后消失 | 写入镜像 | | **覆盖方式** | `docker build --build-arg` | `docker run -e` | -| **适用场景** | 构建参数(版本号等) | 应用配置 | +| **适用场景** | 构建参数 (版本号等)| 应用配置 | | **可见性** | `docker history` 可见 | `docker inspect` 可见 | ``` diff --git a/07_dockerfile/7.8_volume.md b/07_dockerfile/7.8_volume.md index 49b7049..b780115 100644 --- a/07_dockerfile/7.8_volume.md +++ b/07_dockerfile/7.8_volume.md @@ -197,11 +197,13 @@ $ docker inspect mycontainer --format '{{json .Mounts}}' | jq ### VOLUME vs docker run -v +相关信息如下表: + | 特性 | Dockerfile VOLUME | docker run -v | |------|-------------------|---------------| | **定义时机** | 镜像构建时 | 容器运行时 | | **默认行为** | 创建匿名卷 | 可指定命名卷或路径 | -| **灵活性** | 低(固定路径) | 高(可任意指定) | +| **灵活性** | 低 (固定路径)| 高 (可任意指定)| | **适用场景** | 定义必须持久化的路径 | 灵活的数据管理 | --- diff --git a/07_dockerfile/7.9_expose.md b/07_dockerfile/7.9_expose.md index 9fcbc88..a9df04a 100644 --- a/07_dockerfile/7.9_expose.md +++ b/07_dockerfile/7.9_expose.md @@ -76,11 +76,13 @@ $ docker port $(docker ps -q) ### EXPOSE vs -p +相关信息如下表: + | 特性 | EXPOSE | -p | |------|--------|-----| | **位置** | Dockerfile | docker run 命令 | | **作用** | 声明/文档 | 实际端口映射 | -| **是否必需** | 否 | 是(外部访问时) | +| **是否必需** | 否 | 是 (外部访问时)| | **映射发生时** | 不发生 | 运行时发生 | ```mermaid @@ -130,6 +132,7 @@ EXPOSE 80 ``` EXPOSE 不会: + - 自动进行端口映射 - 让服务可从外部访问 - 在容器启动时开启端口监听 diff --git a/07_dockerfile/summary.md b/07_dockerfile/summary.md index 26593ee..428bec2 100644 --- a/07_dockerfile/summary.md +++ b/07_dockerfile/summary.md @@ -1,12 +1,14 @@ ## 本章小结 +相关信息如下表: + | 要点 | 说明 | |------|------| | **作用** | 设置后续指令的工作目录 | | **语法** | `WORKDIR /path` | | **自动创建** | 目录不存在会自动创建 | | **持久性** | 影响后续所有指令,直到下次 WORKDIR | -| **不要用** | `RUN cd /path`(无效) | +| **不要用** | `RUN cd /path` (无效)| ### 延伸阅读 @@ -46,7 +48,7 @@ |------|------| | **作用** | 定义在子镜像构建时执行的指令 | | **语法** | `ONBUILD INSTRUCTION` | -| **适用** | 基础架构镜像(Node, Python, Go 等) | +| **适用** | 基础架构镜像 (Node, Python, Go 等)| | **限制** | 只继承一次,不可级联 | | **规范** | 建议使用 `-onbuild` 标签后缀 | @@ -195,7 +197,7 @@ | 要点 | 说明 | |------|------| -| **作用** | 声明容器提供服务的端口(文档) | +| **作用** | 声明容器提供服务的端口 (文档)| | **不会** | 自动映射端口或开放外部访问 | | **配合** | `docker run -P` 自动映射 | | **外部访问** | 需要 `-p 宿主机端口:容器端口` | diff --git a/08_data_network/data/bind-mounts.md b/08_data_network/data/bind-mounts.md index f0867a1..59d9005 100644 --- a/08_data_network/data/bind-mounts.md +++ b/08_data_network/data/bind-mounts.md @@ -25,11 +25,13 @@ flowchart LR ### Bind Mount vs Volume +相关信息如下表: + | 特性 | Bind Mount | Volume | |------|------------|--------| | **数据位置** | 宿主机任意路径 | Docker 管理的目录 | | **路径指定** | 必须是绝对路径 | 卷名 | -| **可移植性** | 依赖宿主机路径 | 更好(Docker 管理) | +| **可移植性** | 依赖宿主机路径 | 更好 (Docker 管理)| | **性能** | 依赖宿主机文件系统 | 优化的存储驱动 | | **适用场景** | 开发环境、配置文件 | 生产数据持久化 | | **备份** | 直接访问文件 | 需要通过 Docker | @@ -40,13 +42,15 @@ flowchart LR #### 选择建议 +相关信息如下表: + | 需求 | 推荐方案 | |------|----------| | 开发时同步代码 | Bind Mount | | 持久化数据库数据 | Volume | | 共享配置文件 | Bind Mount | | 容器间共享数据 | Volume | -| 备份方便 | Bind Mount(直接访问) | +| 备份方便 | Bind Mount (直接访问)| | 生产环境 | Volume | --- @@ -77,6 +81,8 @@ $ docker run -d \ #### 两种语法对比 +相关信息如下表: + | 特性 | --mount | -v | |------|---------|-----| | 语法 | 键值对,更清晰 | 冒号分隔,更简洁 | @@ -221,7 +227,7 @@ $ docker inspect mycontainer --format '{{json .Mounts}}' | jq | 字段 | 说明 | |------|------| -| `Type` | 挂载类型(bind) | +| `Type` | 挂载类型 (bind)| | `Source` | 宿主机路径 | | `Destination` | 容器内路径 | | `RW` | 是否可读写 | @@ -277,7 +283,7 @@ $ docker run -v /host/path:/container/path:cached myapp |------|------| | `:cached` | 宿主机权威,容器读取可能延迟 | | `:delegated` | 容器权威,宿主机读取可能延迟 | -| `:consistent` | 默认,完全一致(最慢) | +| `:consistent` | 默认,完全一致 (最慢)| --- diff --git a/08_data_network/data/summary.md b/08_data_network/data/summary.md index ac8c386..b06a638 100644 --- a/08_data_network/data/summary.md +++ b/08_data_network/data/summary.md @@ -1,5 +1,7 @@ ## 本章小结 +相关信息如下表: + | 要点 | 说明 | |------|------| | **作用** | 将宿主机目录挂载到容器 | diff --git a/08_data_network/data/tmpfs.md b/08_data_network/data/tmpfs.md index 2f07468..709a132 100644 --- a/08_data_network/data/tmpfs.md +++ b/08_data_network/data/tmpfs.md @@ -30,6 +30,8 @@ $ docker run --mount type=tmpfs,destination=/run,tmpfs-size=67108864 nginx ### 与 Volume / Bind Mount 对比 +相关信息如下表: + | 类型 | 数据位置 | 持久化 | 典型用途 | |------|---------|-------|---------| | Volume | Docker 管理目录 | 是 | 数据库、长期业务数据 | diff --git a/08_data_network/data/volume.md b/08_data_network/data/volume.md index 68f4bc9..ceb4207 100644 --- a/08_data_network/data/volume.md +++ b/08_data_network/data/volume.md @@ -19,6 +19,8 @@ flowchart LR ### 数据卷的特性 +相关信息如下表: + | 特性 | 说明 | |------|------| | **持久化** | 容器删除后数据仍然保留 | @@ -113,6 +115,7 @@ $ docker volume inspect my-vol ``` **关键字段**: + - `Mountpoint`:数据卷在宿主机上的实际存储位置 - `Driver`:存储驱动 (默认 local,也可以用第三方驱动) @@ -137,7 +140,7 @@ $ docker run -d \ | 参数 | 说明 | |------|------| -| `source` | 数据卷名称(不存在会自动创建) | +| `source` | 数据卷名称 (不存在会自动创建)| | `target` | 容器内挂载路径 | | `readonly` | 可选,只读挂载 | @@ -156,11 +159,13 @@ $ docker run -d \ #### 两种方式对比 +相关信息如下表: + | 特性 | --mount | -v | |------|---------|-----| | 语法 | 键值对,更清晰 | 冒号分隔,更简洁 | | 自动创建卷 | source 不存在会报错 | 自动创建 | -| 推荐程度 | ✅ 推荐(更明确) | 常用(更简洁) | +| 推荐程度 | ✅ 推荐 (更明确)| 常用 (更简洁)| #### 只读挂载 @@ -312,6 +317,7 @@ $ docker run --rm \ ``` **原理**: + 1. 创建临时容器 2. 挂载要备份的数据卷到 `/source` 3. 挂载当前目录到 `/backup` diff --git a/08_data_network/network/README.md b/08_data_network/network/README.md index ff7e47d..326454f 100644 --- a/08_data_network/network/README.md +++ b/08_data_network/network/README.md @@ -5,6 +5,7 @@ ## Docker 网络概述 Docker 容器需要网络来: + - 与外部世界通信 (访问互联网、被外部访问) - 容器之间相互通信 - 与宿主机通信 @@ -40,6 +41,8 @@ graph TD ### 核心组件 +相关信息如下表: + | 组件 | 说明 | |------|------| | **docker0** | 虚拟网桥,充当交换机角色 | @@ -105,7 +108,7 @@ ghi789... none null local |------|-----------------| | 只能用 IP 通信 | 支持容器名 DNS 解析 | | 所有容器在同一网络 | 更好的隔离性 | -| 需要 --link(已废弃) | 原生支持服务发现 | +| 需要 --link (已废弃)| 原生支持服务发现 | ### 创建自定义网络 @@ -227,6 +230,8 @@ $ docker run -d -p 8080:80 nginx ### 映射方式 +相关信息如下表: + | 参数 | 说明 | 示例 | |------|------|------| | `-p 8080:80` | 指定端口映射 | 宿主机 8080 → 容器 80 | @@ -322,6 +327,8 @@ $ docker network prune ## 本章小结 +相关信息如下表: + | 概念 | 要点 | |------|------| | **默认网络** | docker0 网桥,172.17.0.0/16 网段 | diff --git a/08_data_network/network/dns.md b/08_data_network/network/dns.md index c6d5597..1dbfa34 100644 --- a/08_data_network/network/dns.md +++ b/08_data_network/network/dns.md @@ -57,8 +57,7 @@ nameserver 114.114.114.114 $ docker run --dns-search=example.com myapp ``` -#### 3. --hostname(-h) - +#### 3. --hostname (-h) 设置容器的主机名。 ```bash @@ -91,6 +90,7 @@ $ docker run -h myweb nginx #### Q:容器无法解析域名 **现象**:`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 端口。 @@ -98,6 +98,7 @@ $ docker run -h myweb nginx #### Q:无法通过容器名通信 **现象**:`ping db` 提示 `bad address 'db'`。**原因**: + - 你可能在使用**默认的 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 4cff55b..67c04cd 100644 --- a/08_data_network/network/port_mapping.md +++ b/08_data_network/network/port_mapping.md @@ -5,6 +5,7 @@ ### 为什么要映射端口 容器运行在自己的隔离网络环境中 (通常是 Bridge 模式)。这意味着: + - **容器之间**:可以通过 IP 或容器名 (自定义网络) 互通。 - **宿主机访问容器**:可以通过容器 IP 访问。 - **外部网络访问容器**:❌ 默认无法直接访问。 @@ -124,6 +125,7 @@ $ docker run -d -p 127.0.0.1:3306:3306 mysql 如果宿主机 8080 已经被占用了,容器将无法启动。 **解决**: + - 更换宿主机端口:`-p 8081:80` - 让 Docker 自动分配:`-p 80` diff --git a/08_data_network/network/summary.md b/08_data_network/network/summary.md index ce7cf2d..50f3738 100644 --- a/08_data_network/network/summary.md +++ b/08_data_network/network/summary.md @@ -1,5 +1,7 @@ ## 本章小结 +相关信息如下表: + | 场景 | DNS 行为 | 备注 | |------|----------|------| | **默认网络** | 继承宿主机 | 不支持容器名解析 | @@ -13,7 +15,7 @@ | 要点 | 说明 | |------|------| -| **-p** | 指定端口映射(常用),如 `8080:80` | +| **-p** | 指定端口映射 (常用),如 `8080:80` | | **-P** | 随机映射所有 EXPOSE 的端口 | | **安全性** | 默认监听所有 IP,敏感服务应绑定 `127.0.0.1` | | **查看** | 使用 `docker port` 或 `docker ps` | diff --git a/09_buildx/9.1_buildkit.md b/09_buildx/9.1_buildkit.md index 8ecc1ec..2888bf1 100644 --- a/09_buildx/9.1_buildkit.md +++ b/09_buildx/9.1_buildkit.md @@ -98,8 +98,8 @@ RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \ |`id` | `id` 设置一个标志,以便区分缓存。| |`target` (必填项) | 缓存的挂载目标文件夹。| |`ro`,`readonly` | 只读,缓存文件夹不能被写入。 | -|`sharing` | 有 `shared` `private` `locked` 值可供选择。`sharing` 设置当一个缓存被多次使用时的表现,由于 `BuildKit` 支持并行构建,当多个步骤使用同一缓存时(同一 `id`)会发生冲突。`shared` 表示多个步骤可以同时读写,`private` 表示当多个步骤使用同一缓存时,每个步骤使用不同的缓存,`locked` 表示当一个步骤完成释放缓存后,后一个步骤才能继续使用该缓存。| -|`from` | 缓存来源(构建阶段),不填写时为空文件夹。| +|`sharing` | 有 `shared` `private` `locked` 值可供选择。`sharing` 设置当一个缓存被多次使用时的表现,由于 `BuildKit` 支持并行构建,当多个步骤使用同一缓存时 (同一 `id`) 会发生冲突。`shared` 表示多个步骤可以同时读写,`private` 表示当多个步骤使用同一缓存时,每个步骤使用不同的缓存,`locked` 表示当一个步骤完成释放缓存后,后一个步骤才能继续使用该缓存。| +|`from` | 缓存来源 (构建阶段),不填写时为空文件夹。| |`source` | 来源的文件夹路径。| #### `RUN --mount=type=bind` diff --git a/10_compose/10.6_django.md b/10_compose/10.6_django.md index 4c5654d..1995e62 100644 --- a/10_compose/10.6_django.md +++ b/10_compose/10.6_django.md @@ -34,6 +34,7 @@ flowchart TD 图 10-1 Django + PostgreSQL 的 Compose 架构 **关键点**: + - `web` 服务运行 Django 应用,对外暴露 8000 端口 - `db` 服务运行 PostgreSQL 数据库,只在内部网络可访问 - 两个服务通过 Docker Compose 自动创建的网络相互通信 @@ -104,8 +105,8 @@ gunicorn>=21.0,<22.0 | 包名 | 作用 | |------|------| | `Django` | Web 框架 | -| `psycopg[binary]` | PostgreSQL 数据库驱动(推荐使用 psycopg 3) | -| `gunicorn` | 生产环境 WSGI 服务器(可选,开发时可不用) | +| `psycopg[binary]` | PostgreSQL 数据库驱动 (推荐使用 psycopg 3)| +| `gunicorn` | 生产环境 WSGI 服务器 (可选,开发时可不用)| ### 步骤 3:创建 compose.yaml @@ -200,6 +201,7 @@ $ docker compose run --rm web django-admin startproject mysite . ``` **命令解释**: + - `docker compose run`:运行一次性命令 - `--rm`:命令执行后删除临时容器 - `web`:在 web 服务环境中执行 @@ -259,6 +261,7 @@ $ docker compose up ``` 你会看到: + 1. 首先构建 web 镜像 (第一次运行) 2. 启动 db 服务,等待健康检查通过 3. 启动 web 服务 diff --git a/10_compose/10.7_rails.md b/10_compose/10.7_rails.md index 92a27e6..5bb61ff 100644 --- a/10_compose/10.7_rails.md +++ b/10_compose/10.7_rails.md @@ -142,6 +142,7 @@ $ docker compose run --rm web rails new . --force --database=postgresql --skip-b ``` **命令解释**: + - `--rm`:执行后删除临时容器 - `--force`:覆盖已存在的文件 - `--database=postgresql`:配置使用 PostgreSQL @@ -282,6 +283,8 @@ $ docker compose run --rm web bundle update ### 开发 vs 生产 +相关信息如下表: + | 配置项 | 开发环境 | 生产环境 | |--------|---------|---------| | Rails 服务器 | Puma (开发模式) | Puma + Nginx | diff --git a/10_compose/10.8_wordpress.md b/10_compose/10.8_wordpress.md index e320fe5..1b6e336 100644 --- a/10_compose/10.8_wordpress.md +++ b/10_compose/10.8_wordpress.md @@ -97,6 +97,7 @@ Compose 会自动读取此同级目录下的文件。 #### 2。数据持久化 我们定义了两个命名卷: + - `db_data`:确保 MySQL 容器重建后数据不丢失 - `wp_data`:保存 WordPress 的核心文件、插件、主题和上传的媒体文件 @@ -198,6 +199,7 @@ WordPress 支持 Redis 缓存以提高性能。 #### Q:数据库连接错误 **现象**:访问页面显示 “Error establishing a database connection”。**排查**: + 1. 检查 `docker compose logs wordpress` 2. 确认 `.env` 中的密码与 YAML 文件引用一致 3. 确认 `WORDPRESS_DB_HOST` 也是 `db` (服务名) diff --git a/11_ops/security/README.md b/11_ops/security/README.md index 63f8f1b..1e0ba05 100644 --- a/11_ops/security/README.md +++ b/11_ops/security/README.md @@ -398,14 +398,15 @@ $ cosign sign --key cosign.key $IMAGE $ cosign verify --key cosign.pub $IMAGE ``` -### 3. SLSA(Supply-chain Levels for Software Artifacts) - +### 3. SLSA (Supply-chain Levels for Software Artifacts) 遵循 SLSA 框架,确保构建过程的完整性,例如使用 GitHub Actions 等受控环境进行构建,而非在开发者本地机器上构建发布。 --- ## 本章小结 +相关信息如下表: + | 安全措施 | 重要程度 | 实现方式 | |---------|---------|---------| | 非 root 运行 | ⭐⭐⭐ | `USER` 指令 | diff --git a/11_ops/security/daemon_sec.md b/11_ops/security/daemon_sec.md index f107bfc..a3d546d 100644 --- a/11_ops/security/daemon_sec.md +++ b/11_ops/security/daemon_sec.md @@ -13,6 +13,7 @@ 最近改进的 Linux 命名空间机制将可以实现使用非 root 用户来运行全功能的容器。这将从根本上解决了容器和主机之间共享文件系统而引起的安全问题。 终极目标是改进 2 个重要的安全特性: + * 将容器的 root 用户[映射到本地主机上的非 root 用户](https://docs.docker.com/engine/security/userns-remap/),减轻容器和主机之间因权限提升而引起的安全问题; * 允许 Docker 服务端在[非 root 权限 (rootless 模式)](https://docs.docker.com/engine/security/rootless/) 下运行,利用安全可靠的子进程来代理执行需要特权权限的操作。这些子进程将只允许在限定范围内进行操作,例如仅仅负责虚拟网络设定或文件系统管理、配置操作等。 diff --git a/11_ops/security/kernel_capability.md b/11_ops/security/kernel_capability.md index 18fe965..afc8527 100644 --- a/11_ops/security/kernel_capability.md +++ b/11_ops/security/kernel_capability.md @@ -10,6 +10,7 @@ Linux 内核自 2.2 版本起就支持能力机制,它将权限划分为更加 默认情况下,Docker 启动的容器被严格限制只允许使用内核的一部分能力。 使用能力机制对加强 Docker 容器的安全有很多好处。通常,在服务器上会运行一堆需要特权权限的进程,包括有 ssh、cron、syslogd、硬件管理工具模块 (例如负载模块)、网络配置工具等等。容器跟这些进程是不同的,因为几乎所有的特权进程都由容器以外的支持系统来进行管理。 + * ssh 访问被主机上 ssh 服务来管理; * cron 通常应该作为用户进程执行,权限交给使用它服务的应用来处理; * 日志系统可由 Docker 或第三方服务管理; @@ -17,6 +18,7 @@ Linux 内核自 2.2 版本起就支持能力机制,它将权限划分为更加 * 网络管理也都在主机上设置,除非特殊需求,容器不需要对网络进行配置。 从上面的例子可以看出,大部分情况下,容器并不需要 “真正的” root 权限,容器只需要少数的能力即可。为了加强安全,容器可以禁用一些没必要的权限。 + * 完全禁止任何 mount 操作; * 禁止直接访问本地主机的套接字; * 禁止访问一些文件系统的操作,比如创建新的设备、修改文件属性等; diff --git a/11_ops/security/other_feature.md b/11_ops/security/other_feature.md index 0ccefa1..4ef8803 100644 --- a/11_ops/security/other_feature.md +++ b/11_ops/security/other_feature.md @@ -5,6 +5,7 @@ 除了能力机制之外,还可以利用一些现有的安全机制来增强使用 Docker 的安全性,例如 TOMOYO,AppArmor,Seccomp,SELinux,GRSEC 等。 Docker 当前默认只启用了能力机制。用户可以采用多种方案来加强 Docker 主机的安全,例如: + * 在内核中启用 GRSEC 和 PAX,这将增加很多编译和运行时的安全检查;通过地址随机化避免恶意探测等。并且,启用该特性不需要 Docker 进行任何配置。 * 使用一些有增强安全特性的容器模板,比如带 AppArmor 的模板和 Redhat 带 SELinux 策略的模板。这些模板提供了额外的安全特性。 * 用户可以自定义访问控制机制来定制安全策略。 diff --git a/12_orchestration/kubernetes/_images/k8s-singlenode-docker.png b/12_orchestration/kubernetes/_images/k8s-singlenode-docker.png deleted file mode 100644 index 5ebf812..0000000 Binary files a/12_orchestration/kubernetes/_images/k8s-singlenode-docker.png and /dev/null differ diff --git a/12_orchestration/kubernetes/_images/kubernetes_logo.svg b/12_orchestration/kubernetes/_images/kubernetes_logo.svg deleted file mode 100644 index 6b702a3..0000000 --- a/12_orchestration/kubernetes/_images/kubernetes_logo.svg +++ /dev/null @@ -1,374 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/12_orchestration/kubernetes/intro.md b/12_orchestration/kubernetes/intro.md index fb50607..da639d0 100644 --- a/12_orchestration/kubernetes/intro.md +++ b/12_orchestration/kubernetes/intro.md @@ -81,6 +81,7 @@ Kubernetes 也是 C/S 架构,由 **Control Plane (控制平面) **和** Worker ### 学习建议 Kubernetes 的学习曲线较陡峭。建议的学习路径: + 1. **理解基本概念**:Pod,Deployment,Service 2. **动手实践**:使用 Minikube 或 Kind 在本地搭建集群 3. **部署应用**:编写 YAML 部署一个无状态应用 diff --git a/13_ecosystem/cloud/intro.md b/13_ecosystem/cloud/intro.md index 70661fe..bde7d62 100644 --- a/13_ecosystem/cloud/intro.md +++ b/13_ecosystem/cloud/intro.md @@ -5,18 +5,21 @@ ### 1。容器编排托管服务 这是目前最主流的形式。云厂商托管 Kubernetes 的控制平面 (Master 节点),用户只需管理工作节点 (Worker Node)。 + * **优势**:降低了 Kubernetes 集群的维护成本,高可用性由厂商保证。 * **典型服务**:AWS EKS,Azure AKS,Google GKE,阿里云 ACK,腾讯云 TKE。 ### 2。容器实例服务 这一类服务通常被称为 CaaS (Container as a Service)。用户无需管理底层服务器 (EC2/CVM),只需提供镜像和配置即可运行容器。 + * **优势**:极致的弹性,按秒计费,零运维。 * **典型服务**:AWS Fargate,Azure Container Instances,Google Cloud Run,阿里云 ECI。 ### 3。镜像仓库服务 提供安全、可靠的私有 Docker 镜像存储服务,通常与云厂商的 CI/CD 流水线深度集成。 + * **典型服务**: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 f7d5f33..e530e25 100644 --- a/13_ecosystem/cloud/multicloud.md +++ b/13_ecosystem/cloud/multicloud.md @@ -4,10 +4,12 @@ ### 三大公有云 Kubernetes 服务对比 +相关信息如下表: + | 特性 | Google GKE | AWS EKS | Azure AKS | | :--- | :--- | :--- | :--- | | **版本更新** | 最快,通常是 K8s 新特性的首发地 | 相对保守,注重稳定性 | 跟随社区,更新速度适中 | -| **控制平面管理** | 全托管,自动升级,免费(部分区域) | 托管,每小时收费 | 全托管,控制平面免费 | +| **控制平面管理** | 全托管,自动升级,免费 (部分区域)| 托管,每小时收费 | 全托管,控制平面免费 | | **节点管理** | GKE Autopilot 模式完全托管节点 | Managed Node Groups 简化管理 | Virtual Machine Scale Sets | | **网络模型** | VPC-native, 性能优秀 | AWS VPC CNI, Pod 直接获取 VPC IP | Azure CNI (消耗 IP 多) 或 Kubenet | | **集成度** | 与 GCP 数据分析、AI 服务集成紧密 | 与 AWS IAM, ALB, CloudWatch 集成深度高 | 与 Active Directory, Azure DevOps 集成好 | diff --git a/14_implementation/14.1_arch.md b/14_implementation/14.1_arch.md index 97a0ee3..5a8ce30 100644 --- a/14_implementation/14.1_arch.md +++ b/14_implementation/14.1_arch.md @@ -34,6 +34,7 @@ Docker 的内部架构如同洋葱一样分层,每一层专注解决特定问 #### 2。Dockerd (守护进程) Docker 的大脑。 + - 监听 API 请求 - 管理 Docker 对象 (镜像、容器、网络、卷) - 编排下层组件完成工作 @@ -41,6 +42,7 @@ Docker 的大脑。 #### 3。Containerd (高级运行时) 行业标准的容器运行时 (CNCF 毕业项目)。 + - 管理容器的完整生命周期 (启动、停止) - 镜像拉取与存储 - **不包含**复杂的与容器无关的功能 (如构建、API) @@ -49,6 +51,7 @@ Docker 的大脑。 #### 4。Runc (低级运行时) 用于创建和运行容器的 CLI 工具。 + - 直接与内核交互 (Namespaces,Cgroups) - 遵循 OCI (Open Container Initiative) 规范 - **主要职责**:根据配置启动一个容器,然后退出 (将控制权交给容器进程) @@ -56,6 +59,7 @@ Docker 的大脑。 #### 5. Shim 每个容器都有一个 shim 进程。 + - **解耦**:允许 dockerd 重启而不影响容器运行 - **保持 IO**:维持容器的标准输入输出 - **状态汇报**:向 containerd 汇报容器退出状态 @@ -135,13 +139,15 @@ flowchart TD ### 总结 +相关信息如下表: + | 组件 | 角色 | 关键职责 | |------|------|----------| | **CLI** | 指挥官 | 发送指令,展示结果 | | **Dockerd** | 大管家 | API 接口,整体调度 | | **Containerd** | 经理 | 容器生命周期,镜像管理 | | **Shim** | 监工 | 保持 IO,允许无守护进程重启 | -| **Runc** | 工人 | 真正干活(创建容器),干完就走 | +| **Runc** | 工人 | 真正干活 (创建容器),干完就走 | ### 延伸阅读 diff --git a/14_implementation/14.2_namespace.md b/14_implementation/14.2_namespace.md index c9951df..40121b5 100644 --- a/14_implementation/14.2_namespace.md +++ b/14_implementation/14.2_namespace.md @@ -36,7 +36,7 @@ Linux 内核提供了以下几种 Namespace,Docker 容器使用了全部: | **UTS** | 主机名 | 独立的主机名和域名 | | **IPC** | 进程间通信 | 独立的信号量、消息队列、共享内存 | | **USER** | 用户/组 ID | 容器内的 root 可以映射为宿主机的普通用户 | -| **Cgroup** | Cgroup 根目录 | 隔离 cgroup 层级视图(Linux 4.6+) | +| **Cgroup** | Cgroup 根目录 | 隔离 cgroup 层级视图 (Linux 4.6+)| --- @@ -139,6 +139,8 @@ MNT Namespace 负责文件系统挂载点的隔离,确保容器看到独立的 #### 与 chroot 的区别 +相关信息如下表: + | 特性 | chroot | MNT Namespace | |------|--------|---------------| | 安全性 | 可以逃逸 | 更安全 | diff --git a/14_implementation/14.3_cgroups.md b/14_implementation/14.3_cgroups.md index a428dd0..2cdbebe 100644 --- a/14_implementation/14.3_cgroups.md +++ b/14_implementation/14.3_cgroups.md @@ -33,17 +33,21 @@ flowchart LR ### cgroups 的历史 +相关信息如下表: + | 时间 | 事件 | |------|------| | 2006 | Google 工程师提出 cgroups 概念 | | 2008 | Linux 2.6.24 正式支持 cgroups v1 | | 2016 | Linux 4.5 引入 cgroups v2 | -| 现在 | Docker 默认使用 cgroups v2(如系统支持) | +| 现在 | Docker 默认使用 cgroups v2 (如系统支持)| --- ### cgroups 可以限制的资源 +相关信息如下表: + | 资源类型 | 子系统 | 说明 | |---------|--------|------| | **CPU** | `cpu`, `cpuset` | CPU 使用时间和核心分配 | @@ -78,10 +82,10 @@ $ docker run --memory-reservation 256m myapp | 参数 | 说明 | |------|------| -| `-m` / `--memory` | 硬限制(超过会 OOM Kill) | +| `-m` / `--memory` | 硬限制 (超过会 OOM Kill)| | `--memory-swap` | 内存 + swap 总限制 | -| `--memory-reservation` | 软限制(内存竞争时生效) | -| `--oom-kill-disable` | 禁用 OOM Killer(谨慎使用) | +| `--memory-reservation` | 软限制 (内存竞争时生效)| +| `--oom-kill-disable` | 禁用 OOM Killer (谨慎使用)| #### CPU 限制 @@ -103,9 +107,9 @@ $ docker run --cpu-shares=512 myapp | 参数 | 说明 | |------|------| -| `--cpus` | 限制 CPU 核心数(如 1.5) | +| `--cpus` | 限制 CPU 核心数 (如 1.5)| | `--cpuset-cpus` | 绑定到特定 CPU 核心 | -| `--cpu-shares` | CPU 时间片权重(相对值) | +| `--cpu-shares` | CPU 时间片权重 (相对值)| | `--cpu-period` / `--cpu-quota` | 精细控制 CPU 配额 | #### 磁盘 I/O 限制 @@ -207,12 +211,14 @@ $ docker run --rm --cpus=1 stress --cpu 4 ### cgroups v1 vs v2 +相关信息如下表: + | 特性 | cgroups v1 | cgroups v2 | |------|-----------|-----------| -| 层级结构 | 多层级(每个资源单独) | 统一层级 | +| 层级结构 | 多层级 (每个资源单独)| 统一层级 | | 管理复杂度 | 复杂 | 简化 | | 资源分配 | 基于层级 | 基于子树 | -| PSI(压力监控) | ❌ | ✅ | +| PSI (压力监控)| ❌ | ✅ | | rootless 容器 | 部分支持 | 完整支持 | #### 概述 diff --git a/14_implementation/14.4_ufs.md b/14_implementation/14.4_ufs.md index e79a0a3..8b7a3e7 100644 --- a/14_implementation/14.4_ufs.md +++ b/14_implementation/14.4_ufs.md @@ -56,6 +56,7 @@ COPY . . # 层4:应用代码 #### 3。容器启动快 容器启动时不需要复制镜像,只需: + 1. 在镜像层上创建一个薄的可写层 2. 联合挂载所有层 @@ -83,6 +84,7 @@ flowchart LR ``` **流程**: + 1. 从只读层读取文件 2. 复制到容器的可写层 3. 在可写层中修改 @@ -105,6 +107,8 @@ Docker 可使用多种联合文件系统实现: #### 各发行版推荐 +相关信息如下表: + | Linux 发行版 | 推荐存储驱动 | |-------------|-------------| | Ubuntu 16.04+ | overlay2 | @@ -154,6 +158,8 @@ flowchart TD #### 文件操作行为 +相关信息如下表: + | 操作 | 行为 | |------|------| | **读取** | 从上到下查找第一个匹配的文件 | @@ -217,12 +223,14 @@ RUN apt-get update && \ #### 2。避免在容器中写入大量数据 容器层的写入性能低于直接写入。大量数据应使用: + - 数据卷 (Volume) - 绑定挂载 (Bind Mount) #### 3。使用。dockerignore 排除不需要的文件可以: + - 减小构建上下文 - 避免创建不必要的层 diff --git a/14_implementation/14.6_network.md b/14_implementation/14.6_network.md index 138843b..58b384f 100644 --- a/14_implementation/14.6_network.md +++ b/14_implementation/14.6_network.md @@ -14,6 +14,7 @@ Docker 容器网络就利用了这项技术。它在本地主机和容器内分 ### 创建网络参数 Docker 创建一个容器的时候,会执行如下操作: + * 创建一对虚拟接口,分别放到本地主机和新容器中; * 本地主机一端桥接到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 veth65f9; * 容器一端放到新容器中,并修改名字作为 eth0,这个接口只在容器的命名空间可见; @@ -22,6 +23,7 @@ Docker 创建一个容器的时候,会执行如下操作: 完成这些之后,容器就可以使用 eth0 虚拟网卡来连接其他容器和其他网络。 可以在 `docker run` 的时候通过 `--net` 参数来指定容器的网络配置,有 4 个可选值: + * `--net=bridge` 这个是默认值,连接到默认的网桥。 * `--net=host` 告诉 Docker 不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如 D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用 `--privileged=true`,容器会被允许直接配置主机的网络堆栈。 * `--net=container:NAME_or_ID` 让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过 `lo` 环回接口通信。 diff --git a/14_implementation/_images/docker_arch.png b/14_implementation/_images/docker_arch.png deleted file mode 100644 index 64df422..0000000 Binary files a/14_implementation/_images/docker_arch.png and /dev/null differ diff --git a/14_implementation/summary.md b/14_implementation/summary.md index acc4a23..3a1c84e 100644 --- a/14_implementation/summary.md +++ b/14_implementation/summary.md @@ -1,5 +1,7 @@ ## 本章小结 +相关信息如下表: + | Namespace | 隔离内容 | 一句话说明 | |-----------|---------|-----------| | PID | 进程 ID | 容器有自己的进程树 | diff --git a/15_cases/ci/drone/_images/drone-build.png b/15_cases/ci/drone/_images/drone-build.png deleted file mode 100644 index 0c6c009..0000000 Binary files a/15_cases/ci/drone/_images/drone-build.png and /dev/null differ diff --git a/15_cases/ci/drone/demo/README.md b/15_cases/ci/drone/demo/README.md index 2942921..cea50f3 100644 --- a/15_cases/ci/drone/demo/README.md +++ b/15_cases/ci/drone/demo/README.md @@ -15,8 +15,10 @@ ```bash docker build -t drone-demo-app . ``` + 3. 运行容器: ```bash docker run -p 8080:8080 drone-demo-app ``` + 4. 访问 `http://localhost:8080` 查看效果。 diff --git a/15_cases/os/_images/alpinelinux-logo.png b/15_cases/os/_images/alpinelinux-logo.png deleted file mode 100644 index acfe2b1..0000000 Binary files a/15_cases/os/_images/alpinelinux-logo.png and /dev/null differ diff --git a/15_cases/os/_images/busybox-logo.png b/15_cases/os/_images/busybox-logo.png deleted file mode 100644 index 4d3126a..0000000 Binary files a/15_cases/os/_images/busybox-logo.png and /dev/null differ diff --git a/15_cases/os/_images/centos-logo.png b/15_cases/os/_images/centos-logo.png deleted file mode 100644 index fec4449..0000000 Binary files a/15_cases/os/_images/centos-logo.png and /dev/null differ diff --git a/15_cases/os/_images/coreos-login.png b/15_cases/os/_images/coreos-login.png deleted file mode 100644 index 02142e7..0000000 Binary files a/15_cases/os/_images/coreos-login.png and /dev/null differ diff --git a/15_cases/os/_images/coreos-logo.jpg b/15_cases/os/_images/coreos-logo.jpg deleted file mode 100644 index dee6e9e..0000000 Binary files a/15_cases/os/_images/coreos-logo.jpg and /dev/null differ diff --git a/15_cases/os/_images/coreos_crt.png b/15_cases/os/_images/coreos_crt.png deleted file mode 100644 index 0260b26..0000000 Binary files a/15_cases/os/_images/coreos_crt.png and /dev/null differ diff --git a/15_cases/os/_images/coreos_list.png b/15_cases/os/_images/coreos_list.png deleted file mode 100644 index 9896b0a..0000000 Binary files a/15_cases/os/_images/coreos_list.png and /dev/null differ diff --git a/15_cases/os/_images/coreos_run_ip.png b/15_cases/os/_images/coreos_run_ip.png deleted file mode 100644 index ab121f4..0000000 Binary files a/15_cases/os/_images/coreos_run_ip.png and /dev/null differ diff --git a/15_cases/os/_images/debian-logo.png b/15_cases/os/_images/debian-logo.png deleted file mode 100644 index 1cfcc65..0000000 Binary files a/15_cases/os/_images/debian-logo.png and /dev/null differ diff --git a/15_cases/os/_images/docker_version.png b/15_cases/os/_images/docker_version.png deleted file mode 100644 index 479a903..0000000 Binary files a/15_cases/os/_images/docker_version.png and /dev/null differ diff --git a/15_cases/os/_images/fedora-logo.png b/15_cases/os/_images/fedora-logo.png deleted file mode 100644 index 7dd1589..0000000 Binary files a/15_cases/os/_images/fedora-logo.png and /dev/null differ diff --git a/15_cases/os/_images/php_pulling.png b/15_cases/os/_images/php_pulling.png deleted file mode 100644 index 189e058..0000000 Binary files a/15_cases/os/_images/php_pulling.png and /dev/null differ diff --git a/15_cases/os/_images/ubuntu-logo.jpg b/15_cases/os/_images/ubuntu-logo.jpg deleted file mode 100644 index 4138fab..0000000 Binary files a/15_cases/os/_images/ubuntu-logo.jpg and /dev/null differ diff --git a/15_cases/os/_images/vmware_coreos.png b/15_cases/os/_images/vmware_coreos.png deleted file mode 100644 index 1003e4c..0000000 Binary files a/15_cases/os/_images/vmware_coreos.png and /dev/null differ diff --git a/16_appendix/16.4_terminology.md b/16_appendix/16.4_terminology.md index f80bfb8..5e98f83 100644 --- a/16_appendix/16.4_terminology.md +++ b/16_appendix/16.4_terminology.md @@ -4,26 +4,28 @@ ### 核心术语统一表 -| 统一写法(推荐) | 可接受写法 | 避免写法 | 说明 | +相关信息如下表: + +| 统一写法 (推荐)| 可接受写法 | 避免写法 | 说明 | |---|---|---|---| | Docker Engine | Docker 引擎 | docker engine | 产品名首字母大写。 | | Docker Desktop | - | docker desktop | 产品名首字母大写。 | | Dockerfile | - | Docker File、dockerfile | 固定拼写。 | -| Docker 镜像(Image) | 镜像 | image(纯英文散落) | 首次出现建议中英文并列。 | -| Docker 容器(Container) | 容器 | container(纯英文散落) | 与镜像区分清楚。 | -| 仓库(Repository) | Repo(非正式) | 镜像仓库/Repository 混用不解释 | 首次出现需给出英文。 | -| 注册服务器(Registry) | 镜像注册服务 | 私有仓库/Registry 混指 | Registry 与 Repository 需区分。 | -| 标签(Tag) | 版本标签 | tag(正文中小写裸写) | 命令中保留原样。 | -| Docker Compose | Compose | docker compose(当作产品名) | 产品名用 `Docker Compose`。 | -| `docker compose` | - | `docker-compose`(新示例中) | 命令统一使用 V2 子命令写法。 | +| Docker 镜像 (Image)| 镜像 | image (纯英文散落)| 首次出现建议中英文并列。 | +| Docker 容器 (Container)| 容器 | container (纯英文散落)| 与镜像区分清楚。 | +| 仓库 (Repository)| Repo (非正式)| 镜像仓库/Repository 混用不解释 | 首次出现需给出英文。 | +| 注册服务器 (Registry)| 镜像注册服务 | 私有仓库/Registry 混指 | Registry 与 Repository 需区分。 | +| 标签 (Tag)| 版本标签 | tag (正文中小写裸写)| 命令中保留原样。 | +| Docker Compose | Compose | docker compose (当作产品名)| 产品名用 `Docker Compose`。 | +| `docker compose` | - | `docker-compose` (新示例中)| 命令统一使用 V2 子命令写法。 | | `compose.yaml` | `compose.yml` | 新示例继续使用 `docker-compose.yml` | 教学默认文件名统一为 `compose.yaml`。 | -| Kubernetes | K8s(缩写) | kubernetes(正文) | 正文统一首字母大写。 | -| `kubectl` | - | kubeclt(拼写错误) | 命令与二进制名用反引号包裹。 | -| etcd | - | Etcd(混用) | 项目官方写法为小写 `etcd`。 | -| Docker Buildx | Buildx | buildx(正文裸写) | 产品名用 `Docker Buildx`。 | +| Kubernetes | K8s (缩写)| kubernetes (正文)| 正文统一首字母大写。 | +| `kubectl` | - | kubeclt (拼写错误)| 命令与二进制名用反引号包裹。 | +| etcd | - | Etcd (混用)| 项目官方写法为小写 `etcd`。 | +| Docker Buildx | Buildx | buildx (正文裸写)| 产品名用 `Docker Buildx`。 | | BuildKit | - | buildkit | 固定大小写。 | -| 控制平面(Control Plane) | - | 主控平面(未定义) | 章节内保持单一译名。 | -| 工作节点(Worker Node) | 节点(在上下文明确时) | 工作机器(未定义) | 与控制平面对照使用。 | +| 控制平面 (Control Plane)| - | 主控平面 (未定义)| 章节内保持单一译名。 | +| 工作节点 (Worker Node)| 节点 (在上下文明确时)| 工作机器 (未定义)| 与控制平面对照使用。 | ### 清稿执行规则 diff --git a/16_appendix/_images/cmd_logic.png b/16_appendix/_images/cmd_logic.png deleted file mode 100644 index d8deeb2..0000000 Binary files a/16_appendix/_images/cmd_logic.png and /dev/null differ diff --git a/16_appendix/_images/container_status.png b/16_appendix/_images/container_status.png deleted file mode 100644 index 9cf8842..0000000 Binary files a/16_appendix/_images/container_status.png and /dev/null differ diff --git a/16_appendix/faq/errors.md b/16_appendix/faq/errors.md index 267eaf4..7311250 100644 --- a/16_appendix/faq/errors.md +++ b/16_appendix/faq/errors.md @@ -1,5 +1,7 @@ ## 常见错误速查表 +相关信息如下表: + | 错误信息 / 现象 | 可能原因 | 解决方案 | | :--- | :--- | :--- | | `Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?` | Docker 服务未启动 | Linux: `sudo systemctl start docker`
Mac/Win: 启动 Docker Desktop | diff --git a/CHANGELOG.md b/CHANGELOG.md index a6cc16e..0272337 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ * 更新 `CoreOS` 章节 * 更新 `etcd` 章节,基于 3.x 版本 - * 删除 `Docker Compose` 中的 `links`指令 + * 删除 `Docker Compose` 中的 `links` 指令 * 替换 `docker daemon` 命令为 `dockerd` * 替换 `docker ps` 命令为 `docker container ls` @@ -71,13 +71,13 @@ * 优化文字排版 * 调整目录结构 * 修复内容逻辑错误 - * 修复`404` 链接 + * 修复 `404` 链接 * 0.9.0-rc1: 2017-11-29 - * 根据最新版本(v17.09)修订内容 + * 根据最新版本 (v17.09) 修订内容 - * 增加 `Dockerfile` 多阶段构建( `multistage builds` ) `Docker 17.05` 新增特性 + * 增加 `Dockerfile` 多阶段构建 (`multistage builds`) `Docker 17.05` 新增特性 * 增加 `docker exec` 子命令介绍 * 增加 `docker` 管理子命令 `container` `image` `network` `volume` 介绍 * 增加 `树莓派单片电脑` 安装 Docker @@ -102,7 +102,7 @@ * 0.8.0: 2017-01-08 * 修正文字内容 - * 根据最新版本(1.12)修订安装使用 + * 根据最新版本 (1.12) 修订安装使用 * 补充附录章节 * 0.7.0: 2016-06-12 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 65162c1..917ff89 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,6 +36,10 @@ $ git rebase upstream/master $ git push -f origin master ``` +## 概述 + +总体概述了以下内容。 + ## 排版规范 -本开源书籍遵循 [中文排版指南](https://github.com/mzlogin/chinese-copywriting-guidelines) 规范。 +本开源书籍遵循[中文排版指南](https://github.com/mzlogin/chinese-copywriting-guidelines)规范。 diff --git a/README.md b/README.md index 49149c3..f630315 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # Docker — 从入门到实践 +下图直观地展示了本节内容: + [![](https://img.shields.io/github/stars/yeasy/docker_practice.svg?style=social&label=Stars)](https://github.com/yeasy/docker_practice) [![](https://img.shields.io/github/release/yeasy/docker_practice/all.svg)](https://github.com/yeasy/docker_practice/releases) [![](https://img.shields.io/badge/Based-Docker%20Engine%20v29.x-blue.svg)](https://docs.docker.com/engine/release-notes/) [![](https://img.shields.io/badge/Docker%20%E6%8A%80%E6%9C%AF%E5%85%A5%E9%97%A8%E4%B8%8E%E5%AE%9E%E6%88%98-jd.com-red.svg)][1] -**v1.5.4** +**v1.5.5** [Docker](https://www.docker.com) 是个划时代的开源项目,它彻底释放了计算虚拟化的威力,极大提高了应用的维护效率,降低了云计算应用开发的成本!使用 Docker,可以让应用的部署、测试和分发都变得前所未有的高效和轻松! @@ -12,14 +14,16 @@ ## 内容特色 -* **入门基础**:前六章为基础内容,帮助深入理解 Docker 的基本概念(镜像、容器、仓库)和核心操作。 +* **入门基础**:前六章为基础内容,帮助深入理解 Docker 的基本概念 (镜像、容器、仓库) 和核心操作。 * **进阶应用**:7 ~ 10 章涵盖数据管理、网络配置、Buildx、Compose、运维管理等高级操作。 -* **深入原理**:11 ~ 13 章介绍容器编排(Kubernetes、Etcd)、容器生态、底层实现技术。 -* **实战扩展**:14 ~ 15 章展示操作系统、CI/CD等典型应用场景和实践案例,以及工具参考。 +* **深入原理**:11 ~ 13 章介绍容器编排 (Kubernetes、Etcd)、容器生态、底层实现技术。 +* **实战扩展**:14 ~ 15 章展示操作系统、CI/CD 等典型应用场景和实践案例,以及工具参考。 * **广泛扩展**:涵盖 Fedora CoreOS、容器云等热门开源项目,并展示典型的应用场景和实践案例。 ## 阅读方式 +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + ### 在线阅读 > 推荐访问官方 GitBook,体验最佳。 @@ -30,7 +34,9 @@ ### 本地阅读 -#### 方式 1:Docker 镜像(推荐) +本节涵盖了相关内容与详细描述,主要探讨以下几个方面: + +#### 方式 1:Docker 镜像 (推荐) 无需安装任何依赖,一条命令即可启动。 @@ -40,7 +46,7 @@ docker run -it --rm -p 4000:80 ccr.ccs.tencentyun.com/dockerpracticesig/docker_p 启动后访问 [http://localhost:4000](http://localhost:4000)。 [详情参考](https://github.com/yeasy/docker_practice/wiki/%E7%A6%BB%E7%BA%BF%E9%98%85%E8%AF%BB%E5%8A%9F%E8%83%BD%E8%AF%A6%E8%A7%A3) -#### 方式 2:本地构建(HonKit) +#### 方式 2:本地构建 适合想要修改内容或深度定制的读者。需要安装 Node.js 环境。 @@ -54,22 +60,24 @@ npx honkit serve 欢迎加入 Docker 技术交流群,分享 Docker 资源,交流 Docker 技术。 -* **GitHub Discussions**:[点击前往](https://github.com/yeasy/docker_practice/discussions)(技术问答、交流) -* **GitHub Issues**:[提交 Bug](https://github.com/yeasy/docker_practice/issues/new/choose)(内容错误、建议) +* **GitHub Discussions**:[点击前往](https://github.com/yeasy/docker_practice/discussions) (技术问答、交流) +* **GitHub Issues**:[提交 Bug](https://github.com/yeasy/docker_practice/issues/new/choose) (内容错误、建议) -> **交流 QQ 群**(部分已满,建议优先使用 GitHub Discussions): +> **交流 QQ 群** (部分已满,建议优先使用 GitHub Discussions): > * 341410255 (I), 419042067 (II), 210028779 (III), 483702734 (IV), 460598761 (V) > * 581983671 (VI), 252403484 (VII), 544818750 (VIII), 571502246 (IX), 145983035 (X) ## 参与贡献 -欢迎 [参与项目维护](CONTRIBUTING.md)。 +欢迎[参与项目维护](CONTRIBUTING.md)。 * [修订记录](CHANGELOG.md) * [贡献者名单](https://github.com/yeasy/docker_practice/graphs/contributors) ## 进阶学习 +下图直观地展示了本节内容: + [![](https://github.com/yeasy/docker_practice/raw/master/_images/docker_primer4.jpg)][1] 《[Docker 技术入门与实战][1]》已更新到第 4 版,讲解最新容器技术栈知识,欢迎大家阅读并反馈建议。 @@ -87,6 +95,8 @@ npx honkit serve ## Star History +下图直观地展示了本节内容: + [![Star History Chart](https://api.star-history.com/svg?repos=yeasy/docker_practice&type=Date)](https://star-history.com/#yeasy/docker_practice&Date) [1]: https://item.jd.com/10200902362001.html diff --git a/SUMMARY.md b/SUMMARY.md index 20a37c0..3622193 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -4,19 +4,19 @@ * [修订记录](CHANGELOG.md) * [如何贡献](CONTRIBUTING.md) -## 第一部分: 入门篇 +## 第一部分:入门篇 * [第一章 Docker 简介](01_introduction/README.md) * [快速上手](01_introduction/1.1_quickstart.md) * [什么是 Docker](01_introduction/1.2_what.md) * [为什么要用 Docker](01_introduction/1.3_why.md) * [本章小结](01_introduction/summary.md) -* [第二章 基本概念](02_basic_concept/README.md) +* [第二章基本概念](02_basic_concept/README.md) * [镜像](02_basic_concept/2.1_image.md) * [容器](02_basic_concept/2.2_container.md) * [仓库](02_basic_concept/2.3_repository.md) * [本章小结](02_basic_concept/summary.md) -* [第三章 安装 Docker](03_install/README.md) +* [第三章安装 Docker](03_install/README.md) * [Ubuntu](03_install/3.1_ubuntu.md) * [Debian](03_install/3.2_debian.md) * [Fedora](03_install/3.3_fedora.md) @@ -27,7 +27,7 @@ * [Windows 10/11](03_install/3.8_windows.md) * [镜像加速器](03_install/3.9_mirror.md) * [开启实验特性](03_install/3.10_experimental.md) -* [第四章 使用镜像](04_image/README.md) +* [第四章使用镜像](04_image/README.md) * [获取镜像](04_image/4.1_pull.md) * [列出镜像](04_image/4.2_list.md) * [删除本地镜像](04_image/4.3_rm.md) @@ -36,7 +36,7 @@ * [其它制作镜像的方式](04_image/4.6_other.md) * [实现原理](04_image/4.7_internal.md) * [本章小结](04_image/summary.md) -* [第五章 操作容器](05_container/README.md) +* [第五章操作容器](05_container/README.md) * [启动](05_container/5.1_run.md) * [守护态运行](05_container/5.2_daemon.md) * [终止](05_container/5.3_stop.md) @@ -44,14 +44,14 @@ * [导出和导入](05_container/5.5_import_export.md) * [删除](05_container/5.6_rm.md) * [本章小结](05_container/summary.md) -* [第六章 访问仓库](06_repository/README.md) +* [第六章访问仓库](06_repository/README.md) * [Docker Hub](06_repository/6.1_dockerhub.md) * [私有仓库](06_repository/6.2_registry.md) * [私有仓库高级配置](06_repository/6.3_registry_auth.md) * [Nexus 3](06_repository/6.4_nexus3_registry.md) * [本章小结](06_repository/summary.md) -## 第二部分: 进阶篇 +## 第二部分:进阶篇 * [第七章 Dockerfile 指令详解](07_dockerfile/README.md) * [RUN 执行命令](07_dockerfile/7.1_run.md) @@ -73,7 +73,7 @@ * [多阶段构建](07_dockerfile/7.17_multistage_builds.md) * [实战多阶段构建 Laravel 镜像](07_dockerfile/7.18_multistage_builds_laravel.md) * [本章小结](07_dockerfile/summary.md) -* [第八章 数据与网络管理](08_data_network/README.md) +* [第八章数据与网络管理](08_data_network/README.md) * [数据管理](08_data_network/data/README.md) * [数据卷](08_data_network/data/volume.md) * [挂载主机目录](08_data_network/data/bind-mounts.md) @@ -97,7 +97,7 @@ * [实战 Rails](10_compose/10.7_rails.md) * [实战 WordPress](10_compose/10.8_wordpress.md) * [实战 LNMP](10_compose/10.9_lnmp.md) -* [第十一章 运维管理](11_ops/README.md) +* [第十一章运维管理](11_ops/README.md) * [容器监控](11_ops/monitor/README.md) * [Prometheus](11_ops/monitor/prometheus.md) * [日志管理](11_ops/logs/README.md) @@ -110,9 +110,9 @@ * [其它安全特性](11_ops/security/other_feature.md) * [总结](11_ops/security/summary.md) -## 第三部分: 深入篇 +## 第三部分:深入篇 -* [第十二章 容器编排](12_orchestration/README.md) +* [第十二章容器编排](12_orchestration/README.md) * [Etcd 项目](12_orchestration/etcd/README.md) * [简介](12_orchestration/etcd/intro.md) * [安装](12_orchestration/etcd/install.md) @@ -125,15 +125,15 @@ * [高级特性](12_orchestration/kubernetes/advanced.md) * [实战练习](12_orchestration/kubernetes/practice.md) * [部署 Kubernetes](12_orchestration/setup/README.md) - * [使用 kubeadm 部署 Kubernetes(CRI 使用 containerd)](12_orchestration/setup/kubeadm.md) - * [使用 kubeadm 部署 Kubernetes(使用 Docker)](12_orchestration/setup/kubeadm-docker.md) + * [使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)](12_orchestration/setup/kubeadm.md) + * [使用 kubeadm 部署 Kubernetes (使用 Docker)](12_orchestration/setup/kubeadm-docker.md) * [在 Docker Desktop 使用](12_orchestration/setup/docker-desktop.md) * [Kind - Kubernetes IN Docker](12_orchestration/setup/kind.md) * [K3s - 轻量级 Kubernetes](12_orchestration/setup/k3s.md) * [一步步部署 Kubernetes 集群](12_orchestration/setup/systemd.md) * [部署 Dashboard](12_orchestration/setup/dashboard.md) * [Kubernetes 命令行 kubectl](12_orchestration/kubectl/README.md) -* [第十三章 容器生态](13_ecosystem/README.md) +* [第十三章容器生态](13_ecosystem/README.md) * [Fedora CoreOS](13_ecosystem/coreos/README.md) * [简介](13_ecosystem/coreos/intro.md) * [安装](13_ecosystem/coreos/install.md) @@ -145,7 +145,7 @@ * [小结](13_ecosystem/cloud/summary.md) * [多云部署策略](13_ecosystem/cloud/multicloud.md) * [podman - 下一代 Linux 容器工具](13_ecosystem/podman/README.md) -* [第十四章 底层实现](14_implementation/README.md) +* [第十四章底层实现](14_implementation/README.md) * [基本架构](14_implementation/14.1_arch.md) * [命名空间](14_implementation/14.2_namespace.md) * [控制组](14_implementation/14.3_cgroups.md) @@ -154,9 +154,9 @@ * [网络](14_implementation/14.6_network.md) * [本章小结](14_implementation/summary.md) -## 第四部分: 实战篇 +## 第四部分:实战篇 -* [第十五章 实战案例](15_cases/README.md) +* [第十五章实战案例](15_cases/README.md) * [实战案例 - 操作系统](15_cases/os/README.md) * [Busybox](15_cases/os/busybox.md) * [Alpine](15_cases/os/alpine.md) @@ -171,7 +171,7 @@ * [Drone Demo](15_cases/ci/drone/demo/README.md) * [在 IDE 中使用 Docker](15_cases/ide/README.md) * [VS Code](15_cases/ide/vsCode.md) -* [第十六章 附录](16_appendix/README.md) +* [第十六章附录](16_appendix/README.md) * [附录一:常见问题总结](16_appendix/faq/README.md) * [常见错误速查表](16_appendix/faq/errors.md) * [附录二:热门镜像介绍](16_appendix/repo/README.md) @@ -191,5 +191,5 @@ * [附录四:Dockerfile 最佳实践](16_appendix/16.1_best_practices.md) * [附录五:如何调试 Docker](16_appendix/16.2_debug.md) * [附录六:资源链接](16_appendix/16.3_resources.md) - * [附录七:术语词表(出版统一版)](16_appendix/16.4_terminology.md) - * [附录八:出版清稿规范(图号与章节风格)](16_appendix/16.5_editorial_style.md) + * [附录七:术语词表 (出版统一版)](16_appendix/16.4_terminology.md) + * [附录八:出版清稿规范 (图号与章节风格)](16_appendix/16.5_editorial_style.md) diff --git a/_images/ECS.jpg b/_images/ECS.jpg deleted file mode 100644 index 734f94d..0000000 Binary files a/_images/ECS.jpg and /dev/null differ diff --git a/_images/aliyun-logo.png b/_images/aliyun-logo.png deleted file mode 100644 index 4700fec..0000000 Binary files a/_images/aliyun-logo.png and /dev/null differ diff --git a/_images/aws-logo.jpg b/_images/aws-logo.jpg deleted file mode 100644 index 1727347..0000000 Binary files a/_images/aws-logo.jpg and /dev/null differ diff --git a/_images/cover.jpg b/_images/cover.jpg deleted file mode 100644 index ad6fa32..0000000 Binary files a/_images/cover.jpg and /dev/null differ diff --git a/_images/cover.png b/_images/cover.png deleted file mode 100644 index 2515444..0000000 Binary files a/_images/cover.png and /dev/null differ diff --git a/_images/cover_small.jpg b/_images/cover_small.jpg deleted file mode 100644 index ab5af5e..0000000 Binary files a/_images/cover_small.jpg and /dev/null differ diff --git a/_images/docker_arch.png b/_images/docker_arch.png deleted file mode 100644 index 64df422..0000000 Binary files a/_images/docker_arch.png and /dev/null differ diff --git a/_images/docker_primer.png b/_images/docker_primer.png deleted file mode 100644 index 0a4294d..0000000 Binary files a/_images/docker_primer.png and /dev/null differ diff --git a/_images/docker_primer2.png b/_images/docker_primer2.png deleted file mode 100644 index 52c8c48..0000000 Binary files a/_images/docker_primer2.png and /dev/null differ diff --git a/_images/docker_primer4.jpg b/_images/docker_primer4.jpg deleted file mode 100644 index 1b2eec0..0000000 Binary files a/_images/docker_primer4.jpg and /dev/null differ diff --git a/_images/donate.jpeg b/_images/donate.jpeg deleted file mode 100644 index 6fcfa7a..0000000 Binary files a/_images/donate.jpeg and /dev/null differ diff --git a/_images/etcd_logo.png b/_images/etcd_logo.png deleted file mode 100644 index 2638ff3..0000000 Binary files a/_images/etcd_logo.png and /dev/null differ diff --git a/_images/k8s_architecture.png b/_images/k8s_architecture.png deleted file mode 100644 index fa39039..0000000 Binary files a/_images/k8s_architecture.png and /dev/null differ diff --git a/_images/kube-proxy.png b/_images/kube-proxy.png deleted file mode 100644 index 7ff19b8..0000000 Binary files a/_images/kube-proxy.png and /dev/null differ diff --git a/_images/kubernetes_design.jpg b/_images/kubernetes_design.jpg deleted file mode 100644 index d601d7a..0000000 Binary files a/_images/kubernetes_design.jpg and /dev/null differ diff --git a/_images/kubernetes_logo.png b/_images/kubernetes_logo.png deleted file mode 100644 index 3128630..0000000 Binary files a/_images/kubernetes_logo.png and /dev/null differ diff --git a/_images/network.png b/_images/network.png deleted file mode 100644 index fdf8928..0000000 Binary files a/_images/network.png and /dev/null differ diff --git a/_images/qcloud-logo.jpg b/_images/qcloud-logo.jpg deleted file mode 100644 index 7b987e7..0000000 Binary files a/_images/qcloud-logo.jpg and /dev/null differ diff --git a/_images/types-of-mounts.png b/_images/types-of-mounts.png deleted file mode 100644 index 5950036..0000000 Binary files a/_images/types-of-mounts.png and /dev/null differ diff --git a/_images/wordpress.png b/_images/wordpress.png deleted file mode 100644 index f7c026a..0000000 Binary files a/_images/wordpress.png and /dev/null differ diff --git a/check_dashes.py b/check_dashes.py new file mode 100644 index 0000000..8f4ddca --- /dev/null +++ b/check_dashes.py @@ -0,0 +1,21 @@ +import os +import re + +count = 0 +for root, dirs, files in os.walk("/Users/baohua/Github/books/docker_practice"): + if ".git" in root or "node_modules" in root: + continue + for file in files: + if file.endswith(".md"): + filepath = os.path.join(root, file) + with open(filepath, "r", encoding="utf-8") as f: + lines = f.readlines() + + for i, line in enumerate(lines): + # match optional spaces, then exactly one dash, then no space and no dash + m = re.match(r'^(\s*)-([^- \t\n].*)$', line) + if m: + print(f"{filepath}:{i+1}:{line.rstrip()}") + count += 1 + +print(f"Total found: {count}") diff --git a/check_project_rules.py b/check_project_rules.py new file mode 100644 index 0000000..a3930d9 --- /dev/null +++ b/check_project_rules.py @@ -0,0 +1,148 @@ +import os +import re +import argparse + +def check_file(filepath, verbose=False): + violations = [] + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + lines = content.split('\n') + + filename = os.path.basename(filepath) + is_readme = filename.lower() == 'readme.md' + is_summary = filename.lower() == 'summary.md' + is_section = re.match(r'^\d+\.\d+_.*\.md$', filename) + + # 1.1 Bold Text: No spaces inside the bold markers + for i, line in enumerate(lines): + if '** ' in line or ' **' in line: + # We must be careful: '** ' might be a bold start with space inside, but it could also be regular text. + # Let's use a simpler, line-bound regex line by line + if re.search(r'\*\*\s+[^*]+\*\*|\*\*[^*]+\s+\*\*', line): + violations.append(f"1.1 Bold Text: Space inside bold markers at line {i+1}") + + # 1.4 Trailing Newline + if not content.endswith('\n') or content.endswith('\n\n'): + if content: # ignore empty files + violations.append("1.4 Trailing Newline: File must end with exactly one newline character") + + headers = [] + for i, line in enumerate(lines): + m = re.match(r'^(#{1,6})\s+(.*)', line) + if m: + level = len(m.group(1)) + text = m.group(2) + headers.append({'line': i, 'level': level, 'text': text}) + + # 1.2 Header Spacing + if i + 1 < len(lines): + next_line = lines[i+1].strip() + if next_line != '': + violations.append(f"1.2 Header Spacing: Header at line {i+1} not followed by a blank line") + if i + 2 < len(lines): + if lines[i+1].strip() == '' and lines[i+2].strip() == '': + violations.append(f"1.2 Header Spacing: Header at line {i+1} followed by multiple blank lines") + + # 1.3 Header Hierarchy + for j in range(len(headers) - 1): + curr_level = headers[j]['level'] + next_level = headers[j+1]['level'] + if next_level > curr_level + 1: + violations.append(f"1.3 Header Hierarchy: Skipped header level from H{curr_level} to H{next_level} at line {headers[j+1]['line']+1}") + + # 2.2 File Header Levels + if headers: + first_header_level = headers[0]['level'] + if is_readme and first_header_level != 1: + violations.append("2.2 File Header Levels: README.md first header must be level 1") + if is_summary and first_header_level != 2: + violations.append("2.2 File Header Levels: SUMMARY.md first header must be level 2") + if is_section and first_header_level != 2: + violations.append("2.2 File Header Levels: Section file first header must be level 2") + + # 2.2 No English Parentheses in Headers unless very common terminologies + for h in headers: + text = h['text'] + i = h['line'] + if re.search(r'([A-Za-z\s]+)', text): + violations.append(f"2.2 No English Parentheses: Header at line {i+1} contains English in parentheses: {text}") + + # 2.3 Single Child Headers + for j in range(len(headers)): + level = headers[j]['level'] + children = 0 + for k in range(j+1, len(headers)): + if headers[k]['level'] <= level: + break + if headers[k]['level'] == level + 1: + children += 1 + if children == 1: + violations.append(f"2.3 Single Child Headers: Header at line {headers[j]['line']+1} has exactly 1 child") + + # 2.5 Bridge Text + for j in range(len(headers)): + level = headers[j]['level'] + child_line = -1 + for k in range(j+1, len(headers)): + if headers[k]['level'] <= level: + break + if headers[k]['level'] == level + 1: + child_line = headers[k]['line'] + break + if child_line != -1: + text_between = '\n'.join([l.strip() for l in lines[headers[j]['line']+1:child_line] if l.strip()]) + if not text_between: + violations.append(f"2.5 Bridge Text: Header at line {headers[j]['line']+1} is followed by a sub-header without introductory text") + + # 3.2 Content Introduction + in_code_block = False + for j, line in enumerate(lines): + if line.startswith('```'): + if not in_code_block: + for k in range(j-1, -1, -1): + if lines[k].strip(): + if lines[k].startswith('#'): + violations.append(f"3.2 Content Introduction: Code block at line {j+1} immediately follows a header") + break + in_code_block = not in_code_block + elif "![" in line and "](" in line: + for k in range(j-1, -1, -1): + if lines[k].strip(): + if lines[k].startswith('#'): + violations.append(f"3.2 Content Introduction: Image at line {j+1} immediately follows a header") + break + + return violations + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('-v', '--verbose', action='store_true') + args = parser.parse_args() + + md_files = [] + for root, dirs, files in os.walk('.'): + for f in files: + if f.endswith('.md') and '.git' not in root and 'node_modules' not in root and '.vuepress' not in root and 'book_rule.md' not in f and 'rules_result.txt' not in f: + md_files.append(os.path.join(root, f)) + + total_violations = 0 + for f in md_files: + try: + violations = check_file(f, args.verbose) + if args.verbose: + print(f"Scanned {f}") + if violations: + print(f"\\nViolations in {f}:") + for v in violations: + print(f" - {v}") + total_violations += len(violations) + except Exception as e: + print(f"Error reading {f}: {e}") + + if total_violations == 0: + print("No violations found!") + else: + print(f"\\nTotal violations: {total_violations}") + +if __name__ == '__main__': + main() diff --git a/checker.py b/checker.py new file mode 100644 index 0000000..b41fd3f --- /dev/null +++ b/checker.py @@ -0,0 +1,109 @@ +import os +import re + +def check_file(filepath): + issues = [] + try: + with open(filepath, 'r', encoding='utf-8') as f: + lines = f.readlines() + except Exception as e: + return [f"Could not read file: {e}"] + + in_code_block = False + + for i, line in enumerate(lines): + line_stripped = line.strip() + + # Code block tracking + if line_stripped.startswith('```'): + in_code_block = not in_code_block + + if in_code_block: + continue + + # 1. Full-width parentheses `(` `)` + if '(' in line or ')' in line: + if line_stripped.startswith('#'): + issues.append(f"Line {i+1}: Header contains full-width parentheses '(' or ')'") + else: + issues.append(f"Line {i+1}: Text contains full-width parentheses '(' or ')'") + + # 2. Missing intro text after headers + if line_stripped.startswith('#'): + j = i + 1 + while j < len(lines) and lines[j].strip() == '': + j += 1 + if j < len(lines): + next_line = lines[j].strip() + if next_line.startswith('```'): + issues.append(f"Line {i+1}: Header immediately followed by code block without text") + elif next_line.startswith('|') and len(next_line.split('|')) > 2: + issues.append(f"Line {i+1}: Header immediately followed by table without text") + elif next_line.startswith('#') and next_line.count('#') == line_stripped.count('#') + 1: + issues.append(f"Line {i+1}: Header immediately followed by sub-header (missing text between)") + elif next_line.startswith('!['): + issues.append(f"Line {i+1}: Header immediately followed by image without text") + + # 3. Missing blank line before list item + # Is this line a list item? + is_list_item = re.match(r'^(\s*[-*+]\s|\s*\d+\.\s)', line) + if is_list_item and i > 0: + prev_line = lines[i-1] + prev_line_stripped = prev_line.strip() + + # If prev line is not empty, and not already a list item, header, quote, or HTML comment + if prev_line_stripped and not prev_line_stripped.startswith('#') and not prev_line_stripped.startswith('>'): + if not re.match(r'^(\s*[-*+]\s|\s*\d+\.\s)', prev_line) and not prev_line_stripped.startswith('