diff --git a/04_image/4.1_pull.md b/04_image/4.1_pull.md index 83d6d63..166dcec 100644 --- a/04_image/4.1_pull.md +++ b/04_image/4.1_pull.md @@ -13,24 +13,24 @@ 从镜像仓库获取镜像的命令是 `docker pull`: ```bash -docker pull [选项] [Registry地址/][命名空间/]仓库名[:标签|@摘要] +docker pull [选项] [Registry地址/]仓库名[:标签] ``` #### 镜像名称格式 -Docker 镜像名称通常由 Registry 地址、命名空间、仓库名和标签(或摘要)组成。其常见格式如下: +Docker 镜像名称由 Registry 地址、用户名、仓库名和标签组成。其标准格式如下: ```bash -docker.io/library/ubuntu:24.04 -────┬──── ─────┬──── ──┬─── ──┬── - │ │ │ │ -Registry地址 命名空间 仓库名 标签 - (可省略) (可省略) +docker.io / library / ubuntu : 24.04 +────┬──── ───┬─── ──┬─── ──┬── + │ │ │ │ +Registry地址 用户名 仓库名 标签 + (可省略) (可省略) ``` | 组成部分 | 说明 | 默认值 | |---------|------|--------| | Registry 地址 | 镜像仓库地址 | `docker.io` (Docker Hub)| -| 命名空间 | 镜像所属用户/组织;官方镜像常为 `library` | `library` (官方镜像)| +| 用户名 | 镜像所属用户/组织 | `library` (官方镜像)| | 仓库名 | 镜像名称 | 必须指定 | | 标签 | 版本标识 | `latest` | @@ -89,19 +89,19 @@ docker.io/library/ubuntu:24.04 #### 分层下载 -从输出可以看到,镜像是 **按层拉取** 的: +从输出可以看到,镜像是 **分层下载** 的: ```mermaid flowchart TD subgraph Image ["ubuntu:24.04 镜像"] direction TB - L3["第3层 c8299583700a
(拉取完成)"] - L2["第2层 be13a9d27eb8
(拉取完成)"] - L1["第1层 92dc2a97ff99
(拉取完成)"] + L3["第3层 c8299583700a
(已存在,跳过下载)"] + L2["第2层 be13a9d27eb8
(下载中... 完成)"] + L1["第1层 92dc2a97ff99
(下载中... 完成)"] L3 --- L2 --- L1 end ``` -如果本地已有相同的层,Docker 通常会显示 `Already exists`;本例中三层都显示 `Pull complete`,表示此次拉取流程都完成了相应的层处理。 +如果本地已有相同的层,Docker 会跳过下载,节省带宽和时间。 --- diff --git a/04_image/4.2_list.md b/04_image/4.2_list.md index c7dc266..821b203 100644 --- a/04_image/4.2_list.md +++ b/04_image/4.2_list.md @@ -46,21 +46,21 @@ Docker 镜像的大小可能与我们通常理解的文件大小有所不同, | 位置 | 显示大小 | 说明 | |------|---------|------| -| Registry / Docker Hub 页面 | 常见为压缩后的分发大小或单平台视角 | 便于传输与分发 | -| `docker image ls` | 本地镜像及其父层累计占用大小 | 更接近主机上的实际展开占用 | +| Docker Hub | 29MB | 压缩后的网络传输大小 | +| docker image ls | 78MB | 本地解压后的实际大小 | #### 实际磁盘占用 -由于镜像是分层存储,**只有基于相同父层构建** 的镜像才会共享相同层: +由于镜像是分层存储,不同镜像可能共享相同的层: ```bash -python:3.12-slim myapp:web myapp:worker - │ │ │ - └───────┬───────┘ │ - ▼ │ - 共享父层与依赖层 ◄──────────┘ +ubuntu:24.04 nginx:latest redis:latest + │ │ │ + └───────┬───────┘ │ + ▼ │ + 共享基础层 ◄───────────────────┘ ``` -因此,`docker image ls` 中各镜像大小之和通常会大于实际磁盘占用;共享层只会在磁盘上保存一次。 +因此,`docker image ls` 中各镜像大小之和 > 实际磁盘占用。 #### 查看实际空间占用 @@ -164,9 +164,9 @@ $ docker image prune ```bash $ docker images -a ``` -会显示默认隐藏的中间层和虚悬镜像,其中一部分可能来自构建过程并被其他镜像复用。 +会显示很多无标签镜像——这些是构建过程中产生的中间层,被其他镜像依赖。 -> ⚠️ 一般不要手动逐个处理这些无标签项。优先删除顶层镜像或使用 `docker image prune` 清理无用镜像,让 Docker 自行回收不再被引用的层。 +> ⚠️ 不要删除中间层镜像。它们是其他镜像的依赖,删除会导致上层镜像无法使用。删除顶层镜像时会自动清理不再需要的中间层。 --- diff --git a/04_image/4.3_rm.md b/04_image/4.3_rm.md index cbe8de5..3bcec72 100644 --- a/04_image/4.3_rm.md +++ b/04_image/4.3_rm.md @@ -19,7 +19,7 @@ $ docker image rm [选项] <镜像1> [<镜像2> ...] | 方式 | 说明 | 示例 | |------|------|------| -| **短 ID** | ID 的前几位,只要足够唯一即可 | `docker rmi 501` | +| **短 ID** | ID 的前几位 (通常 3-4 位)| `docker rmi 501` | | **长 ID** | 完整的镜像 ID | `docker rmi 501ad78535f0...` | | **镜像名:标签** | 仓库名和标签 | `docker rmi redis:7.0` | | **镜像摘要** | 精确的内容摘要 | `docker rmi nginx@sha256:...` | @@ -144,7 +144,7 @@ $ docker image prune -f $ docker image prune -a -## 只清理 24 小时前的未使用镜像 +## 保留最近 24 小时的 $ docker image prune -a --filter "until=24h" ``` @@ -152,17 +152,13 @@ $ docker image prune -a --filter "until=24h" #### 按条件删除 ```bash -## 先列出所有 redis 相关镜像引用 +## 删除所有 redis 镜像 -$ docker image ls --filter reference='redis*' +$ docker rmi $(docker images -q redis) -## 确认后,按仓库名:标签逐个删除需要的镜像 +## 删除 mongo:8.0 之前的所有镜像 -$ docker image rm redis:7 redis:7-alpine - -## 先列出所有比 mongo:8.0 更早创建的镜像 - -$ docker image ls --filter before=mongo:8.0 +$ docker rmi $(docker images -q -f before=mongo:8.0) ## 删除某个时间之前的镜像 @@ -221,25 +217,14 @@ Error: image has dependent child images ### 4.3.6 常用过滤条件 -不同命令支持的过滤条件并不相同。最常见的是 `docker image ls` 用来筛选查看对象,`docker image prune` 用来清理未使用镜像。 - -#### `docker image ls` 常用过滤条件 - | 过滤条件 | 说明 | 示例 | |---------|------|------| | `dangling=true` | 虚悬镜像 | `-f dangling=true` | -| `before=镜像` | 仅匹配比某镜像更早创建的镜像 | `-f before=mongo:3.2` | -| `since=镜像` | 仅匹配比某镜像更晚创建的镜像 | `-f since=mongo:3.2` | +| `before=镜像` | 在某镜像之前 | `-f before=mongo:3.2` | +| `since=镜像` | 在某镜像之后 | `-f since=mongo:3.2` | | `label=key=value` | 按标签过滤 | `-f label=version=1.0` | | `reference=pattern` | 按名称模式 | `-f reference='*:latest'` | -#### `docker image prune` 常用过滤条件 - -| 过滤条件 | 说明 | 示例 | -|---------|------|------| -| `until=<时间>` | 仅清理某个时间点之前创建的未使用镜像 | `--filter "until=24h"` | -| `label=key=value` | 仅清理带指定标签的未使用镜像 | `--filter "label=stage=temp"` | - --- ### 4.3.7 清理策略 diff --git a/04_image/4.5_build.md b/04_image/4.5_build.md index 469b29d..32af734 100644 --- a/04_image/4.5_build.md +++ b/04_image/4.5_build.md @@ -86,7 +86,7 @@ RUN echo '

Hello, Docker!

' > /usr/share/nginx/html/index.html $ docker build -t nginx:v3 . ``` -在当前版本的 Docker 中,`docker build` 默认会通过 Buildx 调用 BuildKit;但如果你显式设置了 `DOCKER_BUILDKIT=0`,或正在使用 Windows container mode,行为会回到 legacy builder。因此你更常看到的是 `[+] Building ...` 这类输出。为了帮助理解“每一步如何形成镜像历史”,下面仍展示一种较容易阅读的 legacy builder 经典输出形式: +在当前版本的 Docker 中,`docker build` 默认会通过 Buildx 调用 BuildKit,因此你更常看到的是 `[+] Building ...` 这类输出。为了帮助理解“每一步如何形成镜像历史”,下面仍展示一种较容易阅读的经典输出形式: ```bash Sending build context to Docker daemon 2.048 kB @@ -98,7 +98,7 @@ Step 2 : RUN echo '

Hello, Docker!

' > /usr/share/nginx/html/index.html Removing intermediate container 9cdc27646c7b Successfully built 44aa4490ce2c ``` -这段输出清晰展示了 legacy builder 的构建过程。在 `Step 2` 中,`RUN` 指令对应一次临时构建容器:执行命令、生成新的镜像层,再删除中间容器。默认的 BuildKit 后端通常不会把这些中间容器和中间镜像以这种形式暴露给用户,但“每条会改文件系统的指令都会生成新的层”这一点并没有改变。 +从命令的输出结果中,我们可以清晰的看到镜像的构建过程。在 `Step 2` 中,如同我们之前所说的那样,`RUN` 指令启动了一个容器 `9cdc27646c7b`,执行了所要求的命令,并最后提交了这一层 `44aa4490ce2c`,随后删除了所用到的这个容器 `9cdc27646c7b`。 这里我们使用了 `docker build` 命令进行镜像构建。其格式为: @@ -111,7 +111,7 @@ docker build [选项] <上下文路径/URL/-> 如果注意,会看到 `docker build` 命令最后有一个 `.`。`.` 表示当前目录,而 `Dockerfile` 就在当前目录,因此不少初学者以为这个路径是在指定 `Dockerfile` 所在路径,这么理解其实是不准确的。如果对应上面的命令格式,你可能会发现,这是在指定 **上下文路径**。那么什么是上下文呢? -首先要理解 `docker build` 的工作原理。今天的 `docker build` 通常会通过 Buildx 向 BuildKit 后端发起构建请求;无论后端运行在本机还是远端,位置参数指定的都是 **构建上下文**,也就是构建器可以访问到的文件集合。 +首先要理解 `docker build` 的工作原理。今天的 `docker build` 默认会通过 Buildx 向 BuildKit 后端发起构建请求;无论后端运行在本机还是远端,位置参数指定的都是 **构建上下文**,也就是构建器可以访问到的文件集合。 当我们进行镜像构建的时候,并非所有定制都会通过 `RUN` 指令完成,经常还需要把本地文件复制进镜像,比如通过 `COPY` 指令、`ADD` 指令等。因此,构建器必须能够访问这些文件,而它能访问的范围正是你传给 `docker build` 的那个上下文。 @@ -124,7 +124,7 @@ COPY ./package.json /app/ ``` 这并不是要复制执行 `docker build` 命令所在的目录下的 `package.json`,也不是复制 `Dockerfile` 所在目录下的 `package.json`,而是复制 **上下文 (context)** 目录下的 `package.json`。 -因此,`COPY` 这类指令中的源文件路径都应该以构建上下文为基准来理解。像 `COPY ../package.json /app` 这样的写法,前导的越界 `../` 会被规范化掉,最终仍只能在上下文根内解析;换句话说,构建器并不能借此读取上下文之外的宿主机文件。如果真的需要那些文件,应该先把它们放进上下文目录,或重新选择合适的上下文。 +因此,`COPY` 这类指令中的源文件路径都应该以构建上下文为基准来理解。对于 legacy builder,像 `COPY ../package.json /app` 这样的写法会直接报错;而在 BuildKit 下,前导的越界 `../` 会被剥离并重新解释为上下文内路径。无论是哪种情况,构建器都无法读取上下文之外的宿主机文件;如果真的需要那些文件,应该先把它们放进上下文目录,或重新选择合适的上下文。 现在就可以理解刚才的命令 `docker build -t nginx:v3 .` 中的这个 `.`,实际上是在指定上下文目录,而不是单纯指定 `Dockerfile` 所在目录。 diff --git a/04_image/4.6_other.md b/04_image/4.6_other.md index 6105748..01f3034 100644 --- a/04_image/4.6_other.md +++ b/04_image/4.6_other.md @@ -6,44 +6,44 @@ 格式:`docker import [选项] <文件>||- [<仓库名>[:<标签>]]` -压缩包可以是本地文件、远程 Web 文件,甚至是从标准输入中得到。压缩包将会在镜像 `/` 目录展开,并直接作为镜像的文件系统内容导入。若还需要补充 `CMD`、`ENV` 等元数据,可以通过 `--change` 追加;但它不支持 `RUN`、`COPY` 这类依赖构建上下文或会生成新文件系统层的 Dockerfile 指令。 +压缩包可以是本地文件、远程 Web 文件,甚至是从标准输入中得到。压缩包将会在镜像 `/` 目录展开,并直接作为镜像第一层提交。 -例如在 Debian/Ubuntu 主机上,可以先用 `debootstrap` 生成 Ubuntu 24.04(`noble`)的 rootfs,再通过标准输入导入为基础镜像: +比如我们想要创建一个 [OpenVZ](https://openvz.org) 的 Ubuntu 16.04 [模板](https://wiki.openvz.org/Download/template/precreated)的镜像: > **版本提示**:示例中的 Ubuntu 16.04 (Xenial) 已于 2021 年 4 月停止支持。如果用于生产环境,建议更新至 Ubuntu 22.04 LTS 或更新版本。 ```bash -$ sudo debootstrap noble noble > /dev/null -$ sudo tar -C noble -c . | docker import - ubuntu:noble +$ docker import \ + http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz \ + openvz/ubuntu:16.04 -sha256:81ec9a55a92a5618161f68ae691d092bf14d700129093158297b3d01593f4ee3 +Downloading from http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz +sha256:412b8fc3e3f786dca0197834a698932b9c51b69bd8cf49e100c35d38c9879213 ``` -这组命令会先得到 `noble/` 目录下的 rootfs,再把它打包后导入成镜像 `ubuntu:noble`。这种方式更适合制作自定义基础镜像或把现成的根文件系统快速封装成镜像。 +这条命令自动下载了 `ubuntu-16.04-x86_64.tar.gz` 文件,并且作为根文件系统展开导入,并保存为镜像 `openvz/ubuntu:16.04`。 导入成功后,我们可以用 `docker image ls` 看到这个导入的镜像: ```bash -$ docker image ls ubuntu +$ docker image ls openvz/ubuntu REPOSITORY TAG IMAGE ID CREATED SIZE -ubuntu noble 81ec9a55a92a 5 seconds ago 78MB +openvz/ubuntu 16.04 412b8fc3e3f7 55 seconds ago 505MB ``` -如果需要在导入时补上镜像元数据,可以配合 `--change` 选项: +如果我们查看其历史的话,会看到描述中有导入的文件链接: ```bash -$ docker import \ - --change 'CMD ["/bin/bash"]' \ - --change 'ENV LANG=C.UTF-8' \ - rootfs.tar \ - custom/base:noble +$ docker history openvz/ubuntu:16.04 +IMAGE CREATED CREATED BY SIZE COMMENT +f477a6e18e98 About a minute ago 214.9 MB Imported from http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz ``` ### 4.6.2 Docker 镜像的导入和导出 `docker save` 和 `docker load` -Docker 还提供了 `docker save` 和 `docker load` 命令,用以将镜像保存为一个归档文件,然后传输到另一个位置上,再加载进来。它们仍然适合离线备份、气隙环境分发,或在两台主机之间手工迁移镜像;如果是团队常规分发、版本管理和协作,优先使用 Docker Registry(无论是 Docker Hub 还是内网私有 Registry)会更合适。 +Docker 还提供了 `docker save` 和 `docker load` 命令,用以将镜像保存为一个文件,然后传输到另一个位置上,再加载进来。这是在没有 Docker Registry 时的做法,现在已经不推荐,镜像迁移应该直接使用 Docker Registry,无论是直接使用 Docker Hub 还是使用内网私有 Registry 都可以。 #### 保存镜像 -使用 `docker save` 命令可以将镜像保存为归档文件。归档中会包含镜像的父层以及所指定的标签;如果本地镜像仓库里已有多个平台变体,还可以通过 `--platform` 仅导出某个平台版本。 +使用 `docker save` 命令可以将镜像保存为归档文件。 比如我们希望保存这个 `alpine` 镜像。 @@ -57,7 +57,7 @@ alpine latest baa5d63471ea 5 weeks ago 保存镜像的命令为: ```bash -$ docker image save -o filename alpine +$ docker save alpine -o filename $ file filename filename: POSIX tar archive ``` @@ -68,16 +68,14 @@ filename: POSIX tar archive 若使用 `gzip` 压缩: ```bash -$ docker image save alpine | gzip > alpine-latest.tar.gz +$ docker save alpine | gzip > alpine-latest.tar.gz ``` -然后我们将 `alpine-latest.tar.gz` 文件复制到了另一个机器上,可以用下面这个命令加载镜像: +然后我们将 `alpine-latest.tar.gz` 文件复制到了到了另一个机器上,可以用下面这个命令加载镜像: ```bash -$ docker image load -i alpine-latest.tar.gz +$ docker load -i alpine-latest.tar.gz Loaded image: alpine:latest ``` -`docker load` 会恢复归档中的镜像和标签;同样地,在需要时也可以通过 `--platform` 只加载其中一个平台变体。 - 如果我们结合这两个命令以及 `ssh` 甚至 `pv` 的话,利用 Linux 强大的管道,我们可以写一个命令完成从一个机器将镜像迁移到另一个机器,并且带进度条的功能: ```bash diff --git a/04_image/4.7_internal.md b/04_image/4.7_internal.md index 1d5d648..7932870 100644 --- a/04_image/4.7_internal.md +++ b/04_image/4.7_internal.md @@ -40,8 +40,8 @@ flowchart TD ``` * **读取文件**:当容器需要读取文件时,Docker 会从最上层 (容器层) 开始向下层 (镜像层) 寻找,直到找到该文件为止。 -* **修改文件**:当容器需要修改某个文件时,底层存储后端会以 **写时复制 (Copy-on-Write,CoW)** 的方式记录变化。在 `overlay2` 这类联合文件系统后端上,常见表现是先把文件 `copy_up` 到容器层再修改;而 `btrfs`、`zfs` 等 CoW 文件系统的内部实现会有所不同。 -* **删除文件**:当容器删除某个文件时,Docker 不会直接改写下层只读层,而是由当前存储后端在上层记录“把下层内容屏蔽掉”的元数据。在 `overlay2` 中,这常表现为 whiteout 或 opaque directory;其他后端会用各自的机制达到相同效果。 +* **修改文件**:当容器需要修改某个文件时,Docker 会从下层镜像中将该文件复制到上层的容器层,然后对副本进行修改。这被称为 **写时复制 (Copy-on-Write,CoW)** 策略。 +* **删除文件**:当容器删除某个文件时,Docker 并不是真的去下层删除它 (因为下层是只读的),而是在容器层创建一个特殊的 “白障 (Whiteout)” 文件,用来标记该文件已被删除,从而在容器视图中隐藏它。 这就是为什么: @@ -58,10 +58,10 @@ Docker 镜像的每一层都有一个唯一的 ID,这个 ID 是根据该层的 ### 4.7.4 联合文件系统 -Docker 用“分层 + CoW”的思路来实现镜像与容器层叠加,但具体后端并不完全相同。`overlay2`、`aufs` 这类后端属于联合文件系统;`btrfs`、`zfs` 更接近具备快照/克隆能力的 CoW 文件系统;而在 Docker Engine 29.0 及之后的全新安装中,默认镜像后端已经变为 containerd image store,它使用 snapshotter 来管理这些层。 +Docker 使用联合文件系统 (Union FS) 与写时复制思路来实现这种分层挂载。传统的实现方式常见于 `overlay2`、`aufs`、`btrfs`、`zfs` 等存储驱动;而在 Docker Engine 29.0 及之后的全新安装中,默认镜像后端已经变为 containerd image store,它使用 snapshotter 来管理这些层。 > **版本背景**:Docker Engine 29.0(发布于 2024 年 2 月)是一个重要版本分界点,引入了 containerd image store 作为默认镜像存储后端。这对镜像管理、OCI 合规性和供应链安全都有深远影响。如果你的 Docker 版本低于 29.0,镜像存储仍使用传统的 classic store 路径。 -虽然底层实现细节不同,但它们都遵循“下层只读、上层记录差异”的总体模型;因此,无论你看到的是 `overlay2`、`zfs` 还是 containerd snapshotter,理解镜像层、容器层和写时复制的核心思想都是一样重要的。 +虽然底层实现细节不同,但它们都遵循上述的 **分层 + CoW** 模型;因此,无论你看到的是 `overlay2` 还是 containerd snapshotter,理解镜像层、容器层和写时复制的方式都是一样重要的。 > 想要深入了解 Overlay2 等文件系统的具体实现原理,包括 WorkDir、UpperDir、LowerDir 等底层细节,请阅读 **[第十二章 底层实现](../12_implementation/README.md)** 中的 **[联合文件系统](../12_implementation/12.4_ufs.md)** 章节。 diff --git a/07_dockerfile/7.16_references.md b/07_dockerfile/7.16_references.md index 8974492..821f18f 100644 --- a/07_dockerfile/7.16_references.md +++ b/07_dockerfile/7.16_references.md @@ -14,12 +14,20 @@ Dockerfile 中的常用指令包括: - **FROM**: 指定基础镜像,必须是第一条指令 - **RUN**: 在镜像中执行命令,用于安装软件包等 -- **WORKDIR**: 设置工作目录 -- **COPY/ADD**: 复制文件到镜像中 -- **EXPOSE**: 声明容器监听的端口 -- **ENV**: 设置环境变量 -- **ENTRYPOINT**: 容器启动时的入口点 +- **COPY**: 复制文件到镜像中 +- **ADD**: 更高级的复制文件(支持 URL 和自动解压) - **CMD**: 容器默认执行的命令 +- **ENTRYPOINT**: 容器启动时的入口点 +- **ENV**: 设置环境变量 +- **ARG**: 构建时的参数变量 +- **VOLUME**: 定义匿名卷挂载点 +- **EXPOSE**: 声明容器监听的端口 +- **WORKDIR**: 设置工作目录 +- **USER**: 指定运行容器时的用户 +- **HEALTHCHECK**: 配置容器健康检查 +- **ONBUILD**: 设置触发器指令,在子镜像构建时执行 +- **LABEL**: 为镜像添加元数据标签 +- **SHELL**: 指定 RUN 等指令使用的 shell ### 最佳实践建议 diff --git a/09_network/9.2_network_types.md b/09_network/9.2_network_types.md index 183f69e..642c1a5 100644 --- a/09_network/9.2_network_types.md +++ b/09_network/9.2_network_types.md @@ -21,7 +21,6 @@ ghi789... none null local | **none** | 禁用网络 | 完全隔离的容器 | | **overlay** | 跨主机网络 | Docker Swarm 集群 | | **macvlan** | 容器拥有独立 MAC 地址 | 需要直接接入物理网络 | -| **ipvlan** | 容器共享父接口 MAC 地址,拥有独立 IP | 云环境等限制 MAC 地址数量的场景 | ### 9.2.2 Bridge 网络:默认 diff --git a/09_network/9.7_advanced_networking.md b/09_network/9.7_advanced_networking.md index e530498..baf4dd9 100644 --- a/09_network/9.7_advanced_networking.md +++ b/09_network/9.7_advanced_networking.md @@ -53,7 +53,7 @@ docker network inspect my-overlay-net docker service create --name web \ --network my-overlay-net \ --replicas 3 \ - nginx + nginx # 确保与环境兼容的 Nginx 版本 # 单机环境下也可以让普通容器加入 attachable overlay 网络 docker run -d --name container1 --network my-overlay-net busybox sleep 1d @@ -111,14 +111,14 @@ docker run -d \ --dns 8.8.8.8 \ --dns 1.1.1.1 \ --dns-search example.com \ - nginx + nginx # 确保与环境兼容的 Nginx 版本 # DNS 选项 docker run -d \ --dns-option ndots:2 \ --dns-option timeout:1 \ --dns-option attempts:3 \ - nginx + nginx # 确保与环境兼容的 Nginx 版本 # 查看容器 DNS 配置 docker exec cat /etc/resolv.conf @@ -171,8 +171,8 @@ networks: docker network create mynet # 运行服务 -docker run -d --name web --network mynet nginx -docker run -d --name db --network mynet postgres +docker run -d --name web --network mynet nginx # 确保与环境兼容的 Nginx 版本 +docker run -d --name db --network mynet postgres # 确保与环境兼容的 PostgreSQL 版本 # 在其他容器中通过服务名访问 docker run -it --network mynet busybox sh diff --git a/11_compose/11.4_commands.md b/11_compose/11.4_commands.md index 5f5776f..e55aafc 100644 --- a/11_compose/11.4_commands.md +++ b/11_compose/11.4_commands.md @@ -26,7 +26,7 @@ Docker Compose 提供了丰富的命令来管理项目和容器。本节将详 **配置验证**: -- `docker compose config`:验证 compose.yaml (或 docker-compose.yml) 格式是否正确 +- `docker compose config`:验证 docker-compose.yml 格式是否正确 ### 11.4.1 命令对象与格式 diff --git a/11_compose/demo/django/docker-compose.yml b/11_compose/demo/django/docker-compose.yml index 47bbadf..7219cb6 100644 --- a/11_compose/demo/django/docker-compose.yml +++ b/11_compose/demo/django/docker-compose.yml @@ -5,11 +5,6 @@ services: image: postgres environment: POSTGRES_PASSWORD: 'postgres' - healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres"] - interval: 5s - timeout: 5s - retries: 5 web: build: . @@ -18,6 +13,3 @@ services: - .:/code ports: - "8000:8000" - depends_on: - db: - condition: service_healthy diff --git a/16_cloud/16.5_multicloud.md b/16_cloud/16.5_multicloud.md index 80a247c..6430a71 100644 --- a/16_cloud/16.5_multicloud.md +++ b/16_cloud/16.5_multicloud.md @@ -7,7 +7,7 @@ | 特性 | Google GKE | AWS EKS | Azure AKS | | :--- | :--- | :--- | :--- | | **版本更新** | 最快,通常是 K8s 新特性的首发地 | 相对保守,注重稳定性 | 跟随社区,更新速度适中 | -| **控制平面管理** | 全托管,自动升级,$0.10/h(有 Free Tier 抵扣)| 托管,标准支持 $0.10/h,延长支持 $0.60/h | 全托管,控制平面免费 | +| **控制平面管理** | 全托管,自动升级,$0.10/h(有 Free Tier 抵扣)| 托管,$0.10/h | 全托管,控制平面免费 | | **节点管理** | 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/17_ecosystem/17.6_containerd.md b/17_ecosystem/17.6_containerd.md index 754b626..ccf41c9 100644 --- a/17_ecosystem/17.6_containerd.md +++ b/17_ecosystem/17.6_containerd.md @@ -41,7 +41,7 @@ Kubernetes 作为一个容器编排系统,为了屏蔽底层不同容器运行 - 早期版本中,Kubernetes 默认使用 docker 作为运行时,通过一个名为 `dockershim` 的桥接组件对接 Docker,Docker 再对接 containerd。 - 随着 containerd 原生支持了 CRI 插件,Kubernetes 开始直接与 containerd 通信,去掉了 `dockershim` 和 `dockerd` 的中间层。这就是为什么从 Kubernetes 1.24+ 开始”弃用 Docker”引发了广泛关注,实际上 Kubernetes 只是弃用 `dockershim`,底层依然在使用从 Docker 基因中诞生的 containerd。参见 [Kubernetes 官方文档](https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd)。 -- containerd 2.0+ 移除了已弃用的 CRI v1alpha2 接口,仅保留 CRI v1(Kubernetes 1.26+ 仅支持 CRI v1)。containerd 2.3+ 是 2.x 系列首个 LTS 版本,支持从 1.7 LTS 直接升级,生产环境推荐使用。详见 [containerd 发布说明](https://github.com/containerd/containerd/releases)。 +- containerd 2.0+ 移除了已弃用的 CRI v1alpha2 接口,仅保留 CRI v1(Kubernetes 1.26+ 仅支持 CRI v1)。如果集群中仍有依赖 CRI v1alpha2 的组件,升级 containerd 2.x 前需先完成迁移。containerd 2.3+ 是 2.x 系列首个 LTS 版本,支持从 1.7 LTS 直接升级,生产环境推荐使用。详见 [containerd 发布说明](https://github.com/containerd/containerd/releases)。 ### 17.6.3 为什么直接使用 containerd? diff --git a/appendix/learning_roadmap.md b/appendix/learning_roadmap.md index 51e8a1e..3101c88 100644 --- a/appendix/learning_roadmap.md +++ b/appendix/learning_roadmap.md @@ -434,7 +434,7 @@ Kubernetes 进阶 (Week 24-36) - 题目数:55 道 - 时间限制:90 分钟 - 及格分数:73%(约 41 道题) -- 费用:$199 USD +- 费用:$165 USD - 有效期:3 年 考试内容比例: diff --git a/appendix/repo/mongodb.md b/appendix/repo/mongodb.md index 2627b1b..dbc7a1c 100644 --- a/appendix/repo/mongodb.md +++ b/appendix/repo/mongodb.md @@ -25,13 +25,13 @@ $ docker run --name some-mongo -d --network my-mongo-net mongo ```bash $ docker run --name some-app -d --network my-mongo-net application-that-uses-mongo ``` -或者通过 `mongosh`(MongoDB 6.0+ 已弃用 `mongo`,请使用 `mongosh`) +或者通过 `mongo` ```bash $ docker run -it --rm \ --network my-mongo-net \ mongo \ - sh -c 'exec mongosh "mongodb://some-mongo:27017/test"' + sh -c 'exec mongo "some-mongo:27017/test"' ``` ### Dockerfile diff --git a/appendix/repo/nodejs.md b/appendix/repo/nodejs.md index a99c33b..8f50b25 100644 --- a/appendix/repo/nodejs.md +++ b/appendix/repo/nodejs.md @@ -28,6 +28,8 @@ $ docker run -it --rm --name my-running-app my-nodejs-app ```bash $ docker run -it --rm \ --name my-running-script \ + # -v "$ ":/usr/src/myapp \ + --mount type=bind,src="$(pwd)",target=/usr/src/myapp \ -w /usr/src/myapp \ node:20-alpine \