diff --git a/01_introduction/1.3_why.md b/01_introduction/1.3_why.md index b849f78..6b6f7b4 100644 --- a/01_introduction/1.3_why.md +++ b/01_introduction/1.3_why.md @@ -179,7 +179,7 @@ flowchart TD end Redis["Redis 容器"] DB["PostgreSQL 容器"] - + Frontend --> API API --> Redis API --> DB diff --git a/02_basic_concept/2.1_image.md b/02_basic_concept/2.1_image.md index b39c161..5d1e87f 100644 --- a/02_basic_concept/2.1_image.md +++ b/02_basic_concept/2.1_image.md @@ -16,12 +16,12 @@ flowchart TD direction TB App["应用程序、工具、库、配置文件...
(这部分被打包成 Docker 镜像)"] end - + subgraph KernelSpace ["Linux 内核"] direction TB Kernel["容器共享宿主机的内核"] end - + UserSpace --- KernelSpace ``` 对于 Linux 而言,内核启动后会挂载 `root` 文件系统来提供用户空间支持。**Docker 镜像** 本质上就是一个 `root` 文件系统。 @@ -63,7 +63,7 @@ flowchart TD AppB_Trad["App B
Ubuntu 500MB"] AppC_Trad["App C
Ubuntu 500MB"] end - + subgraph DockerLayered ["Docker 分层方式 总计: 620MB ✅"] direction TB subgraph Apps ["应用层"] @@ -73,7 +73,7 @@ flowchart TD AppC["App C 40MB"] end Ubuntu["Ubuntu
(共享)500MB"] - + AppA --> Ubuntu AppB --> Ubuntu AppC --> Ubuntu @@ -98,7 +98,7 @@ flowchart TD Layer3["第 3 层: nginx 安装文件 (只读)"] Layer2["第 2 层: apt 缓存更新 (只读)"] Layer1["第 1 层: Ubuntu 基础系统 (只读)
← 基础镜像层"] - + Layer4 --> Layer3 --> Layer2 --> Layer1 ``` 每一层的特点: diff --git a/02_basic_concept/2.2_container.md b/02_basic_concept/2.2_container.md index bb55dbf..5fd9669 100644 --- a/02_basic_concept/2.2_container.md +++ b/02_basic_concept/2.2_container.md @@ -20,7 +20,7 @@ flowchart TD direction TB N1["• 共享系统资源
• 共享网络
• 共享文件系统"] end - + subgraph ContainerProcess ["容器进程 (运行在宿主机内核上)"] direction TB C1["• 独立进程空间
• 独立网络环境
• 独立文件系统
• 独立用户空间"] @@ -51,7 +51,7 @@ flowchart TD VMHW[Hardware] VMApp --> VMGuest --> V --> VMH --> VMHW end - + subgraph Container ["容器 (所有容器共享宿主机内核)"] direction TB subgraph CApp ["应用层"] @@ -89,7 +89,7 @@ flowchart TD ImageLayerN1["镜像第 N-1 层(只读)"] Dots["..."] ImageLayer1["镜像第 1 层(只读)
基础镜像层"] - + ContainerLayer --> ImageLayerN --> ImageLayerN1 --> Dots --> ImageLayer1 ``` @@ -157,11 +157,11 @@ stateDiagram-v2 Running --> Stopped : docker stop Running --> Paused : docker pause Paused --> Running : docker unpause - + Created --> Deleted : docker rm Stopped --> Deleted : docker rm Paused --> Deleted : docker rm - + Deleted --> [*] ``` 图 2-1:容器生命周期状态流转图 diff --git a/03_install/3.1_ubuntu.md b/03_install/3.1_ubuntu.md index 07e9c2a..ec42e8d 100644 --- a/03_install/3.1_ubuntu.md +++ b/03_install/3.1_ubuntu.md @@ -113,7 +113,7 @@ $ sudo systemctl start docker 默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。 > ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限** -> +> > 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。 > 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。 diff --git a/03_install/3.2_debian.md b/03_install/3.2_debian.md index d2c63b6..aa38526 100644 --- a/03_install/3.2_debian.md +++ b/03_install/3.2_debian.md @@ -104,7 +104,7 @@ $ sudo systemctl start docker 默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。 > ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限** -> +> > 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。 > 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。 diff --git a/03_install/3.3_fedora.md b/03_install/3.3_fedora.md index e07d078..5d0fd05 100644 --- a/03_install/3.3_fedora.md +++ b/03_install/3.3_fedora.md @@ -115,7 +115,7 @@ $ sudo systemctl start docker 默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。 > ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限** -> +> > 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。 > 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。 diff --git a/03_install/3.4_centos.md b/03_install/3.4_centos.md index 5ddbb7d..3a781d6 100644 --- a/03_install/3.4_centos.md +++ b/03_install/3.4_centos.md @@ -122,7 +122,7 @@ $ sudo systemctl start docker 默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。 > ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限** -> +> > 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。 > 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。 diff --git a/03_install/3.5_raspberry-pi.md b/03_install/3.5_raspberry-pi.md index fccece0..49d41b4 100644 --- a/03_install/3.5_raspberry-pi.md +++ b/03_install/3.5_raspberry-pi.md @@ -73,7 +73,7 @@ Traceback (most recent call last): File "/usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py", line 109, in __init__ self.reload_sourceslist() File "/usr/lib/python3/dist-packages/softwareproperties/SoftwareProperties.py", line 599, in reload_sourceslist - self.distro.get_sources(self.sourceslist) + self.distro.get_sources(self.sourceslist) File "/usr/lib/python3/dist-packages/aptsources/distro.py", line 91, in get_sources raise NoDistroTemplateException( aptsources.distro.NoDistroTemplateException: Error: could not find a distribution template for Raspbian/bullseye @@ -129,7 +129,7 @@ $ sudo systemctl start docker 默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。 > ⚠️ **安全警告:`docker` 用户组等同于 `root` 权限** -> +> > 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐,但这也意味着该用户可以轻易获取主机的最高 root 权限(例如通过挂载根目录运行容器)。 > 如果你在一个多用户共享的生产系统上配置,切勿随意将普通用户加入此组。此时,更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。 diff --git a/03_install/3.6_offline.md b/03_install/3.6_offline.md index bf1b845..494e26f 100644 --- a/03_install/3.6_offline.md +++ b/03_install/3.6_offline.md @@ -162,7 +162,7 @@ EOF ```bash ## 测试刚才的本地源,安装createrepo软件 -yum clean all +yum clean all yum install createrepo -y ``` diff --git a/04_image/4.3_rm.md b/04_image/4.3_rm.md index 77c9a86..2bad114 100644 --- a/04_image/4.3_rm.md +++ b/04_image/4.3_rm.md @@ -93,19 +93,19 @@ Docker 会检测镜像是否有容器依赖或其他标签指向,只有在确 ```mermaid flowchart TD Start(["docker rmi redis:alpine"]) --> Step1 - + subgraph Process ["删除流程"] direction TB Step1["1. Untag:移除 redis:alpine 标签"] --> Step2 - + Step2{"2. 检查是否还有其他标签指向此镜像"} Step2 -- "有" --> Keep1["只 Untag,不删除"] Step2 -- "无" --> Step3 - + Step3{"3. 检查是否有容器依赖"} Step3 -- "有" --> Error["报错,无法删除"] Step3 -- "无" --> Step4 - + Step4{"4. 从上到下逐层删除,检查每层是否被其他镜像使用"} Step4 -- "被使用" --> Keep2["保留该层"] Step4 -- "未使用" --> Delete["Deleted (删除该层)"] @@ -172,7 +172,7 @@ $ docker image prune -a --filter "until=168h" # 7天前 ```bash $ docker rmi nginx -Error: conflict: unable to remove repository reference "nginx" +Error: conflict: unable to remove repository reference "nginx" (must force) - container abc123 is using its referenced image ``` **解决方案**: diff --git a/04_image/4.7_internal.md b/04_image/4.7_internal.md index b478f23..06478d3 100644 --- a/04_image/4.7_internal.md +++ b/04_image/4.7_internal.md @@ -33,7 +33,7 @@ flowchart TD L3["镜像层 (只读, Read-only Image Layer)"] L2["镜像层 (只读, Read-only Image Layer)"] L1["基础镜像层 (只读, Base Image Layer)"] - + L4 --- L3 --- L2 --- L1 end Note["所有的写操作都在容器层这里"] -.-> L4 diff --git a/05_container/5.1_run.md b/05_container/5.1_run.md index 66b00c7..49fe108 100644 --- a/05_container/5.1_run.md +++ b/05_container/5.1_run.md @@ -62,14 +62,14 @@ root@af8bae53bdd3:/# exit # 退出容器 ```mermaid flowchart TD Cmd["docker run ubuntu:24.04 /bin/echo 'Hello'"] --> Step1 - + Step1{"1. 检查本地是否有 ubuntu:24.04 镜像"} Step1 -- 有 --> Step1_Yes["使用本地镜像"] Step1 -- 无 --> Step1_No["从 Registry 下载"] - + Step1_Yes --> Step2 Step1_No --> Step2 - + Step2["2. 创建容器
• 基于镜像的只读层
• 添加一层可读写层(容器存储层)"] --> Step3 Step3["3. 配置网络
• 创建虚拟网卡
• 分配 IP 地址
• 连接到 Docker 网桥"] --> Step4 Step4["4. 启动容器,执行指定命令"] --> Step5 diff --git a/05_container/5.3_stop.md b/05_container/5.3_stop.md index f785065..c629246 100644 --- a/05_container/5.3_stop.md +++ b/05_container/5.3_stop.md @@ -155,11 +155,11 @@ stateDiagram-v2 Running --> Stopped : docker stop Running --> Paused : docker pause Paused --> Running : docker unpause - + Created --> Deleted : docker rm Stopped --> Deleted : docker rm Paused --> Deleted : docker rm - + Deleted --> [*] ``` --- diff --git a/05_container/5.4_attach_exec.md b/05_container/5.4_attach_exec.md index 1027190..db30342 100644 --- a/05_container/5.4_attach_exec.md +++ b/05_container/5.4_attach_exec.md @@ -165,7 +165,7 @@ CONTAINER ID IMAGE STATUS NAMES ```bash $ docker attach myubuntu -root@243c32535da7:/# +root@243c32535da7:/# ## 按 Ctrl+P 然后 Ctrl+Q @@ -197,7 +197,7 @@ flowchart LR end NewProc["新进程"] -- 附加到 --> E_PID50 end - + subgraph Attach ["docker attach"] direction TB subgraph Container2 ["容器"] @@ -205,7 +205,7 @@ flowchart LR end MainProc["附加到主进程"] --> A_PID1 end - + note1["退出 bash 不影响 nginx"] note2["退出 bash 容器停止"] Container1 -.-> note1 diff --git a/07_dockerfile/7.11_user.md b/07_dockerfile/7.11_user.md index 62b07cc..8616486 100644 --- a/07_dockerfile/7.11_user.md +++ b/07_dockerfile/7.11_user.md @@ -21,7 +21,7 @@ flowchart LR R_C["容器内 root"] -- 可能逃逸 --> R_H["宿主机 root"] R_C -- 漏洞利用 --> R_Control["完全控制宿主机"] end - + subgraph NonRoot ["非 root 用户运行:"] direction TB NR_C["容器内普通用户"] -- 逃逸后 --> NR_H["宿主机普通用户"] diff --git a/07_dockerfile/7.8_volume.md b/07_dockerfile/7.8_volume.md index e3d16c0..1772e6f 100644 --- a/07_dockerfile/7.8_volume.md +++ b/07_dockerfile/7.8_volume.md @@ -25,7 +25,7 @@ flowchart LR Result1["容器删除 = 数据丢失"] Container1 ~~~ Result1 end - + subgraph UseVolume ["使用 VOLUME:"] direction TB Container2["容器存储层
(只读/无状态)"] diff --git a/08_data/8.1_volume.md b/08_data/8.1_volume.md index 66b0614..e1b6d27 100644 --- a/08_data/8.1_volume.md +++ b/08_data/8.1_volume.md @@ -37,7 +37,7 @@ graph TD Image[镜像层
ReadOnly] Writable --- Image end - + Lifecycle[生命周期 = 容器生命周期] -.-> Container Delete[容器删除] -->|导致| DataLost[数据丢失 ❌] ``` @@ -49,11 +49,11 @@ graph TD subgraph Container [容器] AppDir["/app/data"] end - + subgraph Volume [数据卷 my-data] Data[持久化数据] end - + AppDir == 挂载 ==> Volume Delete[容器删除] -.->|不会影响| Volume ``` diff --git a/08_data/8.2_bind-mounts.md b/08_data/8.2_bind-mounts.md index 04820b7..08517b8 100644 --- a/08_data/8.2_bind-mounts.md +++ b/08_data/8.2_bind-mounts.md @@ -9,11 +9,11 @@ flowchart LR subgraph Host ["宿主机"] Dir1["/home/user/code/"] end - + subgraph Container ["容器"] Dir2["/usr/share/nginx/html/"] end - + Dir1 <-->|Bind Mount| Dir2 ``` 目录结构(同一份文件): @@ -210,7 +210,7 @@ $ docker inspect mycontainer --format '{{json .Mounts}}' | jq ```bash $ docker run --mount type=bind,source=/not/exist,target=/app nginx -docker: Error response from daemon: invalid mount config for type "bind": +docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /not/exist ``` **解决**:确保源路径存在,或改用 `-v` (会自动创建) diff --git a/09_network/9.2_network_types.md b/09_network/9.2_network_types.md index fd20155..642c1a5 100644 --- a/09_network/9.2_network_types.md +++ b/09_network/9.2_network_types.md @@ -15,7 +15,7 @@ ghi789... none null local 各网络类型的特点和适用场景如下: | 网络类型 | 说明 | 适用场景 | -|---------|------|---------| +|---------|------|---------| | **bridge** | 默认类型,容器连接到虚拟网桥 | 大多数单机场景 | | **host** | 容器直接使用宿主机网络栈 | 需要最高网络性能时 | | **none** | 禁用网络 | 完全隔离的容器 | @@ -64,12 +64,12 @@ flowchart LR direction LR C1A["容器 A (172.17.0.2)"] --> D0A["docker0"] --> C1B["容器 B (172.17.0.3)"] end - + subgraph Comm2 ["访问外网"] direction LR C2A["容器 A (172.17.0.2)"] --> D0B["docker0"] --> Eth0A["eth0"] --> InternetA["互联网"] end - + subgraph Comm3 ["被外部访问,需端口映射"] direction LR Req["外部请求"] --> Eth0B["eth0"] --> D0C["docker0"] --> C3A["容器 A"] diff --git a/09_network/9.3_custom_network.md b/09_network/9.3_custom_network.md index d35d358..c2ae68c 100644 --- a/09_network/9.3_custom_network.md +++ b/09_network/9.3_custom_network.md @@ -7,7 +7,7 @@ 默认 bridge 网络存在以下局限,而自定义网络可以很好地解决这些问题: | 问题 | 自定义网络的优势 | -|------|-----------------| +|------|-----------------| | 只能用 IP 通信 | 支持容器名 DNS 解析 | | 所有容器在同一网络 | 更好的隔离性 | | 需要 --link (已废弃)| 原生支持服务发现 | diff --git a/09_network/9.6_network_isolation.md b/09_network/9.6_network_isolation.md index 3df6fbc..55bf97b 100644 --- a/09_network/9.6_network_isolation.md +++ b/09_network/9.6_network_isolation.md @@ -16,7 +16,7 @@ $ docker network create backend $ docker run -d --name web --network frontend nginx -## 容器 B 在 backend +## 容器 B 在 backend $ docker run -d --name db --network backend postgres @@ -62,13 +62,13 @@ graph TD Web1["Web 服务器 1"] Web2["Web 服务器 2"] end - + subgraph BackendNet ["backend 网络"] API["API 服务器"] DB["数据库"] Cache["Redis 缓存"] end - + LB --> Web1 LB --> Web2 Web1 -.-> API diff --git a/11_compose/11.5_compose_file.md b/11_compose/11.5_compose_file.md index 3ae9ecb..59d0369 100644 --- a/11_compose/11.5_compose_file.md +++ b/11_compose/11.5_compose_file.md @@ -459,7 +459,7 @@ services: - mysql_data:/var/lib/mysql volumes: - mysql_data: + mysql_data: ``` ### 11.5.33 其它指令 diff --git a/11_compose/11.6_django.md b/11_compose/11.6_django.md index 13e6820..caa8887 100644 --- a/11_compose/11.6_django.md +++ b/11_compose/11.6_django.md @@ -18,15 +18,15 @@ flowchart TD Port8000[":8000"] Django ~~~ Port8000 end - + subgraph DB ["db 服务"] direction TB Postgres["PostgreSQL
数据库"] end - + Django -- ":5432" --> Postgres end - + Browser["localhost:8000
(浏览器访问)"] Port8000 --> Browser ``` diff --git a/11_compose/11.7_rails.md b/11_compose/11.7_rails.md index 4e09869..a721c8a 100644 --- a/11_compose/11.7_rails.md +++ b/11_compose/11.7_rails.md @@ -18,15 +18,15 @@ flowchart TD Port3000[":3000"] Rails ~~~ Port3000 end - + subgraph DB ["db 服务"] direction TB Postgres["PostgreSQL
数据库"] end - + Rails -- ":5432" --> Postgres end - + Browser["localhost:3000"] Port3000 --> Browser ``` diff --git a/11_compose/11.8_wordpress.md b/11_compose/11.8_wordpress.md index 4749fe5..617bff2 100644 --- a/11_compose/11.8_wordpress.md +++ b/11_compose/11.8_wordpress.md @@ -27,7 +27,7 @@ services: image: mysql:8.0 container_name: wordpress_db restart: always - command: + command: # 使用原生密码认证(旧版 WP 兼容性) - --default-authentication-plugin=mysql_native_password diff --git a/12_implementation/12.2_namespace.md b/12_implementation/12.2_namespace.md index d837ada..a7eff9a 100644 --- a/12_implementation/12.2_namespace.md +++ b/12_implementation/12.2_namespace.md @@ -16,13 +16,13 @@ flowchart LR H4["PID 1234: nginx"] H5["PID 1235: nginx worker"] end - + subgraph Container ["容器内视角"] direction TB C1["PID 1: nginx
← 容器认为自己是 PID 1"] C2["PID 2: nginx worker"] end - + H4 -. "(实际是宿主机的 1234)" .- C1 ``` @@ -92,13 +92,13 @@ flowchart LR H1["eth0: 192.168.1.10
端口 80 可用"] H2["docker0: 172.17.0.1"] end - + subgraph Container ["容器"] direction TB C1["eth0: 172.17.0.2
端口 80 可用"] C2["(veth pair 连接)"] end - + H2 <--> C2 ``` diff --git a/12_implementation/12.3_cgroups.md b/12_implementation/12.3_cgroups.md index 422c7e8..8ebfdcd 100644 --- a/12_implementation/12.3_cgroups.md +++ b/12_implementation/12.3_cgroups.md @@ -17,7 +17,7 @@ flowchart LR B["容器 B、C 饥饿"] end end - + subgraph Limit ["有 cgroups 限制"] direction TB subgraph HostRes2 ["宿主机资源"] diff --git a/12_implementation/12.4_ufs.md b/12_implementation/12.4_ufs.md index 8aa0f94..9a4f55e 100644 --- a/12_implementation/12.4_ufs.md +++ b/12_implementation/12.4_ufs.md @@ -12,12 +12,12 @@ flowchart TD ContainerFS["容器看到的文件系统
/bin /etc /lib /usr /var /app /data"] UnionFS["UnionFS 联合挂载"] - + ContainerLayer["容器层 (读写) : /app/data/log.txt (新写入)"] ImageLayer3["镜像层3 (只读) : /app/app.py"] ImageLayer2["镜像层2 (只读) : /usr/local/bin/python"] ImageLayer1["镜像层1 (只读) : /bin /etc /lib (基础系统)"] - + ContainerFS --> UnionFS UnionFS --> ContainerLayer --> ImageLayer3 --> ImageLayer2 --> ImageLayer1 ``` @@ -68,7 +68,7 @@ flowchart LR B_C["容器层 (空)"] B_I["镜像层
/etc/nginx.conf"] end - + subgraph After ["修改后"] direction TB A_C["容器层
/etc/nginx.conf ← 复制到容器层后修改"] @@ -126,11 +126,11 @@ overlay2 是目前最推荐的存储驱动: flowchart TD Merged["merged (合并视图)
容器看到的完整文件系统"] OverlayFS["OverlayFS"] - + Upper["upper
(容器层)
读写"] Lower2["lower2
(镜像层)
只读"] Lower1["lower1
(基础层)
只读"] - + Merged --> OverlayFS OverlayFS --> Upper OverlayFS --> Lower2 diff --git a/12_implementation/summary.md b/12_implementation/summary.md index d88bfbe..23670d0 100644 --- a/12_implementation/summary.md +++ b/12_implementation/summary.md @@ -9,7 +9,7 @@ | **Union FS** | 分层存储 | overlay2 为推荐驱动,支持 Copy-on-Write | | Namespace | 隔离内容 | 一句话说明 | -|-----------|---------|-----------| +|-----------|---------|-----------| | PID | 进程 ID | 容器有自己的进程树 | | NET | 网络 | 容器有自己的 IP 和端口 | | MNT | 文件系统 | 容器有自己的根目录 | diff --git a/14_kubernetes_setup/14.2_kubeadm-docker.md b/14_kubernetes_setup/14.2_kubeadm-docker.md index c174149..9814532 100644 --- a/14_kubernetes_setup/14.2_kubeadm-docker.md +++ b/14_kubernetes_setup/14.2_kubeadm-docker.md @@ -5,7 +5,7 @@ > ⚠️ **强烈提示:Docker 与 Kubernetes 环境的时代分界** > > 自 Kubernetes v1.24 起,内置的 `dockershim` 组件已被正式移除。这意味着 **Kubernetes 不再将 Docker Engine 作为默认内置的容器运行时**。虽然 Docker 仍然是你本地构建、管理镜像的绝佳工具,但它已不再是 kubelet 的默认运行时选项。 -> +> > 因此,**强烈推荐** 读者直接参考同目录下的《[使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)](14.1_kubeadm.md)》作为主要的部署路线。 > > 本文档保留,主要用于历史环境维护或特殊需求场景:如果你必须在较新的 Kubernetes 集群中继续使用 Docker Engine 作为底层运行时,你必须理解 CRI 层机制,额外部署并配置第三方兼容层 `cri-dockerd`,同时在部署时手动补充 `--cri-socket` 等参数约束。