diff --git a/01_introduction/1.1_quickstart.md b/01_introduction/1.1_quickstart.md
index 581443b..680b7bc 100644
--- a/01_introduction/1.1_quickstart.md
+++ b/01_introduction/1.1_quickstart.md
@@ -9,6 +9,7 @@
```html
Hello, Docker!
```
+
### 1.1.2 编写 Dockerfile
在同级目录下创建一个名为 `Dockerfile` (无后缀) 的文件:
@@ -17,6 +18,7 @@
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/index.html
```
+
### 1.1.3 构建镜像
打开终端,进入该目录,执行构建命令:
diff --git a/01_introduction/1.2_what.md b/01_introduction/1.2_what.md
index a2a0537..7be03b2 100644
--- a/01_introduction/1.2_what.md
+++ b/01_introduction/1.2_what.md
@@ -40,6 +40,7 @@ flowchart LR
end
A == 一致 ==> C
```
+
### 1.2.3 Docker vs 虚拟机
很多人第一次接触 Docker 时会问:**“这不就是虚拟机吗?”** 答案是:**不是,而且差别很大。**
diff --git a/01_introduction/1.3_why.md b/01_introduction/1.3_why.md
index c110c41..b849f78 100644
--- a/01_introduction/1.3_why.md
+++ b/01_introduction/1.3_why.md
@@ -33,6 +33,7 @@
├── Day 4:问老同事怎么配的,他也忘了
└── Day 5:终于能跑起来了!但不知道为什么……
```
+
#### 场景三:服务器迁移的恐惧
```bash
@@ -41,6 +42,7 @@
运维:"当时是一个已经离职的同事配的……"
所有人:😱
```
+
### 1.3.2 Docker 如何解决这些问题
Docker 的出现为上述问题提供了完美的解决方案。它通过 “一次构建,到处运行” 的核心理念,从根本上改变了软件交付的方式。
@@ -54,6 +56,7 @@ flowchart LR
test -- "有问题
反馈修改和更新" --> dev
test -- "没问题
发布" --> prod["生产环境"]
```
+
### 1.3.3 Docker 的核心优势
除了解决上述痛点,Docker 还拥有诸多显著的技术优势,包括环境一致性、秒级启动、高效的资源利用等。
@@ -76,6 +79,7 @@ $ docker compose up
...
```
+
#### 2. 秒级启动
传统虚拟机启动需要几分钟 (引导操作系统),而 Docker 容器启动通常只需要 **几秒甚至几百毫秒**。
@@ -126,6 +130,7 @@ flowchart TD
Server2 --- Containers
end
```
+
#### 4. 持续交付和部署
Docker 完美契合 DevOps 的工作流程:
@@ -182,6 +187,7 @@ flowchart TD
Worker --> DB
end
```
+
### 1.3.4 Docker 不适合的场景
笔者认为,技术选型要客观。Docker 并非银弹,以下场景可能不太适合:
diff --git a/02_basic_concept/2.1_image.md b/02_basic_concept/2.1_image.md
index c39ede0..b39c161 100644
--- a/02_basic_concept/2.1_image.md
+++ b/02_basic_concept/2.1_image.md
@@ -79,6 +79,7 @@ flowchart TD
AppC --> Ubuntu
end
```
+
#### 分层是如何工作的?
笔者用一个实际的 Dockerfile 来解释分层:
@@ -135,6 +136,7 @@ RUN apt-get update && \
## 在同一层完成安装、使用、清理
```
+
#### 查看镜像的分层
```bash
@@ -150,6 +152,7 @@ a6bd71f48f68 2 weeks ago CMD ["nginx" "-g" "daemon off;"] 0B
2 weeks ago COPY 30-tune-worker-processes.sh /docker-ent… 4.62kB
...
```
+
### 2.1.5 镜像的标识
Docker 镜像有多种标识方式:
@@ -172,6 +175,7 @@ ubuntu:24.04
nginx # 等同于 nginx:latest
```
+
#### 2. 镜像 ID:Content-Addressable 标识
每个镜像有一个基于内容计算的唯一 ID:
@@ -182,6 +186,7 @@ REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest a6bd71f48f68 2 weeks ago 187MB
ubuntu 24.04 ca2b0f26964c 3 weeks ago 78.1MB
```
+
#### 3. 镜像摘要
更精确的标识,基于镜像内容的 SHA256 哈希:
diff --git a/02_basic_concept/2.2_container.md b/02_basic_concept/2.2_container.md
index 9b0ef94..bb55dbf 100644
--- a/02_basic_concept/2.2_container.md
+++ b/02_basic_concept/2.2_container.md
@@ -92,6 +92,7 @@ flowchart TD
ContainerLayer --> ImageLayerN --> ImageLayerN1 --> Dots --> ImageLayer1
```
+
#### Copy-on-Write:写时复制
当容器需要修改镜像层中的文件时:
@@ -104,6 +105,7 @@ flowchart TD
读取文件:直接从镜像层读取(共享,高效)
修改文件:复制到容器层,然后修改(只有这个容器能看到修改)
```
+
#### ⚠️ 容器存储层的生命周期
> **笔者特别强调**:这是新手最容易踩的坑!**容器存储层与容器生命周期绑定。容器删除,数据就没了!**
@@ -122,6 +124,7 @@ $ docker rm abc123
## 数据丢了!没有任何办法恢复!
```
+
#### 正确的数据持久化方式
按照 Docker 最佳实践,容器存储层应该保持 **无状态**。需要持久化的数据应该使用:
@@ -190,6 +193,7 @@ $ docker unpause abc123 # 恢复
$ docker rm abc123 # 删除已停止的容器
$ docker rm -f abc123 # 强制删除运行中的容器
```
+
### 2.2.6 容器与进程的关系
> **核心概念**:容器的生命周期 = 主进程 (PID 1) 的生命周期
diff --git a/02_basic_concept/2.3_repository.md b/02_basic_concept/2.3_repository.md
index 71e2c19..de2480c 100644
--- a/02_basic_concept/2.3_repository.md
+++ b/02_basic_concept/2.3_repository.md
@@ -110,6 +110,7 @@ $ docker pull bitnami/redis # 第三方镜像
$ docker login
$ docker push username/myapp:v1.0
```
+
#### 其他公共 Registry
除了 Docker Hub,还有以下几个常见的公共 Registry:
@@ -160,6 +161,7 @@ $ docker push localhost:5000/myapp:v1.0
$ docker pull localhost:5000/myapp:v1.0
```
+
#### 企业级解决方案
官方 Registry 功能较为基础,企业环境常用以下方案:
@@ -225,6 +227,7 @@ $ docker push registry.example.com/myteam/myapp:v1.0
$ docker logout
```
+
### 2.3.7 镜像的安全性
在使用公共镜像或维护私有镜像时,安全性是不容忽视的重要环节。
@@ -245,6 +248,7 @@ redis # ✅ 官方
bitnami/redis # ⚠️ 需要评估
someuser/myapp # ⚠️ 需要评估
```
+
#### 镜像签名
当前更推荐使用 Sigstore / Notation 体系进行镜像签名与验证。`Docker Content Trust (DCT)` 已进入退场阶段,不建议作为新项目主方案。
@@ -265,6 +269,7 @@ $ cosign generate-key-pair
$ cosign sign --key cosign.key $IMAGE
$ cosign verify --key cosign.pub $IMAGE
```
+
#### 漏洞扫描
```bash
diff --git a/03_install/3.1_ubuntu.md b/03_install/3.1_ubuntu.md
index a41f7ed..07e9c2a 100644
--- a/03_install/3.1_ubuntu.md
+++ b/03_install/3.1_ubuntu.md
@@ -36,6 +36,7 @@ do
sudo apt remove $pkg;
done
```
+
### 3.1.2 使用 APT 安装
由于 `apt` 源使用 HTTPS 以确保软件下载过程中不被篡改。因此,我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书。
@@ -83,6 +84,7 @@ $ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io
```
+
### 3.1.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Ubuntu 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装:
@@ -105,6 +107,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
+
### 3.1.5 建立 docker 用户组
默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
diff --git a/03_install/3.2_debian.md b/03_install/3.2_debian.md
index 02594ac..d2c63b6 100644
--- a/03_install/3.2_debian.md
+++ b/03_install/3.2_debian.md
@@ -25,6 +25,7 @@ $ sudo apt-get remove docker \
docker-engine \
docker.io
```
+
### 3.2.2 使用 APT 安装
由于 apt 源使用 HTTPS 以确保软件下载过程中不被篡改。因此,我们首先需要添加使用 HTTPS 传输的软件包以及 CA 证书。
@@ -74,6 +75,7 @@ $ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
```
+
### 3.2.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Debian 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装:
@@ -96,6 +98,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
+
### 3.2.5 建立 docker 用户组
默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
diff --git a/03_install/3.3_fedora.md b/03_install/3.3_fedora.md
index 8c8abd7..e07d078 100644
--- a/03_install/3.3_fedora.md
+++ b/03_install/3.3_fedora.md
@@ -32,6 +32,7 @@ $ sudo dnf remove docker \
docker-engine-selinux \
docker-engine
```
+
### 3.3.2 使用 dnf 安装
使用 dnf 包管理器安装是推荐的方式,便于后续的更行和管理。
@@ -67,6 +68,7 @@ $ sudo dnf config-manager --set-enabled docker-ce-test
```bash
$ sudo dnf config-manager --set-disabled docker-ce-test
```
+
#### 安装 Docker
更新 `dnf` 软件源缓存,并安装 `docker-ce`。
@@ -84,6 +86,7 @@ docker-ce.x86_64 18.06.1.ce-3.fc28 docker-ce-stable
$ sudo dnf -y install docker-ce-18.06.1.ce
```
+
### 3.3.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Fedora 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装:
@@ -106,6 +109,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
+
### 3.3.5 建立 docker 用户组
默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
diff --git a/03_install/3.4_centos.md b/03_install/3.4_centos.md
index 6dfa4be..5ddbb7d 100644
--- a/03_install/3.4_centos.md
+++ b/03_install/3.4_centos.md
@@ -34,6 +34,7 @@ $ sudo yum remove docker \
docker-ce-cli \
containerd.io
```
+
### 3.4.2 使用 yum 安装
使用 yum/dnf 安装是管理 Docker 生命周期的标准方式。
@@ -64,6 +65,7 @@ $ sudo sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.r
```bash
$ sudo dnf config-manager --set-enabled docker-ce-test
```
+
#### 安装 Docker
更新 `dnf` 软件源缓存,并安装 `docker-ce`。
@@ -71,6 +73,7 @@ $ sudo dnf config-manager --set-enabled docker-ce-test
```bash
$ sudo dnf install docker-ce docker-ce-cli containerd.io
```
+
### 3.4.3 CentOS8 额外设置
CentOS 8/Stream 默认使用 `nftables`。Docker 在新版本中已提供 `nftables` 实验支持,但在一些环境下仍可能遇到兼容性问题。若你遇到容器网络异常,可以先切换回 `iptables` 后端:
@@ -89,6 +92,7 @@ $ firewall-cmd --permanent --zone=trusted --add-interface=docker0
$ firewall-cmd --reload
```
+
### 3.4.4 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,CentOS 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装:
@@ -112,6 +116,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
+
### 3.4.6 建立 docker 用户组
默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
@@ -192,6 +197,7 @@ EOF
```bash
$ sudo sysctl -p
```
+
### 3.4.10 参考文档
* [Docker 官方 CentOS 安装文档](https://docs.docker.com/engine/install/centos/)。
diff --git a/03_install/3.5_raspberry-pi.md b/03_install/3.5_raspberry-pi.md
index c98f389..fccece0 100644
--- a/03_install/3.5_raspberry-pi.md
+++ b/03_install/3.5_raspberry-pi.md
@@ -89,6 +89,7 @@ $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docke
# $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/raspbian $(lsb_release -cs) stable" | sudo tee -a /etc/apt/sources.list
```
+
#### 安装 Docker
更新 apt 软件包缓存,并安装 `docker-ce`。
@@ -98,6 +99,7 @@ $ sudo apt-get update
$ sudo apt-get install docker-ce
```
+
### 3.5.3 使用脚本自动安装
在测试或开发环境中 Docker 官方为了简化安装流程,提供了一套便捷的安装脚本,Raspberry Pi OS 系统上可以使用这套脚本安装,另外可以通过 `--mirror` 选项使用国内源进行安装:
@@ -121,6 +123,7 @@ $ sudo sh get-docker.sh --mirror Aliyun
$ sudo systemctl enable docker
$ sudo systemctl start docker
```
+
### 3.5.5 建立 docker 用户组
默认情况下,`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑,一般 Linux 系统上不会直接使用 `root` 用户。因此,更好的做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
diff --git a/03_install/3.6_offline.md b/03_install/3.6_offline.md
index 4e68de8..bf1b845 100644
--- a/03_install/3.6_offline.md
+++ b/03_install/3.6_offline.md
@@ -41,6 +41,7 @@ docker-ce.x86_64 3:19.03.2-3.el7 docker-ce-stable
docker-ce.x86_64 3:19.03.1-3.el7 docker-ce-stable
....
```
+
##### 下载到指定文件夹
```bash
@@ -74,6 +75,7 @@ Background downloading packages, then exiting:
Total 118 MB/s | 87 MB 00:00:00
exiting because "Download Only" specified
```
+
##### 复制到目标服务器之后进入文件夹安装:C-N
* 离线安装时,必须使用 rpm 命令不检查依赖的方式安装
@@ -81,6 +83,7 @@ exiting because "Download Only" specified
```bash
rpm -Uvh *.rpm --nodeps --force
```
+
##### 锁定软件版本:C-N
**下载锁定版本软件**
@@ -130,6 +133,7 @@ versionlock deleted: 1
```bash
sudo yum versionlock delete all
```
+
#### YUM 本地源服务器搭建安装 Docker
##### 挂载 ISO 镜像搭建本地 File 源
@@ -161,6 +165,7 @@ EOF
yum clean all
yum install createrepo -y
```
+
##### 根据本地文件搭建 BASE 网络源
```bash
@@ -183,6 +188,7 @@ createrepo /var/www/html/base/
systemctl enable httpd
systemctl start httpd
```
+
##### 下载 Docker-CE 镜像仓库
在有网络的服务器上下载 Docker-ce 镜像
@@ -202,6 +208,7 @@ mkdir /tmp/docker-ce/
reposync -r docker-ce-stable -p /tmp/docker-ce/
```
+
##### 创建仓库索引
把下载的 docker-ce 文件夹复制到离线的服务器
@@ -213,6 +220,7 @@ reposync -r docker-ce-stable -p /tmp/docker-ce/
createrepo /var/www/html/docker-ce/
```
+
##### YUM 客户端设置:C...N
```bash
@@ -239,6 +247,7 @@ proxy=_none_
EOF
```
+
##### Docker 安装:C...N
```bash
diff --git a/03_install/3.7_mac.md b/03_install/3.7_mac.md
index f23ad8a..43da3cd 100644
--- a/03_install/3.7_mac.md
+++ b/03_install/3.7_mac.md
@@ -18,6 +18,7 @@ Docker Desktop 为 Mac 用户提供了无缝的 Docker 体验。你可以选择
```bash
$ brew install --cask docker
```
+
#### 手动下载安装
如果需要手动下载,请点击以下[链接](https://desktop.docker.com/mac/main/amd64/Docker.dmg)下载 Docker Desktop for Mac。
@@ -63,6 +64,7 @@ $ docker run -d -p 80:80 --name webserver nginx
$ docker stop webserver
$ docker rm webserver
```
+
### 3.7.4 镜像加速
如果在使用过程中发现拉取 Docker 镜像十分缓慢,可以配置 Docker [国内镜像加速](3.9_mirror.md)。
diff --git a/03_install/3.8_windows.md b/03_install/3.8_windows.md
index 40fcd36..46bb8f2 100644
--- a/03_install/3.8_windows.md
+++ b/03_install/3.8_windows.md
@@ -22,6 +22,7 @@
```powershell
$ winget install Docker.DockerDesktop
```
+
### 3.8.3 在 WSL2 运行 Docker
若你的 Windows 版本为 Windows 10 专业版或家庭版 v1903 及以上版本可以使用 WSL2 运行 Docker,具体请查看 [Docker Desktop WSL 2 backend](https://docs.docker.com/docker-for-windows/wsl/)。
diff --git a/03_install/summary.md b/03_install/summary.md
index a506ea6..429668a 100644
--- a/03_install/summary.md
+++ b/03_install/summary.md
@@ -19,6 +19,7 @@ Docker 支持在多种平台上安装和使用,选择合适的安装方式是
$ docker version
$ docker run --rm hello-world
```
+
### 延伸阅读
- [镜像加速器](3.9_mirror.md):解决国内拉取镜像慢的问题
diff --git a/04_image/4.1_pull.md b/04_image/4.1_pull.md
index 1162e35..4d741fd 100644
--- a/04_image/4.1_pull.md
+++ b/04_image/4.1_pull.md
@@ -9,6 +9,7 @@
```bash
docker pull [选项] [Registry地址/]仓库名[:标签]
```
+
#### 镜像名称格式
Docker 镜像名称由 Registry 地址、用户名、仓库名和标签组成。其标准格式如下:
@@ -70,6 +71,7 @@ Digest: sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26
Status: Downloaded newer image for ubuntu:24.04
docker.io/library/ubuntu:24.04
```
+
#### 输出解读
| 输出内容 | 说明 |
@@ -180,6 +182,7 @@ $ docker images --digests ubuntu
REPOSITORY TAG DIGEST IMAGE ID
ubuntu 24.04 sha256:4bc3ae6596938cb0d9e5ac51a1152ec9dcac2a1c50829c74abd9c4361e321b26 ca2b0f26964c
```
+
#### 使用摘要拉取
用摘要拉取可确保获取完全相同的镜像:
diff --git a/04_image/4.2_list.md b/04_image/4.2_list.md
index 91bf5ea..6aacbdb 100644
--- a/04_image/4.2_list.md
+++ b/04_image/4.2_list.md
@@ -87,6 +87,7 @@ ubuntu 24.04 329ed837d508 78MB
ubuntu noble 329ed837d508 78MB
ubuntu 22.04 a1b2c3d4e5f6 72MB
```
+
#### 按仓库名和标签过滤
```bash
@@ -94,6 +95,7 @@ $ docker images ubuntu:24.04
REPOSITORY TAG IMAGE ID SIZE
ubuntu 24.04 329ed837d508 78MB
```
+
#### 使用过滤器 --filter
| 过滤条件 | 说明 | 示例 |
@@ -132,6 +134,7 @@ $ docker images
REPOSITORY TAG IMAGE ID SIZE
00285df0df87 342MB
```
+
#### 产生原因
1. **镜像重新构建**:新镜像使用了旧镜像的标签,旧镜像标签被移除
@@ -188,11 +191,13 @@ $ docker rmi $(docker images -q)
$ docker rmi $(docker images -q redis)
```
+
#### 显示完整 ID
```bash
$ docker images --no-trunc
```
+
#### 显示摘要
```bash
@@ -200,6 +205,7 @@ $ docker images --digests
REPOSITORY TAG DIGEST IMAGE ID
nginx latest sha256:b4f0e0bdeb5... e43d811ce2f4
```
+
#### 自定义格式
使用 Go 模板语法自定义输出:
@@ -220,6 +226,7 @@ redis latest 183MB
nginx latest 181MB
ubuntu 24.04 78MB
```
+
#### 可用模板字段
| 字段 | 说明 |
diff --git a/04_image/4.3_rm.md b/04_image/4.3_rm.md
index 70483ba..77c9a86 100644
--- a/04_image/4.3_rm.md
+++ b/04_image/4.3_rm.md
@@ -38,6 +38,7 @@ $ docker rmi 501
Untagged: redis:alpine
Deleted: sha256:501ad78535f0...
```
+
#### 使用镜像名删除
```bash
@@ -45,6 +46,7 @@ $ docker rmi redis:alpine
Untagged: redis:alpine
Deleted: sha256:501ad78535f0...
```
+
#### 使用摘要删除
摘要删除最精确,适用于 CI/CD 场景:
@@ -76,6 +78,7 @@ Deleted: sha256:501ad78535f015d88872e13fa87a828425117e3d28075d0c117932b05bf189b7
Deleted: sha256:96167737e29ca8e9d74982ef2a0dda76ed7b430da55e321c071f0dbff8c2899b
Deleted: sha256:32770d1dcf835f192cafd6b9263b7b597a1778a403a109e2cc2ee866f74adf23
```
+
#### Untagged vs Deleted
| 操作 | 含义 |
@@ -131,6 +134,7 @@ $ docker image prune
$ docker image prune -f
```
+
#### 删除所有未使用的镜像
```bash
@@ -142,6 +146,7 @@ $ docker image prune -a
$ docker image prune -a --filter "until=24h"
```
+
#### 按条件删除
```bash
@@ -182,6 +187,7 @@ $ docker rmi nginx
$ docker rmi -f nginx
```
+
#### 原因二:多个标签指向同一镜像
```bash
@@ -234,6 +240,7 @@ $ docker image prune -f
$ docker system prune -a
```
+
#### CI/CD 环境
```bash
@@ -241,6 +248,7 @@ $ docker system prune -a
$ docker image prune -a --filter "until=72h" -f
```
+
#### 查看空间占用
```bash
diff --git a/04_image/4.6_other.md b/04_image/4.6_other.md
index 5174c30..a1baa0e 100644
--- a/04_image/4.6_other.md
+++ b/04_image/4.6_other.md
@@ -34,6 +34,7 @@ $ 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 Registry,无论是直接使用 Docker Hub 还是使用内网私有 Registry 都可以。
diff --git a/05_container/5.1_run.md b/05_container/5.1_run.md
index 43dfb72..66b00c7 100644
--- a/05_container/5.1_run.md
+++ b/05_container/5.1_run.md
@@ -18,6 +18,7 @@
```bash
docker run [选项] 镜像 [命令] [参数...]
```
+
#### 最简单的例子
输出 “Hello World” 后容器自动终止:
@@ -53,6 +54,7 @@ root@af8bae53bdd3:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@af8bae53bdd3:/# exit # 退出容器
```
+
### 5.1.3 docker run 的完整流程
执行 `docker run` 时,Docker 在后台完成以下操作:
@@ -73,6 +75,7 @@ flowchart TD
Step4["4. 启动容器,执行指定命令"] --> Step5
Step5["5. 命令执行完毕,容器停止"]
```
+
### 5.1.4 常用启动选项
#### 基础选项
@@ -99,6 +102,7 @@ $ docker run -d -P nginx
$ docker run -d -p 127.0.0.1:8080:80 nginx
```
+
#### 数据卷挂载
```bash
@@ -114,6 +118,7 @@ $ docker run -v /host/path:/container/path nginx
$ docker run -v /host/path:/container/path:ro nginx
```
+
#### 环境变量
```bash
@@ -125,6 +130,7 @@ $ docker run -e MYSQL_ROOT_PASSWORD=secret mysql
$ docker run --env-file .env myapp
```
+
#### 资源限制
```bash
@@ -136,6 +142,7 @@ $ docker run -m 512m nginx
$ docker run --cpus=1.5 nginx
```
+
### 5.1.5 启动已终止容器
使用 `docker start` 重新启动已停止的容器:
@@ -155,6 +162,7 @@ $ docker start myubuntu
$ docker start -ai myubuntu
```
+
### 5.1.6 容器内进程的特点
容器内只运行指定的应用程序及其必需资源:
@@ -199,6 +207,7 @@ $ docker run -d nginx
$ docker run -d -p 80:80 nginx
```
+
#### Q:容器内修改的文件丢失
**原因**:未使用数据卷,数据保存在容器存储层
diff --git a/05_container/5.2_daemon.md b/05_container/5.2_daemon.md
index eb75698..4a8db71 100644
--- a/05_container/5.2_daemon.md
+++ b/05_container/5.2_daemon.md
@@ -92,6 +92,7 @@ $ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
77b2dc01fe0f ubuntu:24.04 /bin/sh -c 'while tr 2 minutes ago Up 1 minute agitated_wright
```
+
#### 查看容器输出日志
```bash
@@ -106,6 +107,7 @@ hello world
```bash
$ docker container logs -f 77b2dc01fe0f
```
+
#### 查看已停止的容器
```bash
@@ -130,6 +132,7 @@ $ docker run -d -p 3306:3306 mysql:8
$ docker run -d -p 6379:6379 redis
```
+
#### 2. 调试时先用前台模式
当容器启动有问题时,**去掉 `-d` 参数** 可以直接看到输出和错误:
@@ -139,6 +142,7 @@ $ docker run -d -p 6379:6379 redis
$ docker run myimage:latest
```
+
#### 3. 使用 --rm 自动清理
对于一次性任务,使用 `--rm` 参数让容器退出后自动删除:
@@ -151,6 +155,7 @@ Hello, World!
...
```
+
#### 4. 配合日志查看
```bash
@@ -170,6 +175,7 @@ $ docker logs -f myapp
$ docker logs -t myapp
```
+
### 5.2.6 常见问题排查
#### Q:容器启动后立即退出
diff --git a/05_container/5.3_stop.md b/05_container/5.3_stop.md
index d605729..f785065 100644
--- a/05_container/5.3_stop.md
+++ b/05_container/5.3_stop.md
@@ -21,6 +21,7 @@
```bash
$ docker stop 容器名或ID
```
+
#### 工作原理
```mermaid
@@ -29,6 +30,7 @@ flowchart TD
A --> B["2. 等待容器优雅退出 (默认 10 秒)"]
B --> C["3. 如果超时仍未退出,发送 SIGKILL 强制终止"]
```
+
#### 自定义超时时间
```bash
@@ -40,6 +42,7 @@ $ docker stop -t 30 mycontainer
$ docker stop -t 0 mycontainer
```
+
#### 停止多个容器
```bash
@@ -60,6 +63,7 @@ $ docker stop $(docker ps -q)
```bash
$ docker kill 容器名或ID
```
+
#### 与 stop 的区别
| 命令 | 信号 | 使用场景 |
@@ -127,6 +131,7 @@ $ docker start 容器名或ID
$ docker start -ai 容器名
```
+
#### 重启运行中的容器
```bash
@@ -166,11 +171,13 @@ stateDiagram-v2
```bash
$ docker stop $(docker ps -q)
```
+
#### 删除所有已停止的容器
```bash
$ docker container prune
```
+
#### 停止并删除所有容器
```bash
@@ -204,6 +211,7 @@ FROM node:22
CMD ["node", "server.js"]
```
+
#### Q:容器无法停止
```bash
diff --git a/05_container/5.4_attach_exec.md b/05_container/5.4_attach_exec.md
index f1c0e5a..1027190 100644
--- a/05_container/5.4_attach_exec.md
+++ b/05_container/5.4_attach_exec.md
@@ -35,6 +35,7 @@ $ docker exec -it 容器名 /bin/bash
$ docker exec -it 容器名 /bin/sh
```
+
#### 参数说明
| 参数 | 作用 |
@@ -67,6 +68,7 @@ $ docker ps
CONTAINER ID IMAGE STATUS NAMES
69d137adef7a ubuntu Up 2 minutes myubuntu
```
+
#### 执行单条命令
不进入交互模式,直接执行命令:
@@ -84,6 +86,7 @@ $ docker exec myubuntu cat /etc/nginx/nginx.conf
$ docker exec -u root myubuntu apt update
```
+
#### 只用 -i 不用 -t 的区别
```bash
@@ -112,6 +115,7 @@ root@69d137adef7a:/# # 有提示符
```bash
$ docker attach 容器名
```
+
#### 工作原理
`attach` 会附加到容器的 **主进程** (PID 1) 的标准输入输出:
@@ -126,6 +130,7 @@ flowchart LR
end
Attach["docker attach"] -->|"附加到这里"| P1
```
+
#### docker attach 示例
```bash
@@ -139,6 +144,7 @@ $ docker run -dit --name myubuntu ubuntu
$ docker attach myubuntu
root@243c32535da7:/#
```
+
#### ⚠️ 重要警告
**从 attach 会话中输入 `exit` 或按 `Ctrl+D` 会导致容器停止!**
@@ -224,6 +230,7 @@ $ docker exec myapp tail -f /var/log/app.log
$ docker exec myapp python manage.py migrate
```
+
#### 2. 生产环境避免进入容器
笔者建议:生产环境应尽量避免进入容器直接操作,而是通过:
@@ -261,6 +268,7 @@ $ docker debug myapp
```bash
$ docker exec -it myapp /bin/sh
```
+
#### Q:需要 root 权限
```bash
diff --git a/05_container/5.6_rm.md b/05_container/5.6_rm.md
index d0d348a..ace1829 100644
--- a/05_container/5.6_rm.md
+++ b/05_container/5.6_rm.md
@@ -27,6 +27,7 @@ $ docker rm 容器名或ID
$ docker rm mycontainer
mycontainer
```
+
#### 强制删除运行中的容器
```bash
@@ -73,6 +74,7 @@ Total reclaimed space: 150MB
$ docker container prune -f
```
+
#### 删除所有容器:包括运行中的
```bash
@@ -85,6 +87,7 @@ $ docker rm $(docker ps -aq)
$ docker rm -f $(docker ps -aq)
```
+
#### 按条件删除
```bash
@@ -158,6 +161,7 @@ $ docker container prune -f
$ docker system prune -f
```
+
#### 生产环境
```bash
@@ -171,6 +175,7 @@ $ docker run --rm ubuntu echo "Hello"
$ docker container prune --filter "until=168h" # 保留 7 天内的
```
+
#### 完整清理脚本
```bash
@@ -212,6 +217,7 @@ $ docker rm mycontainer
$ docker rm -f mycontainer
```
+
#### Q:删除后磁盘空间没释放
可能原因:
diff --git a/06_repository/6.1_dockerhub.md b/06_repository/6.1_dockerhub.md
index b15a2f1..81f364d 100644
--- a/06_repository/6.1_dockerhub.md
+++ b/06_repository/6.1_dockerhub.md
@@ -37,6 +37,7 @@ centos The official build of CentOS. 7000+ [OK]
```bash
$ docker pull nginx:alpine
```
+
#### 3. 推送镜像
需要先登录:
@@ -108,6 +109,7 @@ $ docker push username/myapp:v1
```bash
$ echo "dckr_pat_xxxxxxx" | docker login --username username --password-stdin
```
+
#### 3. 关注镜像漏洞
Docker Hub 会对官方镜像和付费用户的镜像进行安全扫描。在镜像标签页可以看到漏洞扫描结果。
diff --git a/06_repository/6.2_registry.md b/06_repository/6.2_registry.md
index 3c1f2dc..4f91d3c 100644
--- a/06_repository/6.2_registry.md
+++ b/06_repository/6.2_registry.md
@@ -25,6 +25,7 @@ $ docker run -d \
-v /opt/data/registry:/var/lib/registry \
registry
```
+
### 6.2.2 在私有仓库上传、搜索、下载镜像
创建好私有仓库之后,就可以使用 `docker tag` 来标记一个镜像,然后推送它到仓库。例如私有仓库地址为 `127.0.0.1:5000`。
@@ -86,6 +87,7 @@ $ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
127.0.0.1:5000/ubuntu:latest latest ba5877dc9bec 6 weeks ago 192.7 MB
```
+
### 6.2.3 配置非 https 仓库地址
如果你不想使用 `127.0.0.1:5000` 作为仓库地址,比如想让本网段的其他主机也能把镜像推送到私有仓库。你就得把例如 `192.168.199.100:5000` 这样的内网地址作为私有仓库地址,这时你会发现无法成功推送镜像。
diff --git a/06_repository/6.3_registry_auth.md b/06_repository/6.3_registry_auth.md
index e06979f..5f2b0f0 100644
--- a/06_repository/6.3_registry_auth.md
+++ b/06_repository/6.3_registry_auth.md
@@ -114,6 +114,7 @@ health:
interval: 10s
threshold: 3
```
+
### 6.3.3 生成 http 认证文件
```bash
@@ -143,6 +144,7 @@ services:
volumes:
registry-data:
```
+
### 6.3.5 修改 Hosts 文件
编辑 `/etc/hosts`
@@ -150,6 +152,7 @@ volumes:
```bash
127.0.0.1 docker.domain.com
```
+
### 6.3.6 启动
```bash
diff --git a/06_repository/6.4_nexus3_registry.md b/06_repository/6.4_nexus3_registry.md
index d0dfad9..9406152 100644
--- a/06_repository/6.4_nexus3_registry.md
+++ b/06_repository/6.4_nexus3_registry.md
@@ -107,6 +107,7 @@ server {
error_page 500 502 503 504 /50x.html;
}
```
+
### 6.4.5 Docker 主机访问镜像仓库
如果不启用 SSL 加密可以通过[前面章节](6.2_registry.md)的方法添加非 https 仓库地址到 Docker 的配置文件中然后重启 Docker。
diff --git a/07_dockerfile/7.10_workdir.md b/07_dockerfile/7.10_workdir.md
index 1645132..b2956a2 100644
--- a/07_dockerfile/7.10_workdir.md
+++ b/07_dockerfile/7.10_workdir.md
@@ -30,6 +30,7 @@ COPY . . # 复制到 /app/
RUN cd /app
RUN echo "hello" > world.txt # 文件在根目录!
```
+
#### 原因分析
```dockerfile
@@ -110,6 +111,7 @@ RUN npm install
COPY . .
CMD ["node", "server.js"]
```
+
#### 2. 使用绝对路径
```docker
@@ -121,6 +123,7 @@ WORKDIR /app
WORKDIR app
```
+
#### 3. 不要用 RUN cd
```docker
@@ -133,6 +136,7 @@ RUN cd /app && echo "hello" > world.txt
WORKDIR /app
RUN echo "hello" > world.txt
```
+
#### 4. 适时重置 WORKDIR
```docker
diff --git a/07_dockerfile/7.11_user.md b/07_dockerfile/7.11_user.md
index f49df69..62b07cc 100644
--- a/07_dockerfile/7.11_user.md
+++ b/07_dockerfile/7.11_user.md
@@ -55,6 +55,7 @@ USER appuser
CMD ["node", "server.js"]
```
+
#### 使用 UID/GID
```docker
@@ -80,6 +81,7 @@ USER nonexistent
RUN useradd -r -s /bin/false appuser
USER appuser
```
+
#### 创建用户的方式
**Debian/Ubuntu**:
@@ -139,6 +141,7 @@ chown -R redis:redis /data
exec gosu redis "$@"
```
+
#### 为什么不用 su/sudo
| 问题 | su/sudo | gosu |
@@ -208,6 +211,7 @@ CMD ["myapp"]
CMD ["myapp"] # 以 root 运行
```
+
#### 2. 使用固定 UID/GID
便于在宿主机和容器间共享文件:
@@ -219,6 +223,7 @@ RUN addgroup -g 1000 -S appgroup && \
adduser -u 1000 -S -G appgroup appuser
USER 1000:1000
```
+
#### 3. 多阶段构建中的 USER
```docker
@@ -252,6 +257,7 @@ permission denied: '/app/data.log'
```docker
RUN mkdir -p /app/data && chown appuser:appuser /app/data
```
+
#### Q:无法绑定低于 1024 的端口
非 root 用户无法绑定 80、443 等端口。
diff --git a/07_dockerfile/7.12_healthcheck.md b/07_dockerfile/7.12_healthcheck.md
index 0598474..e71945a 100644
--- a/07_dockerfile/7.12_healthcheck.md
+++ b/07_dockerfile/7.12_healthcheck.md
@@ -40,6 +40,7 @@ RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -fs http://localhost/ || exit 1
```
+
#### 命令返回值
- `0`:成功 (healthy)
@@ -82,6 +83,7 @@ HEALTHCHECK CMD curl -f http://localhost/ || exit 1
HEALTHCHECK CMD wget -q --spider http://localhost/ || exit 1
```
+
#### 数据库
```docker
@@ -93,6 +95,7 @@ HEALTHCHECK CMD mysqladmin ping -h localhost || exit 1
HEALTHCHECK CMD redis-cli ping || exit 1
```
+
#### 自定义脚本
```docker
@@ -178,6 +181,7 @@ $ docker inspect --format '{{json .State.Health}}' mycontainer | jq
HEALTHCHECK --start-period=60s CMD curl -f http://localhost/ || exit 1
```
+
#### 4. 只检查核心依赖
健康检查应主要关注 **当前服务** 是否可用,而不是检查其下游依赖 (数据库等)。下游依赖的检查应由应用逻辑处理。
diff --git a/07_dockerfile/7.13_onbuild.md b/07_dockerfile/7.13_onbuild.md
index 8c8fe3f..6d9875e 100644
--- a/07_dockerfile/7.13_onbuild.md
+++ b/07_dockerfile/7.13_onbuild.md
@@ -76,6 +76,7 @@ FROM 基础镜像 ──build──> 读取基础镜像触发器 ──> 执行
ONBUILD COPY requirements.txt ./
ONBUILD RUN pip install -r requirements.txt
```
+
#### 2. 自动编译代码
```docker
@@ -84,6 +85,7 @@ ONBUILD RUN pip install -r requirements.txt
ONBUILD COPY . .
ONBUILD RUN go build -o app main.go
```
+
#### 3. 处理静态资源
```docker
@@ -127,6 +129,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/
node:20-onbuild
python:3.12-onbuild
```
+
#### 2. 避免执行耗时操作
尽量不要在 `ONBUILD` 中执行过于耗时或不确定的操作 (如更新系统软件),这会让子镜像构建变得缓慢且不可控。
diff --git a/07_dockerfile/7.14_label.md b/07_dockerfile/7.14_label.md
index 4517a8d..c7a7303 100644
--- a/07_dockerfile/7.14_label.md
+++ b/07_dockerfile/7.14_label.md
@@ -26,6 +26,7 @@ LABEL = = ...
LABEL version="1.0"
LABEL description="这是一个 Web 应用服务器"
```
+
#### 定义多个标签:推荐
```docker
@@ -119,6 +120,7 @@ $ docker inspect nginx --format '{{json .Config.Labels}}' | jq
"maintainer": "NGINX Docker Maintainers "
}
```
+
#### 过滤器
可以使用标签过滤镜像:
diff --git a/07_dockerfile/7.15_shell.md b/07_dockerfile/7.15_shell.md
index c953aca..d3b2c2b 100644
--- a/07_dockerfile/7.15_shell.md
+++ b/07_dockerfile/7.15_shell.md
@@ -31,6 +31,7 @@ SHELL ["/bin/bash", "-c"]
RUN echo {a..z}
```
+
#### 2. 增强错误处理
默认情况下,管道命令 `cmd1 | cmd2` 只要 `cmd2` 成功,整个指令就视为成功。这可能掩盖构建错误。
@@ -51,6 +52,7 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN wget -O - https://invalid-url | tar xz
```
+
#### 3. Windows 环境
在 Windows 容器中,经常需要在 `cmd` 和 `powershell` 之间切换。
@@ -122,6 +124,7 @@ RUN echo "Using sh again"
```docker
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
```
+
#### 2. 明确意图
如果由于脚本需求必须更改 shell,最好在 Dockerfile 中显式声明,而不是依赖默认行为。
diff --git a/07_dockerfile/7.17_multistage_builds.md b/07_dockerfile/7.17_multistage_builds.md
index 5b59282..49e5ad4 100644
--- a/07_dockerfile/7.17_multistage_builds.md
+++ b/07_dockerfile/7.17_multistage_builds.md
@@ -46,6 +46,7 @@ CMD ["./app"]
```bash
$ docker build -t go/helloworld:1 -f Dockerfile.one .
```
+
### 7.17.2 分散到多个 Dockerfile
另一种方式,就是我们事先在一个 `Dockerfile` 将项目及其依赖库编译测试打包好后,再将其拷贝到运行环境中,这种方式需要我们编写两个 `Dockerfile` 和一些编译脚本才能将其两个阶段自动整合起来,这种方式虽然可以很好地规避第一种方式存在的风险,但明显部署过程较复杂。
@@ -110,6 +111,7 @@ REPOSITORY TAG IMAGE ID CREATED SIZE
go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
```
+
### 7.17.3 使用多阶段构建
为解决以上问题,Docker v17.05 开始支持多阶段构建 (`multistage builds`)。使用多阶段构建我们就可以很容易解决前面提到的问题,并且只需要编写一个 `Dockerfile`:
@@ -168,6 +170,7 @@ FROM golang:alpine as builder
```bash
$ docker build --target builder -t username/imagename:tag .
```
+
### 7.17.5 构建时从其他镜像复制文件
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件,我们也可以复制任意镜像中的文件。
diff --git a/07_dockerfile/7.18_multistage_builds_laravel.md b/07_dockerfile/7.18_multistage_builds_laravel.md
index 7374604..c4b9649 100644
--- a/07_dockerfile/7.18_multistage_builds_laravel.md
+++ b/07_dockerfile/7.18_multistage_builds_laravel.md
@@ -54,6 +54,7 @@ server {
}
}
```
+
### 7.18.2 前端构建
第一阶段进行前端构建。
@@ -74,6 +75,7 @@ RUN set -x ; cd /app \
&& mkdir -p public \
&& npm run production
```
+
### 7.18.3 安装 Composer 依赖
第二阶段安装 Composer 依赖。
@@ -93,6 +95,7 @@ RUN set -x ; cd /app \
--no-scripts \
--prefer-dist
```
+
### 7.18.4 整合以上阶段所生成的文件
第三阶段对以上阶段生成的文件进行整合。
@@ -118,6 +121,7 @@ RUN set -x ; cd ${LARAVEL_PATH} \
&& chmod -R 777 storage \
&& php artisan package:discover
```
+
### 7.18.5 最后一个阶段构建 NGINX 镜像
```docker
@@ -128,6 +132,7 @@ ARG LARAVEL_PATH=/app/laravel
COPY laravel.conf /etc/nginx/conf.d/
COPY --from=laravel ${LARAVEL_PATH}/public ${LARAVEL_PATH}/public
```
+
### 7.18.6 构建 Laravel 及 Nginx 镜像
使用 `docker build` 命令构建镜像。
@@ -137,6 +142,7 @@ $ docker build -t my/laravel --target=laravel .
$ docker build -t my/nginx --target=nginx .
```
+
### 7.18.7 启动容器并测试
新建 Docker 网络
diff --git a/07_dockerfile/7.1_run.md b/07_dockerfile/7.1_run.md
index 03acf58..5308458 100644
--- a/07_dockerfile/7.1_run.md
+++ b/07_dockerfile/7.1_run.md
@@ -55,6 +55,7 @@ RUN apt-get update && \
apt-get install -y nginx && \
rm -rf /var/lib/apt/lists/*
```
+
#### 2. 清理缓存
在安装完软件后,立即清除缓存,可以显著减小镜像体积。
@@ -103,6 +104,7 @@ RUN touch hello.txt
WORKDIR /app
RUN touch hello.txt
```
+
#### Q:环境变量不生效?
```docker
@@ -136,6 +138,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
RUN --mount=type=cache,target=/go/pkg/mod \
go build -o app
```
+
#### 2. 挂载密钥
安全地使用 SSH 密钥或 Token,而不将其记录在镜像中。
diff --git a/07_dockerfile/7.2_copy.md b/07_dockerfile/7.2_copy.md
index 84f813f..699e5de 100644
--- a/07_dockerfile/7.2_copy.md
+++ b/07_dockerfile/7.2_copy.md
@@ -23,6 +23,7 @@ COPY package.json /app/
COPY config.json /app/settings.json
```
+
#### 复制多个文件
```docker
@@ -35,6 +36,7 @@ COPY package.json package-lock.json /app/
COPY *.json /app/
COPY src/*.js /app/src/
```
+
#### 复制目录
```docker
@@ -77,6 +79,7 @@ COPY app[0-9].js /app/ # app0.js ~ app9.js
```docker
COPY app.js /usr/src/app/
```
+
#### 相对路径:基于 WORKDIR
```docker
@@ -84,6 +87,7 @@ WORKDIR /app
COPY package.json ./ # 复制到 /app/package.json
COPY src/ ./src/ # 复制到 /app/src/
```
+
#### 自动创建目录
如果目标目录不存在,Docker 会自动创建:
@@ -174,6 +178,7 @@ RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
```
+
#### 使用 --link 优化缓存
```docker
@@ -227,6 +232,7 @@ COPY . .
COPY . .
RUN npm install
```
+
#### 2. 使用 .dockerignore
```docker
@@ -238,6 +244,7 @@ COPY . .
...
```
+
#### 3. 明确复制路径
```docker
diff --git a/07_dockerfile/7.3_add.md b/07_dockerfile/7.3_add.md
index ac951de..d604063 100644
--- a/07_dockerfile/7.3_add.md
+++ b/07_dockerfile/7.3_add.md
@@ -51,6 +51,7 @@ ADD 会识别并解压以下格式:
FROM scratch
ADD ubuntu-noble-core-cloudimg-amd64-root.tar.gz /
```
+
#### 解压过程
```bash
@@ -76,6 +77,7 @@ app.tar.gz 包含: /app/ 目录结果:
ADD https://example.com/app.zip /app/app.zip
```
+
#### 为什么不推荐
| 问题 | 说明 |
@@ -127,6 +129,7 @@ ADD rootfs.tar.gz /
ADD dist.tar.gz /app/
```
+
#### ❌ 不适合使用 ADD
```docker
@@ -180,6 +183,7 @@ ADD app.tar.gz /app/
COPY . /app/
```
+
#### 2. 仅在需要解压时使用 ADD
```docker
@@ -187,6 +191,7 @@ COPY . /app/
ADD app.tar.gz /app/
```
+
#### 3. 不要用 ADD 下载文件
```docker
@@ -198,6 +203,7 @@ ADD https://example.com/file.tar.gz /tmp/
RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app
```
+
#### 4. 解压后清理
```docker
diff --git a/07_dockerfile/7.4_cmd.md b/07_dockerfile/7.4_cmd.md
index 4430d89..ec6f9e4 100644
--- a/07_dockerfile/7.4_cmd.md
+++ b/07_dockerfile/7.4_cmd.md
@@ -111,6 +111,7 @@ CMD ["/bin/bash"] + cat /etc/os-release
CMD service nginx start
```
+
#### 原因分析
```bash
@@ -126,6 +127,7 @@ CMD service nginx start
↓
6. 容器主进程(sh)退出 → 容器停止
```
+
#### 正确做法
```docker
@@ -153,6 +155,7 @@ CMD ["curl", "-s", "http://example.com"]
$ docker run myimage # 执行默认命令
$ docker run myimage curl -v ... # 完全覆盖
```
+
#### 搭配 ENTRYPOINT
```docker
@@ -182,6 +185,7 @@ CMD ["python", "app.py"]
CMD ["sh", "-c", "echo $PATH && python app.py"]
```
+
#### 2. 确保应用在前台运行
```docker
@@ -196,6 +200,7 @@ CMD ["java", "-jar", "app.jar"]
CMD service nginx start
CMD systemctl start nginx
```
+
#### 3. 使用双引号
```docker
@@ -207,6 +212,7 @@ CMD ["node", "server.js"]
CMD ['node', 'server.js']
```
+
#### 4. 配合 ENTRYPOINT 使用
```docker
@@ -233,6 +239,7 @@ $ docker run myapp --port 9000
CMD ["echo", "first"]
CMD ["echo", "second"] # 只有这个生效
```
+
#### Q:如何在 CMD 中使用环境变量?
```docker
@@ -244,6 +251,7 @@ CMD echo "Port is $PORT"
CMD ["sh", "-c", "echo Port is $PORT"]
```
+
#### Q:为什么我的容器不响应 Ctrl+C?
可能是使用了 shell 格式,信号被 sh 吃掉了:
diff --git a/07_dockerfile/7.5_entrypoint.md b/07_dockerfile/7.5_entrypoint.md
index d9fa714..bf98988 100644
--- a/07_dockerfile/7.5_entrypoint.md
+++ b/07_dockerfile/7.5_entrypoint.md
@@ -95,6 +95,7 @@ exec: "-i": executable file not found
...
```
+
#### 使用 ENTRYPOINT 解决
```docker
@@ -111,6 +112,7 @@ HTTP/1.1 200 OK
...
当前 IP:61.148.226.66
```
+
#### 交互图示
```bash
@@ -160,6 +162,7 @@ fi
exec "$@"
```
+
#### 工作流程
```bash
@@ -173,6 +176,7 @@ docker-entrypoint.sh redis-server docker-entrypoint.sh bash
└─ exec gosu redis redis-server └─ exec bash
(以 redis 用户运行) (以 root 用户运行)
```
+
#### 关键点
1. **exec “$@”**:用传入的参数替换当前进程,确保信号正确传递
@@ -261,12 +265,14 @@ ENTRYPOINT ["python", "app.py"]
ENTRYPOINT python app.py
```
+
#### 2. 提供有意义的默认参数
```docker
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
```
+
#### 3. 入口脚本使用 exec
```bash
@@ -278,6 +284,7 @@ CMD ["-g", "daemon off;"]
exec "$@"
```
+
#### 4. 处理信号
确保 ENTRYPOINT 脚本能正确传递信号:
diff --git a/07_dockerfile/7.6_env.md b/07_dockerfile/7.6_env.md
index be32312..a27e0ac 100644
--- a/07_dockerfile/7.6_env.md
+++ b/07_dockerfile/7.6_env.md
@@ -21,6 +21,7 @@ ENV = = ...
ENV NODE_VERSION 20.10.0
ENV APP_ENV production
```
+
#### 设置多个变量
```docker
@@ -53,6 +54,7 @@ WORKDIR $APP_HOME
COPY . $APP_HOME
```
+
#### 2. 容器运行时使用
```docker
@@ -106,6 +108,7 @@ $ docker run -e APP_ENV=development -e DEBUG=true myimage
$ docker run --env-file .env myimage
```
+
#### .env 文件格式
```bash
@@ -165,6 +168,7 @@ RUN apt-get install nginx=${NGINX_VERSION}
RUN apt-get install nginx=1.25.0
```
+
#### 2. 不要存储敏感信息
```docker
@@ -178,6 +182,7 @@ ENV DB_PASSWORD=secret123
...
```
+
#### 3. 为应用提供合理默认值
```docker
@@ -185,6 +190,7 @@ ENV APP_ENV=production \
APP_PORT=8080 \
LOG_LEVEL=info
```
+
#### 4. 使用有意义的变量名
```docker
@@ -215,12 +221,14 @@ CMD ["python", "app.py", "--port", "$PORT"]
CMD ["sh", "-c", "python app.py --port $PORT"]
```
+
#### Q:如何查看容器的环境变量
```bash
$ docker inspect mycontainer --format '{{json .Config.Env}}'
$ docker exec mycontainer env
```
+
#### Q:多行 ENV 还是多个 ENV
```docker
diff --git a/07_dockerfile/7.7_arg.md b/07_dockerfile/7.7_arg.md
index 2d9a615..e0222bb 100644
--- a/07_dockerfile/7.7_arg.md
+++ b/07_dockerfile/7.7_arg.md
@@ -43,6 +43,7 @@ ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine
RUN echo "Using Node.js $NODE_VERSION"
```
+
#### 构建时覆盖
```bash
@@ -72,6 +73,7 @@ FROM ${REGISTRY}/${IMAGE_NAME}:20
RUN echo $REGISTRY # 输出空
```
+
#### FROM 之后重新声明
```docker
@@ -84,6 +86,7 @@ FROM node:${NODE_VERSION}-alpine
ARG NODE_VERSION
RUN echo "Node version: $NODE_VERSION"
```
+
#### 多阶段构建中的 ARG
```docker
@@ -116,6 +119,7 @@ FROM alpine:${ALPINE_VERSION}
```bash
$ docker build --build-arg ALPINE_VERSION=3.18 .
```
+
#### 2. 设置软件版本
```docker
@@ -123,6 +127,7 @@ ARG NGINX_VERSION=1.25.0
RUN curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xz
```
+
#### 3. 配置构建环境
```docker
@@ -135,6 +140,7 @@ RUN if [ "$ENABLE_DEBUG" = "true" ]; then \
npm install --production; \
fi
```
+
#### 4. 配置私有仓库
```docker
@@ -199,6 +205,7 @@ ARG NODE_VERSION=20
ARG NODE_VERSION
```
+
#### 2. 不要用 ARG 存储敏感信息
```docker
@@ -211,6 +218,7 @@ RUN echo "password=$DB_PASSWORD" > /app/.env
...
```
+
#### 3. 使用 ARG 提高构建灵活性
```docker
diff --git a/07_dockerfile/7.8_volume.md b/07_dockerfile/7.8_volume.md
index cbf1e7c..e3d16c0 100644
--- a/07_dockerfile/7.8_volume.md
+++ b/07_dockerfile/7.8_volume.md
@@ -47,6 +47,7 @@ flowchart LR
FROM mysql:8.0
VOLUME /var/lib/mysql
```
+
#### 定义多个卷
```docker
@@ -67,6 +68,7 @@ $ docker volume ls
DRIVER VOLUME NAME
local a1b2c3d4e5f6... # 自动创建的匿名卷
```
+
#### 2. 可被命名卷覆盖
```bash
@@ -74,6 +76,7 @@ local a1b2c3d4e5f6... # 自动创建的匿名卷
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
```
+
#### 3. 可被 Bind Mount 覆盖
```bash
@@ -120,12 +123,14 @@ VOLUME /data
FROM postgres:16
VOLUME /var/lib/postgresql/data
```
+
#### 日志目录
```docker
FROM nginx
VOLUME /var/log/nginx
```
+
#### 上传文件目录
```docker
@@ -212,6 +217,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.0
FROM postgres:16
VOLUME /var/lib/postgresql/data
```
+
#### 2. 不要在 VOLUME 后修改目录
```docker
@@ -225,6 +231,7 @@ RUN cp init-data.json /app/data/
RUN mkdir -p /app/data && cp init-data.json /app/data/
VOLUME /app/data
```
+
#### 3. 文档中说明 VOLUME 用途
```docker
diff --git a/07_dockerfile/7.9_expose.md b/07_dockerfile/7.9_expose.md
index 67d8211..549a4e2 100644
--- a/07_dockerfile/7.9_expose.md
+++ b/07_dockerfile/7.9_expose.md
@@ -44,6 +44,7 @@ EXPOSE 80 443
$ docker inspect nginx --format '{{.Config.ExposedPorts}}'
map[80/tcp:{}]
```
+
#### 2. 配合 -P 使用
使用 `docker run -P` 时,Docker 会自动映射 EXPOSE 的端口到宿主机随机端口:
@@ -75,6 +76,7 @@ flowchart TD
Run["docker run -p
实际端口映射
宿主机 ←→ 容器"]
Expose ~~~ Run
```
+
#### 没有 EXPOSE 也能 -p
```docker
@@ -145,6 +147,7 @@ EXPOSE 5432
FROM redis
EXPOSE 6379
```
+
#### 2. 使用明确的协议
```docker
@@ -160,6 +163,7 @@ EXPOSE 53/udp
EXPOSE 53/tcp 53/udp
```
+
#### 3. 与应用实际端口保持一致
```docker
diff --git a/08_data/8.1_volume.md b/08_data/8.1_volume.md
index 14614c1..66b0614 100644
--- a/08_data/8.1_volume.md
+++ b/08_data/8.1_volume.md
@@ -41,6 +41,7 @@ graph TD
Lifecycle[生命周期 = 容器生命周期] -.-> Container
Delete[容器删除] -->|导致| DataLost[数据丢失 ❌]
```
+
#### 数据卷:推荐
```mermaid
@@ -65,6 +66,7 @@ graph TD
```bash
$ docker volume create my-vol
```
+
#### 列出所有数据卷
```bash
@@ -74,6 +76,7 @@ local my-vol
local postgres_data
local redis_data
```
+
#### 查看数据卷详情
```bash
@@ -182,6 +185,7 @@ $ docker run -d \
-v postgres_data:/var/lib/postgresql/data \
postgres:16
```
+
#### 场景二:多容器共享数据
```bash
@@ -201,6 +205,7 @@ $ docker run --rm \
-v shared-data:/data \
alpine cat /data/log.txt
```
+
#### 场景三:配置文件持久化
```bash
@@ -227,6 +232,7 @@ $ docker volume rm my-vol
$ docker rm -v container_name
```
+
#### 清理未使用的数据卷
```bash
@@ -279,6 +285,7 @@ $ docker run --rm \
-v $(pwd):/backup:ro \
alpine tar xzf /backup/my-vol-backup.tar.gz -C /target
```
+
#### 备份脚本示例
```bash
@@ -331,6 +338,7 @@ $ docker run -v /host/path:/app/data nginx
```bash
$ docker inspect container_name --format '{{json .Mounts}}' | jq
```
+
#### Q:数据卷的数据在哪里?
```bash
diff --git a/08_data/8.2_bind-mounts.md b/08_data/8.2_bind-mounts.md
index 82c0f46..04820b7 100644
--- a/08_data/8.2_bind-mounts.md
+++ b/08_data/8.2_bind-mounts.md
@@ -58,6 +58,7 @@ $ docker run -d \
--mount type=bind,source=/宿主机路径,target=/容器路径 \
nginx
```
+
#### 使用 -v:简写
```bash
@@ -65,6 +66,7 @@ $ docker run -d \
-v /宿主机路径:/容器路径 \
nginx
```
+
#### 两种语法对比
| 特性 | --mount | -v |
@@ -97,6 +99,7 @@ $ echo "Hello" > src/index.html
...
```
+
#### 场景二:配置文件挂载
```bash
@@ -106,6 +109,7 @@ $ docker run -d \
--mount type=bind,source=/path/to/nginx.conf,target=/etc/nginx/nginx.conf,readonly \
nginx
```
+
#### 场景三:日志收集
```bash
@@ -115,6 +119,7 @@ $ docker run -d \
--mount type=bind,source=/var/log/myapp,target=/app/logs \
myapp
```
+
#### 场景四:共享 SSH 密钥
```bash
@@ -227,6 +232,7 @@ $ docker run -u root ...
$ docker run -u $(id -u):$(id -g) ...
```
+
#### Q:macOS/Windows 性能问题
在 Docker Desktop 上,Bind Mount 性能较差 (需要跨文件系统同步):
@@ -253,6 +259,7 @@ $ docker run -v /host/path:/container/path:cached myapp
$ docker run -v $(pwd):/app -p 3000:3000 node npm run dev
```
+
#### 2. 生产环境使用 Volume
```bash
@@ -260,11 +267,13 @@ $ docker run -v $(pwd):/app -p 3000:3000 node npm run dev
$ docker run -v mysql_data:/var/lib/mysql mysql
```
+
#### 3. 配置文件使用只读挂载
```bash
$ docker run -v /config/nginx.conf:/etc/nginx/nginx.conf:ro nginx
```
+
#### 4. 注意路径安全
```bash
diff --git a/09_network/9.1_dns.md b/09_network/9.1_dns.md
index 4ff418c..7a92863 100644
--- a/09_network/9.1_dns.md
+++ b/09_network/9.1_dns.md
@@ -49,6 +49,7 @@ Docker 守护进程在 `127.0.0.11` 运行了一个 DNS 服务器。容器内的
$ docker run -it --dns=114.114.114.114 ubuntu cat /etc/resolv.conf
nameserver 114.114.114.114
```
+
#### 2. --dns-search
指定 DNS 搜索域。例如设置为 `example.com`,则 `ping host` 会尝试解析 `host.example.com`。
@@ -56,6 +57,7 @@ nameserver 114.114.114.114
```bash
$ docker run --dns-search=example.com myapp
```
+
#### 3. --hostname 与 -h
设置容器的主机名。
diff --git a/09_network/9.2_network_types.md b/09_network/9.2_network_types.md
index 35bdfbd..fd20155 100644
--- a/09_network/9.2_network_types.md
+++ b/09_network/9.2_network_types.md
@@ -9,6 +9,7 @@ abc123... bridge bridge local
def456... host host local
ghi789... none null local
```
+
### 9.2.1 网络类型对比
各网络类型的特点和适用场景如下:
@@ -52,6 +53,7 @@ $ docker run -it --network none alpine ip addr
1: lo: ...
inet 127.0.0.1/8 scope host lo
```
+
### 9.2.5 数据流向
容器网络中的数据流向可以分为以下几种情况:
diff --git a/09_network/9.3_custom_network.md b/09_network/9.3_custom_network.md
index d778da8..d35d358 100644
--- a/09_network/9.3_custom_network.md
+++ b/09_network/9.3_custom_network.md
@@ -25,6 +25,7 @@ $ docker network create mynet
$ docker network inspect mynet
```
+
### 9.3.3 使用自定义网络
启动容器时通过 `--network` 参数指定连接的网络:
@@ -41,6 +42,7 @@ $ docker exec web ping db
PING db (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.083 ms
```
+
### 9.3.4 容器名 DNS 解析
自定义网络自动提供 DNS 服务。Docker 守护进程在 `127.0.0.11` 运行了一个嵌入式 DNS 服务器,容器内的 DNS 请求会被转发到这里:
@@ -55,6 +57,7 @@ flowchart LR
Web["web
172.18.0.2"] -- "DNS: 'db' → 172.18.0.3" --> DB["db
172.18.0.3"]
end
```
+
### 9.3.5 常用网络命令
以下是 Docker 网络管理中常用的命令:
diff --git a/09_network/9.4_container_linking.md b/09_network/9.4_container_linking.md
index 451cf43..59344e7 100644
--- a/09_network/9.4_container_linking.md
+++ b/09_network/9.4_container_linking.md
@@ -20,6 +20,7 @@ $ docker run -d --name app --network app-net myapp
...
```
+
### 9.4.2 连接到多个网络
一个容器可以同时连接到多个网络,这对于需要跨网络通信的中间件容器特别有用:
@@ -37,6 +38,7 @@ $ docker network connect backend multi-net-container
$ docker inspect multi-net-container --format '{{json .NetworkSettings.Networks}}'
```
+
### 9.4.3 ⚠️ --link 已废弃
`--link` 是 Docker 早期用于容器互联的方式,**已经被废弃**,不建议在新项目中使用。请使用自定义网络替代:
diff --git a/09_network/9.5_port_mapping.md b/09_network/9.5_port_mapping.md
index f64cef2..ddea50f 100644
--- a/09_network/9.5_port_mapping.md
+++ b/09_network/9.5_port_mapping.md
@@ -75,6 +75,7 @@ $ docker port mycontainer
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080
```
+
#### docker ps
运行 `docker ps` 可以查看到所有容器的端口映射列表:
@@ -101,6 +102,7 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web
$ docker run -d -p 127.0.0.1:3306:3306 mysql
```
+
#### 2. 避免端口冲突
如果宿主机 8080 已经被占用了,容器将无法启动。
diff --git a/09_network/9.6_network_isolation.md b/09_network/9.6_network_isolation.md
index 7d86be1..3df6fbc 100644
--- a/09_network/9.6_network_isolation.md
+++ b/09_network/9.6_network_isolation.md
@@ -25,6 +25,7 @@ $ docker run -d --name db --network backend postgres
$ docker exec web ping db
ping: db: Name or service not known
```
+
### 9.6.2 安全优势
这种隔离机制带来以下安全优势:
diff --git a/09_network/9.7_advanced_networking.md b/09_network/9.7_advanced_networking.md
index f3ef1a5..8f73005 100644
--- a/09_network/9.7_advanced_networking.md
+++ b/09_network/9.7_advanced_networking.md
@@ -29,6 +29,7 @@ veth 对
↓
容器 B (192.168.0.3,不同宿主机)
```
+
#### 创建和使用 Overlay 网络
**Docker Swarm 模式下的 Overlay 网络:**
@@ -73,6 +74,7 @@ docker exec container1 curl http://container2
# 检查网络配置
docker network inspect custom-overlay
```
+
#### Overlay 网络性能优化
```bash
@@ -107,6 +109,7 @@ networks:
driver_opts:
com.docker.network.driver.mtu: 1450
```
+
### 9.7.2 CNI 插件生态概览
容器网络接口(CNI)是容器编排平台(尤其是 Kubernetes)的标准化网络接口。不同的 CNI 插件提供不同的网络能力。
@@ -255,6 +258,7 @@ Docker 内嵌 DNS 服务器 (127.0.0.11)
↓
DNS 响应 → 容器缓存 → 应用
```
+
#### 配置容器 DNS
**在运行时指定 DNS:**
@@ -317,6 +321,7 @@ networks:
"registry-mirrors": ["https://mirror.example.com"]
}
```
+
#### 自定义服务发现
**使用 Docker 内建 DNS 的服务发现:**
@@ -361,6 +366,7 @@ services:
# frontend 容器可以直接访问 http://backend:8080
# backend 容器可以直接访问 postgres://database:5432
```
+
#### DNS 性能优化
```bash
@@ -393,6 +399,7 @@ kubectl patch deployment -n kube-system coredns --patch '{
}
}'
```
+
### 9.7.4 网络策略实践
网络策略定义了容器间的流量控制规则,是微服务架构中的安全基础。
@@ -473,6 +480,7 @@ spec:
- protocol: TCP
port: 443
```
+
#### 微服务网络策略示例
```yaml
@@ -597,6 +605,7 @@ spec:
- protocol: TCP
port: 5432
```
+
#### 使用 Calico/Cilium 的高级网络策略
**L7 应用层策略(仅 Cilium 支持):**
@@ -630,6 +639,7 @@ spec:
sourceIPs:
- "10.0.0.0/8"
```
+
### 9.7.5 跨主机容器通信方案对比
#### 方案对比表
@@ -661,6 +671,7 @@ helm install cilium cilium/cilium --namespace kube-system
# 5. 需要多云/跨域:使用 Weave
```
+
### 9.7.6 网络故障排查
**常见网络问题诊断:**
diff --git a/10_buildx/10.1_buildkit.md b/10_buildx/10.1_buildkit.md
index 85c5c73..449135f 100644
--- a/10_buildx/10.1_buildkit.md
+++ b/10_buildx/10.1_buildkit.md
@@ -110,6 +110,7 @@ RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoint,target=/docker-php-entrypoint \
cat /docker-php-entrypoint
```
+
#### `RUN --mount=type=tmpfs`
该指令可以将一个 `tmpfs` 文件系统挂载到指定位置。
@@ -120,6 +121,7 @@ RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoin
RUN --mount=type=tmpfs,target=/temp \
mount | grep /temp
```
+
#### `RUN --mount=type=secret`
该指令可以将一个文件 (例如密钥) 挂载到指定位置。
@@ -133,6 +135,7 @@ RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
```bash
$ docker build -t test --secret id=aws,src=$HOME/.aws/credentials .
```
+
#### `RUN --mount=type=ssh`
该指令可以挂载 `ssh` 密钥。
@@ -151,6 +154,7 @@ $ ssh-add ~/.ssh/id_rsa
(Input your passphrase here)
$ docker build -t test --ssh default=$SSH_AUTH_SOCK .
```
+
### 10.1.2 使用 `docker compose build` 与 BuildKit
Docker Compose 同样支持 BuildKit,这使得多服务应用的构建更加高效。
diff --git a/10_buildx/10.2_buildx.md b/10_buildx/10.2_buildx.md
index 3adc697..764ae6e 100644
--- a/10_buildx/10.2_buildx.md
+++ b/10_buildx/10.2_buildx.md
@@ -26,6 +26,7 @@ $ docker buildx bake
$ docker buildx bake web
```
+
#### 生成 SBOM
Buildx 支持在构建时直接生成 SBOM (Software Bill of Materials),这对于软件供应链安全至关重要。
diff --git a/10_buildx/10.3_multi-arch-images.md b/10_buildx/10.3_multi-arch-images.md
index afa17ea..1be0715 100644
--- a/10_buildx/10.3_multi-arch-images.md
+++ b/10_buildx/10.3_multi-arch-images.md
@@ -39,6 +39,7 @@ $ docker manifest inspect hello-world
]
}
```
+
### 10.3.2 使用 `docker buildx` 构建多架构镜像
`docker buildx` 是构建多架构镜像的最佳实践工具,它屏蔽了底层的复杂性,提供了一键构建多架构镜像的能力。
@@ -53,6 +54,7 @@ $ docker manifest inspect hello-world
$ docker buildx create --name mybuilder --use
$ docker buildx inspect --bootstrap
```
+
#### 构建和推送
使用 `docker buildx build` 命令并指定 `--platform` 参数,可以同时构建支持多种架构的镜像。`--push` 参数会将构建好的镜像和 manifest list 推送到 Docker 仓库。
@@ -96,6 +98,7 @@ COPY bin/dist-${TARGETOS}-${TARGETARCH} /dist
ENTRYPOINT ["/dist"]
```
+
### 10.3.3 使用 `docker manifest`:底层工具
除了 `docker buildx`,我们也可以直接操作 Manifest List 来手动组合不同架构的镜像。
@@ -120,6 +123,7 @@ $ docker manifest create your-username/my-app:latest \
$ docker manifest push your-username/my-app:latest
```
+
#### 检查 manifest list
你可以使用 `docker manifest inspect` 来查看一个 manifest list 的详细信息,如上文所示。
diff --git a/11_compose/11.2_install.md b/11_compose/11.2_install.md
index be2685e..c62ca72 100644
--- a/11_compose/11.2_install.md
+++ b/11_compose/11.2_install.md
@@ -30,17 +30,20 @@ $ curl -SL https://github.com/docker/compose/releases/download/v5.1.0/docker-com
```bash
$ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
```
+
### 11.2.2 测试安装
```bash
$ docker compose version
Docker Compose version v5.1.0
```
+
### 11.2.3 bash 补全命令
```bash
$ curl -L https://raw.githubusercontent.com/docker/compose/v5.1.0/contrib/completion/bash/docker-compose | sudo tee /etc/bash_completion.d/docker-compose > /dev/null
```
+
### 11.2.4 卸载
如果是二进制包方式安装的,删除二进制文件即可。
diff --git a/11_compose/11.3_usage.md b/11_compose/11.3_usage.md
index f8b330d..c7c140b 100644
--- a/11_compose/11.3_usage.md
+++ b/11_compose/11.3_usage.md
@@ -37,6 +37,7 @@ def hello():
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
```
+
#### Dockerfile
编写 `Dockerfile` 文件,内容为
@@ -48,6 +49,7 @@ WORKDIR /code
RUN pip install redis flask
CMD ["python", "app.py"]
```
+
#### compose.yaml
编写 `compose.yaml` 文件,这是 Compose 推荐使用的主模板文件 (也兼容 `docker-compose.yml` 等历史文件名)。
@@ -62,6 +64,7 @@ services:
redis:
image: "redis:alpine"
```
+
#### 运行 compose 项目
```bash
@@ -77,11 +80,13 @@ $ docker compose up
```bash
$ docker compose up -d
```
+
#### 停止
```bash
$ docker compose stop
```
+
#### 进入服务
```bash
@@ -90,31 +95,37 @@ $ docker compose exec redis sh
127.0.0.1:6379> get hits
"9"
```
+
#### 查看日志
```bash
$ docker compose logs -f
```
+
#### 构建镜像
```bash
$ docker compose build
```
+
#### 启动服务
```bash
$ docker compose start
```
+
#### 运行一次性命令
```bash
$ docker compose run web python app.py
```
+
#### 验证 Compose 文件
```bash
$ docker compose config
```
+
#### 删除项目
```bash
diff --git a/11_compose/11.4_commands.md b/11_compose/11.4_commands.md
index 0734334..4fcd408 100644
--- a/11_compose/11.4_commands.md
+++ b/11_compose/11.4_commands.md
@@ -13,6 +13,7 @@ Docker Compose 提供了丰富的命令来管理项目和容器。本节将详
```bash
docker compose [-f=...] [options] [COMMAND] [ARGS...]
```
+
### 11.4.2 命令选项
* `-f, --file FILE` 指定使用的 Compose 模板文件。默认会自动识别 `compose.yaml` (也兼容 `docker-compose.yml` 等),并且可以多次指定。
@@ -74,6 +75,7 @@ docker compose [-f=...] [options] [COMMAND] [ARGS...]
```bash
$ docker compose kill -s SIGINT
```
+
#### `logs`
格式为 `docker compose logs [options] [SERVICE...]`。
diff --git a/11_compose/11.5_compose_file.md b/11_compose/11.5_compose_file.md
index c94940b..3ae9ecb 100644
--- a/11_compose/11.5_compose_file.md
+++ b/11_compose/11.5_compose_file.md
@@ -52,6 +52,7 @@ build:
- alpine:latest
- corp/web_app:3.14
```
+
### 11.5.2 `cap_add, cap_drop`
指定容器的内核能力 (capacity) 分配。
@@ -68,6 +69,7 @@ cap_add:
cap_drop:
- NET_ADMIN
```
+
### 11.5.3 `command`
覆盖容器启动后默认执行的命令。
@@ -75,6 +77,7 @@ cap_drop:
```yaml
command: echo "hello world"
```
+
### 11.5.4 `configs`
`configs` 来自 Compose Specification。它在 Swarm 中是原生对象;在本地 `docker compose` 模式下通常以文件挂载的形式实现,具体能力取决于 Compose 版本与运行平台。
@@ -88,6 +91,7 @@ command: echo "hello world"
```yaml
cgroup_parent: cgroups_1
```
+
### 11.5.6 `container_name`
指定容器名称。默认将会使用 `项目名称_服务名称_序号` 这样的格式。
@@ -109,6 +113,7 @@ container_name: docker-web-container
devices:
- "/dev/ttyUSB1:/dev/ttyUSB0"
```
+
### 11.5.9 `depends_on`
解决容器的依赖、启动先后的问题。以下例子中会先启动 `redis` `db` 再启动 `web`
@@ -140,6 +145,7 @@ dns:
- 8.8.8.8
- 114.114.114.114
```
+
### 11.5.11 `dns_search`
配置 `DNS` 搜索域。可以是一个值,也可以是一个列表。
@@ -151,6 +157,7 @@ dns_search:
- domain1.example.com
- domain2.example.com
```
+
### 11.5.12 `tmpfs`
挂载一个 tmpfs 文件系统到容器。
@@ -161,6 +168,7 @@ tmpfs:
- /run
- /tmp
```
+
### 11.5.13 `env_file`
从文件中获取环境变量,可以为单独的文件路径或列表。
@@ -184,6 +192,7 @@ env_file:
PROG_ENV=development
```
+
### 11.5.14 `environment`
设置环境变量。你可以使用数组或字典两种格式。
@@ -204,6 +213,7 @@ environment:
```bash
y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF
```
+
### 11.5.15 `expose`
暴露端口,但不映射到宿主机,只被连接的服务访问。
@@ -215,6 +225,7 @@ expose:
- "3000"
- "8000"
```
+
### 11.5.16 `external_links`
> 注意:不建议使用该指令。
@@ -227,6 +238,7 @@ external_links:
- project_db_1:mysql
- project_db_1:postgresql
```
+
### 11.5.17 `extra_hosts`
类似 Docker 中的 `--add-host` 参数,指定额外的 host 名称映射信息。
@@ -242,6 +254,7 @@ extra_hosts:
8.8.8.8 googledns
52.1.157.61 dockerhub
```
+
### 11.5.18 `healthcheck`
通过命令检查容器是否健康运行。
@@ -253,6 +266,7 @@ healthcheck:
timeout: 10s
retries: 3
```
+
### 11.5.19 `image`
指定为镜像名称或镜像 ID。如果镜像在本地不存在,`Compose` 将会尝试拉取这个镜像。
@@ -262,6 +276,7 @@ image: ubuntu
image: orchardup/postgresql
image: a4bc65fd
```
+
### 11.5.20 `labels`
为容器添加 Docker 元数据 (metadata) 信息。例如可以为容器添加辅助说明信息。
@@ -272,6 +287,7 @@ labels:
com.startupteam.department: "devops department"
com.startupteam.release: "rc3 for v1.0"
```
+
### 11.5.21 `links`
> 注意:不推荐使用该指令。容器之间应通过 Docker 网络 (networks) 进行互联。
@@ -300,6 +316,7 @@ options:
max-size: "200k"
max-file: "10"
```
+
### 11.5.23 `network_mode`
设置网络模式。使用和 `docker run` 的 `--network` 参数一样的值。
@@ -311,6 +328,7 @@ network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
```
+
### 11.5.24 `networks`
配置容器连接的网络。
@@ -327,6 +345,7 @@ networks:
some-network:
other-network:
```
+
### 11.5.25 `pid`
跟主机系统共享进程命名空间。打开该选项的容器之间,以及容器和宿主机系统之间可以通过进程 ID 来相互访问和操作。
@@ -334,6 +353,7 @@ networks:
```yaml
pid: "host"
```
+
### 11.5.26 `ports`
暴露端口信息。
@@ -370,6 +390,7 @@ secrets:
my_other_secret:
external: true
```
+
### 11.5.28 `security_opt`
指定容器模板标签 (label) 机制的默认属性 (用户、角色、类型、级别等)。例如配置标签的用户名和角色名。
@@ -379,6 +400,7 @@ security_opt:
- label:user:USER
- label:role:ROLE
```
+
### 11.5.29 `stop_signal`
设置另一个信号来停止容器。在默认情况下使用的是 SIGTERM 停止容器。
@@ -386,6 +408,7 @@ security_opt:
```yaml
stop_signal: SIGUSR1
```
+
### 11.5.30 `sysctls`
配置容器内核参数。
@@ -399,6 +422,7 @@ sysctls:
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0
```
+
### 11.5.31 `ulimits`
指定容器的 ulimits 限制值。
@@ -412,6 +436,7 @@ sysctls:
soft: 20000
hard: 40000
```
+
### 11.5.32 `volumes`
数据卷所挂载路径设置。可以设置为宿主机路径 (`HOST:CONTAINER`) 或者数据卷名称 (`VOLUME:CONTAINER`),并且可以设置访问模式 (`HOST:CONTAINER:ro`)。
@@ -436,6 +461,7 @@ services:
volumes:
mysql_data:
```
+
### 11.5.33 其它指令
此外,还有包括 `domainname, entrypoint, hostname, ipc, mac_address, privileged, read_only, shm_size, restart, stdin_open, tty, user, working_dir` 等指令,基本跟 `docker run` 中对应参数的功能一致。
@@ -487,6 +513,7 @@ stdin_open: true
```yaml
tty: true
```
+
### 11.5.34 读取变量
Compose 模板文件支持动态读取主机的系统环境变量和当前目录下的 `.env` 文件中的变量。
diff --git a/11_compose/11.6_django.md b/11_compose/11.6_django.md
index 2f3e281..13e6820 100644
--- a/11_compose/11.6_django.md
+++ b/11_compose/11.6_django.md
@@ -298,6 +298,7 @@ $ docker compose exec db psql -U django_user -d django_db
$ docker compose ps
$ docker compose logs db
```
+
#### Q2:代码修改没有生效
**可能原因**:
@@ -313,6 +314,7 @@ $ docker compose logs db
$ sudo chown -R $USER:$USER .
```
+
### 11.6.11 开发 vs 生产:关键差异
笔者特别提醒,本节的配置是 **开发环境** 配置。生产环境需要以下调整:
@@ -340,6 +342,7 @@ services:
# ...
```
+
### 11.6.12 延伸阅读
- [Compose 模板文件详解](11.5_compose_file.md):深入理解 Compose 文件的所有配置项
diff --git a/11_compose/11.7_rails.md b/11_compose/11.7_rails.md
index 208b536..4e09869 100644
--- a/11_compose/11.7_rails.md
+++ b/11_compose/11.7_rails.md
@@ -88,6 +88,7 @@ gem 'rails', '~> 7.1'
```bash
$ touch Gemfile.lock
```
+
### 11.7.5 步骤 3:创建 compose.yaml
配置如下:
@@ -157,6 +158,7 @@ compose.yaml bin db public
```bash
$ docker compose build
```
+
### 11.7.8 步骤 6:配置数据库连接
修改 `config/database.yml`:
@@ -196,6 +198,7 @@ web-1 | => Run `bin/rails server --help` for more startup options
web-1 | Puma starting in single mode...
web-1 | * Listening on http://0.0.0.0:3000
```
+
### 11.7.10 步骤 8:创建数据库
在另一个终端执行:
@@ -230,6 +233,7 @@ $ docker compose exec web rails generate scaffold Post title:string body:text
$ docker compose exec web bash
```
+
### 11.7.12 常见问题
#### Q:数据库连接失败
@@ -240,6 +244,7 @@ $ docker compose exec web bash
$ docker compose ps
$ docker compose logs db
```
+
#### Q:server.pid 文件导致启动失败
错误信息:`A server is already running`
@@ -249,6 +254,7 @@ $ docker compose logs db
```bash
$ docker compose exec web rm -f tmp/pids/server.pid
```
+
#### Q:Gem 安装失败
可能需要更新 bundler 或清理缓存:
@@ -256,6 +262,7 @@ $ docker compose exec web rm -f tmp/pids/server.pid
```bash
$ docker compose run --rm web bundle update
```
+
### 11.7.13 开发 vs 生产
| 配置项 | 开发环境 | 生产环境 |
diff --git a/11_compose/11.8_wordpress.md b/11_compose/11.8_wordpress.md
index 79d1672..4749fe5 100644
--- a/11_compose/11.8_wordpress.md
+++ b/11_compose/11.8_wordpress.md
@@ -154,6 +154,7 @@ $ docker exec wordpress_db mysqldump -u wordpress -pwordpress wordpress > backup
networks:
- wp_net
```
+
#### 2. 使用 Nginx 反向代理
在生产环境中,不要直接暴露 WordPress 端口,而是通过 Nginx 进行反向代理并配置 SSL。
diff --git a/12_implementation/12.2_namespace.md b/12_implementation/12.2_namespace.md
index 9a82663..d837ada 100644
--- a/12_implementation/12.2_namespace.md
+++ b/12_implementation/12.2_namespace.md
@@ -25,6 +25,7 @@ flowchart LR
H4 -. "(实际是宿主机的 1234)" .- C1
```
+
### 12.2.2 Namespace 的类型
Linux 内核提供了以下几种 Namespace,Docker 容器使用了全部:
@@ -65,6 +66,7 @@ PID USER COMMAND
1 root nginx: master process ← 在容器内是 PID 1
2 root nginx: worker process
```
+
#### PID 关键点
- 容器内的 PID 1 进程特殊重要——它是容器的主进程,退出则容器停止
@@ -99,6 +101,7 @@ flowchart LR
H2 <--> C2
```
+
#### NET 关键点
- 每个容器有独立的网卡、IP、路由表、iptables 规则
@@ -129,6 +132,7 @@ MNT Namespace 负责文件系统挂载点的隔离,确保容器看到独立的
│ └── merged/ ────┼─── 这个目录成为容器的 /
└── ... └── ...
```
+
#### 与 chroot 的区别
| 特性 | chroot | MNT Namespace |
@@ -212,6 +216,7 @@ flowchart LR
C1 -- 映射 --> H1
C2 -- 映射 --> H2
```
+
#### 安全意义
容器内的 root 用户可以映射为宿主机上的普通用户,即使容器被突破,攻击者在宿主机上也只有普通权限。
@@ -243,6 +248,7 @@ $ exit
$ hostname
my-server
```
+
#### 实验 2:PID Namespace
```bash
@@ -261,6 +267,7 @@ USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 8960 4516 pts/0 S 10:00 0:00 /bin/bash
root 8 0.0 0.0 10072 3200 pts/0 R+ 10:00 0:00 ps aux
```
+
#### 实验 3:NET Namespace
```bash
diff --git a/12_implementation/12.3_cgroups.md b/12_implementation/12.3_cgroups.md
index 25e8663..422c7e8 100644
--- a/12_implementation/12.3_cgroups.md
+++ b/12_implementation/12.3_cgroups.md
@@ -117,6 +117,7 @@ $ docker run --device-read-bps /dev/sda:10mb myapp
$ docker run --device-write-iops /dev/sda:100 myapp
```
+
#### 进程数限制
```bash
@@ -165,6 +166,7 @@ abc123 Exited (137) 5 seconds ago hopeful_darwin
...
```
+
#### CPU 限制验证
```bash
@@ -253,11 +255,13 @@ services:
$ docker run -m 1g myapp
```
+
#### 2. 为关键应用设置 CPU 保证
```bash
$ docker run --cpus=2 --cpu-shares=2048 critical-app
```
+
#### 3. 监控资源使用
```bash
diff --git a/12_implementation/12.4_ufs.md b/12_implementation/12.4_ufs.md
index 40d2a7e..06040eb 100644
--- a/12_implementation/12.4_ufs.md
+++ b/12_implementation/12.4_ufs.md
@@ -197,6 +197,7 @@ RUN apt-get update && \
apt-get install -y nginx && \
rm -rf /var/lib/apt/lists/*
```
+
#### 2. 避免在容器中写入大量数据
容器层的写入性能低于直接写入。大量数据应使用:
diff --git a/13_kubernetes_concepts/13.2_concepts.md b/13_kubernetes_concepts/13.2_concepts.md
index 771e33f..91e8ec7 100644
--- a/13_kubernetes_concepts/13.2_concepts.md
+++ b/13_kubernetes_concepts/13.2_concepts.md
@@ -65,6 +65,7 @@ status:
- type: Ready
status: "True"
```
+
#### 节点控制器
在 Kubernetes 控制平面中,节点控制器 (Node Controller) 负责管理节点的生命周期,主要包含:
@@ -81,6 +82,7 @@ $ kubectl cordon worker-1
## 排空节点上的 Pod
$ kubectl drain worker-1 --ignore-daemonsets
```
+
### 13.2.2 容器组
在 Kubernetes 中,使用的最小调度单位是容器组 (Pod),它是创建、调度、管理的最小单位。一个 Pod 包含一个或多个紧密协作的容器,它们共享网络命名空间和存储卷。
diff --git a/13_kubernetes_concepts/13.4_advanced.md b/13_kubernetes_concepts/13.4_advanced.md
index 8a7b46f..9b6d967 100644
--- a/13_kubernetes_concepts/13.4_advanced.md
+++ b/13_kubernetes_concepts/13.4_advanced.md
@@ -52,6 +52,7 @@ spec:
type: Utilization
averageUtilization: 50
```
+
### 13.4.5 ConfigMap 与 Secret
* **ConfigMap**:存储非机密的配置数据 (配置文件、环境变量)。
diff --git a/13_kubernetes_concepts/13.5_practice.md b/13_kubernetes_concepts/13.5_practice.md
index aae23d5..46de7df 100644
--- a/13_kubernetes_concepts/13.5_practice.md
+++ b/13_kubernetes_concepts/13.5_practice.md
@@ -40,6 +40,7 @@ spec:
```bash
kubectl apply -f nginx-deployment.yaml
```
+
### 13.5.3 步骤 2:创建 Service
创建一个名为 `nginx-service.yaml` 的文件:
@@ -82,6 +83,7 @@ kubectl apply -f nginx-deployment.yaml
```bash
kubectl rollout status deployment/nginx-deployment
```
+
### 13.5.5 步骤 4:清理资源
练习结束后,记得清理资源:
diff --git a/14_kubernetes_setup/14.1_kubeadm.md b/14_kubernetes_setup/14.1_kubeadm.md
index 7872a82..634b807 100644
--- a/14_kubernetes_setup/14.1_kubeadm.md
+++ b/14_kubernetes_setup/14.1_kubeadm.md
@@ -17,6 +17,7 @@ $ sudo apt install containerd.io
$ sudo yum install containerd.io
```
+
### 14.1.2 配置 containerd
新建 `/etc/systemd/system/cri-containerd.service` 文件
@@ -230,6 +231,7 @@ oom_score = 0
base_image_size = ""
async_remove = false
```
+
### 14.1.3 安装 **kubelet**、**kubeadm**、**kubectl**、**cri-tools**、**kubernetes-cni**
需要在每台机器上安装以下的软件包:
@@ -253,6 +255,7 @@ $ sudo apt-get install -y kubelet kubeadm kubectl cri-tools kubernetes-cni
$ sudo apt-mark hold kubelet kubeadm kubectl
```
+
#### CentOS/Fedora
```bash
@@ -270,6 +273,7 @@ EOF
$ sudo yum install -y kubelet kubeadm kubectl cri-tools kubernetes-cni
```
+
### 14.1.4 修改内核的运行参数
#### 加载内核模块
@@ -283,6 +287,7 @@ EOF
$ sudo modprobe overlay
$ sudo modprobe br_netfilter
```
+
#### 禁用 swap:必须
kubelet 默认要求禁用 swap,否则可能导致初始化失败或节点无法加入集群。
@@ -303,6 +308,7 @@ EOF
$ sysctl --system
```
+
### 14.1.5 配置 kubelet
为了让 kubelet 正确运行,我们需要对其进行一些必要的配置。
@@ -325,6 +331,7 @@ ExecStartPre=-/sbin/modprobe ip_vs_sh
```bash
$ sudo systemctl daemon-reload
```
+
### 14.1.6 部署
安装配置完成后,我们将分别在 Master 节点和 Worker 节点上进行部署操作。
@@ -373,6 +380,7 @@ Then you can join any number of worker nodes by running the following on each as
kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
```
+
#### node 工作节点
在 **另一主机** 重复 **部署** 小节以前的步骤,安装配置好 kubelet。根据提示,加入到集群。
@@ -387,6 +395,7 @@ $ kubeadm join 192.168.199.100:6443 \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe \
--cri-socket /run/cri-containerd/cri-containerd.sock
```
+
### 14.1.7 查看服务
所有服务启动后,通过 `crictl` 查看本地实际运行的容器。这些服务大概分为三类:主节点服务、工作节点服务和其它服务。
@@ -394,6 +403,7 @@ $ kubeadm join 192.168.199.100:6443 \
```bash
CONTAINER_RUNTIME_ENDPOINT=/run/cri-containerd/cri-containerd.sock crictl ps -a
```
+
#### 主节点服务
* `apiserver` 是整个系统的对外接口,提供 RESTful 方式供客户端和其它组件调用;
@@ -437,6 +447,7 @@ $ kubectl get node -o yaml | grep CIDR
```bash
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.1/Documentation/kube-flannel.yml
```
+
### 14.1.10 master 节点默认不能运行 pod
如果用 `kubeadm` 部署一个单节点集群,默认情况下无法使用,请执行以下命令解除限制
@@ -454,6 +465,7 @@ $ kubectl taint nodes --all node-role.kubernetes.io/master-
...
```
+
### 14.1.11 参考文档
* [官方文档](https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)
diff --git a/14_kubernetes_setup/14.2_kubeadm-docker.md b/14_kubernetes_setup/14.2_kubeadm-docker.md
index d7d987c..fd080f8 100644
--- a/14_kubernetes_setup/14.2_kubeadm-docker.md
+++ b/14_kubernetes_setup/14.2_kubeadm-docker.md
@@ -44,6 +44,7 @@ $ sudo systemctl start cri-docker
$ sudo /usr/local/bin/cri-dockerd --version
```
+
#### CentOS/Fedora
```bash
@@ -66,6 +67,7 @@ $ sudo systemctl daemon-reload
$ sudo systemctl enable cri-docker
$ sudo systemctl start cri-docker
```
+
### 14.2.3 安装 **kubelet**、**kubeadm**、**kubectl**
需要在每台机器上安装以下的软件包:
@@ -89,6 +91,7 @@ $ sudo apt-get install -y kubelet kubeadm kubectl
$ sudo apt-mark hold kubelet kubeadm kubectl
```
+
#### CentOS/Fedora
```bash
@@ -106,6 +109,7 @@ EOF
$ sudo yum install -y kubelet kubeadm kubectl
```
+
### 14.2.4 修改内核的运行参数
#### 加载内核模块
@@ -119,6 +123,7 @@ EOF
$ sudo modprobe overlay
$ sudo modprobe br_netfilter
```
+
#### 禁用 swap:必须
kubelet 默认要求禁用 swap,否则可能导致初始化失败或节点无法加入集群。
@@ -139,6 +144,7 @@ EOF
$ sysctl --system
```
+
### 14.2.5 配置 kubelet
为了让 kubelet 正确运行,我们需要对其进行一些必要的配置。
@@ -161,6 +167,7 @@ ExecStartPre=-/sbin/modprobe ip_vs_sh
```bash
$ sudo systemctl daemon-reload
```
+
### 14.2.6 部署
安装配置完成后,我们将分别在 Master 节点和 Worker 节点上进行部署操作。
@@ -205,6 +212,7 @@ Then you can join any number of worker nodes by running the following on each as
kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
```
+
#### node 工作节点
在 **另一主机** 重复 **部署** 小节以前的步骤,安装配置好 kubelet。根据提示,加入到集群。
@@ -213,6 +221,7 @@ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
$ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
```
+
### 14.2.7 查看服务
所有服务启动后,查看本地实际运行的 Docker 容器。这些服务大概分为三类:主节点服务、工作节点服务和其它服务。
@@ -260,6 +269,7 @@ $ kubectl get node -o yaml | grep CIDR
```bash
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.1/Documentation/kube-flannel.yml
```
+
### 14.2.10 master 节点默认不能运行 pod
如果用 `kubeadm` 部署一个单节点集群,默认情况下无法使用,请执行以下命令解除限制
@@ -277,6 +287,7 @@ $ kubectl taint nodes --all node-role.kubernetes.io/master-
...
```
+
### 14.2.11 参考文档
* [官方文档](https://kubernetes.io/zh/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)
diff --git a/14_kubernetes_setup/14.4_kind.md b/14_kubernetes_setup/14.4_kind.md
index 645fb02..5e0bf4c 100644
--- a/14_kubernetes_setup/14.4_kind.md
+++ b/14_kubernetes_setup/14.4_kind.md
@@ -20,6 +20,7 @@ Kind 是一个二进制文件,并在 PATH 中即可使用。以下是不同系
```bash
brew install kind
```
+
#### Linux / Windows
可以下载二进制文件:
@@ -31,6 +32,7 @@ curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
```
+
### 14.4.3 创建集群
最简单的创建方式:
@@ -43,6 +45,7 @@ kind create cluster
```bash
kind create cluster --name my-cluster
```
+
### 14.4.4 与集群交互
Kind 会自动将 kubeconfig 合并到 `~/.kube/config`。
@@ -51,6 +54,7 @@ Kind 会自动将 kubeconfig 合并到 `~/.kube/config`。
kubectl cluster-info --context kind-kind
kubectl get nodes
```
+
### 14.4.5 高级用法:配置集群
创建一个 `kind-config.yaml` 来定制集群,例如映射端口到宿主机:
@@ -72,6 +76,7 @@ nodes:
```bash
kind create cluster --config kind-config.yaml
```
+
### 14.4.6 删除集群
```bash
diff --git a/14_kubernetes_setup/14.5_k3s.md b/14_kubernetes_setup/14.5_k3s.md
index d82352d..e7c9d88 100644
--- a/14_kubernetes_setup/14.5_k3s.md
+++ b/14_kubernetes_setup/14.5_k3s.md
@@ -32,6 +32,7 @@ sudo k3s kubectl get nodes
NAME STATUS ROLES AGE VERSION
k3s-master Ready control-plane,master 1m v1.35.1+k3s1
```
+
### 14.5.3 快速使用
K3s 内置了 `kubectl` 命令 (通过 `k3s kubectl` 调用),为了方便,通常会建立别名或配置 `KUBECONFIG`。
@@ -45,6 +46,7 @@ export KUBECONFIG=/etc/rancher/k3s/k3s.yaml
kubectl get pods -A
```
+
### 14.5.4 清理卸载
```bash
diff --git a/14_kubernetes_setup/14.6_systemd.md b/14_kubernetes_setup/14.6_systemd.md
index 579772a..413a5b1 100644
--- a/14_kubernetes_setup/14.6_systemd.md
+++ b/14_kubernetes_setup/14.6_systemd.md
@@ -30,6 +30,7 @@
/etc/systemd/system/kube-proxy.service
/etc/systemd/system/kube-apiserver.service
```
+
#### 常用命令
```bash
@@ -48,6 +49,7 @@ sudo systemctl status kubelet
# 设置开机自启
sudo systemctl enable kubelet
```
+
### 参考资源
详细的部署步骤和配置说明,可以参考以下项目:
diff --git a/14_kubernetes_setup/14.7_dashboard.md b/14_kubernetes_setup/14.7_dashboard.md
index 2789e16..dc630c3 100644
--- a/14_kubernetes_setup/14.7_dashboard.md
+++ b/14_kubernetes_setup/14.7_dashboard.md
@@ -11,6 +11,7 @@
```bash
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
```
+
### 14.7.2 访问
通过命令行代理访问,执行以下命令:
diff --git a/14_kubernetes_setup/14.8_kubectl.md b/14_kubernetes_setup/14.8_kubectl.md
index 766933f..6a5aee0 100644
--- a/14_kubernetes_setup/14.8_kubectl.md
+++ b/14_kubernetes_setup/14.8_kubectl.md
@@ -7,6 +7,7 @@
kubectl [flags]
kubectl [command]
```
+
### 14.8.1 get
显示一个或多个资源
diff --git a/15_etcd/15.4_etcdctl.md b/15_etcd/15.4_etcdctl.md
index 5ed6715..cf639a0 100644
--- a/15_etcd/15.4_etcdctl.md
+++ b/15_etcd/15.4_etcdctl.md
@@ -80,6 +80,7 @@ OPTIONS:
--user="" username[:password] for authentication (prompt if password is not supplied)
-w, --write-out="simple" set the output format (fields, json, protobuf, simple, table)
```
+
### 15.4.1 数据库操作
数据库操作围绕对键值和目录的 CRUD (符合 REST 风格的一套操作:Create) 完整生命周期的管理。
@@ -94,6 +95,7 @@ etcd 在键的组织上采用了层次化的空间结构 (类似于文件系统
$ etcdctl put /testdir/testkey "Hello world"
OK
```
+
#### get
获取指定键的值。例如
@@ -119,6 +121,7 @@ hello
$ etcdctl del testkey
1
```
+
### 15.4.2 非数据库操作
#### watch
@@ -133,6 +136,7 @@ PUT
testkey
2
```
+
#### member
通过 `list`、`add`、`update`、`remove` 命令列出、添加、更新、删除 etcd 实例到 etcd 集群中。
diff --git a/16_cloud/16.2_tencentCloud.md b/16_cloud/16.2_tencentCloud.md
index b14d960..1775d01 100644
--- a/16_cloud/16.2_tencentCloud.md
+++ b/16_cloud/16.2_tencentCloud.md
@@ -35,6 +35,7 @@
export KUBECONFIG=/path/to/kubeconfig.yaml
kubectl cluster-info
```
+
#### 2. 部署容器应用
创建 Deployment 部署应用:
@@ -67,6 +68,7 @@ kubectl apply -f deployment.yaml
kubectl get pods
kubectl get svc
```
+
#### 3. 管理镜像
通过腾讯云容器镜像服务 (TCR) 存储和管理私有镜像:
@@ -81,6 +83,7 @@ docker tag my-app:latest ccr.ccs.tencentyun.com/namespace/my-app:latest
# 推送镜像到腾讯云
docker push ccr.ccs.tencentyun.com/namespace/my-app:latest
```
+
### 腾讯云 Docker 镜像加速器配置
为了加快镜像拉取速度,腾讯云提供了镜像加速服务。配置方法如下:
@@ -116,6 +119,7 @@ sudo systemctl restart docker
# 查看镜像源是否生效
docker info | grep -A 5 "Registry Mirrors"
```
+
#### Windows/Mac 配置
对于 Docker Desktop,在设置界面中:
@@ -167,6 +171,7 @@ docker push ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
FROM ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
RUN echo "使用腾讯云镜像作为基础镜像"
```
+
#### TKE 集群中使用 TCR 镜像
配置镜像拉取凭证后,在 Deployment 中直接引用 TCR 镜像:
diff --git a/16_cloud/16.3_alicloud.md b/16_cloud/16.3_alicloud.md
index 8b84ca9..0c2ae26 100644
--- a/16_cloud/16.3_alicloud.md
+++ b/16_cloud/16.3_alicloud.md
@@ -37,6 +37,7 @@
export KUBECONFIG=/path/to/kubeconfig.yaml
kubectl get nodes
```
+
#### 2. 部署容器应用
通过 Deployment 部署应用示例:
@@ -73,6 +74,7 @@ kubectl apply -f deployment.yaml
kubectl get pods -o wide
kubectl logs
```
+
#### 3. 暴露服务
创建 Service 暴露应用:
@@ -96,6 +98,7 @@ spec:
kubectl apply -f service.yaml
kubectl get svc web-service
```
+
### 阿里云 Docker 镜像加速器配置
为了加快从阿里云镜像源拉取官方镜像的速度,可以配置镜像加速器。阿里云为容器服务 ACK 用户提供了免费的镜像加速服务。
@@ -132,6 +135,7 @@ sudo systemctl restart docker
```bash
docker info | grep -A 5 "Registry Mirrors"
```
+
#### Windows/Mac 配置
在 Docker Desktop 的 Settings 中:
@@ -146,6 +150,7 @@ docker info | grep -A 5 "Registry Mirrors"
docker pull nginx:latest
time docker pull alpine:latest
```
+
### 阿里云容器镜像服务:ACR
阿里云容器镜像服务 (ACR, Container Registry) 是企业级的容器镜像存储和分发平台:
@@ -183,6 +188,7 @@ FROM registry.cn-hangzhou.aliyuncs.com/myapp/my-app:v1.0
COPY . /app
RUN echo "已成功使用阿里云镜像"
```
+
#### ACK 集群中使用 ACR 镜像
在 ACK 集群中,需要先配置镜像拉取凭证(Secret),然后在 Deployment 中引用:
@@ -233,6 +239,7 @@ spec:
- web
topologyKey: kubernetes.io/hostname
```
+
#### 创建镜像拉取凭证
在 ACK 集群中创建 Secret,用于拉取私有镜像:
@@ -249,6 +256,7 @@ kubectl create secret docker-registry acr-secret \
kubectl get secret acr-secret
kubectl describe secret acr-secret
```
+
#### ACR 优势
- 在 ACK 集群中与镜像仓库无缝集成,简化身份认证
diff --git a/17_ecosystem/17.2_coreos_install.md b/17_ecosystem/17.2_coreos_install.md
index d554d1c..0489835 100644
--- a/17_ecosystem/17.2_coreos_install.md
+++ b/17_ecosystem/17.2_coreos_install.md
@@ -26,6 +26,7 @@ passwd:
```bash
$ docker run -i --rm quay.io/coreos/fcct:v0.5.0 --pretty --strict < example.fcc > example.ign
```
+
### 17.2.4 挂载 ISO 启动虚拟机并安装
> 虚拟机需要分配 3GB 以上内存,否则会无法启动。
diff --git a/17_ecosystem/17.3_podman.md b/17_ecosystem/17.3_podman.md
index bfaef79..8c5aa41 100644
--- a/17_ecosystem/17.3_podman.md
+++ b/17_ecosystem/17.3_podman.md
@@ -22,6 +22,7 @@ Podman 支持多种操作系统,安装过程也相对简单。
```bash
$ sudo yum -y install podman
```
+
#### macOS
macOS 上需要安装 Podman Desktop 或通过 Homebrew 安装:
@@ -31,6 +32,7 @@ $ brew install podman
$ podman machine init
$ podman machine start
```
+
### 17.3.3 基本使用
`podman` 的命令行几乎与 `docker` 完全兼容,大多数情况下,你只需将 `docker` 替换为 `podman` 即可。
@@ -42,16 +44,19 @@ $ podman machine start
$ podman run -d -p 80:80 nginx:alpine
```
+
#### 列出容器
```bash
$ podman ps
```
+
#### 构建镜像
```bash
$ podman build -t myimage .
```
+
### 17.3.4 Pods 的概念
与 Docker 不同,Podman 支持“Pod”的概念 (类似于 Kubernetes 的 Pod),允许你在同一个网络命名空间中运行多个容器。
@@ -65,6 +70,7 @@ $ podman pod create --name mypod -p 8080:80
$ podman run -d --pod mypod --name webbing nginx
```
+
### 17.3.5 迁移到 Podman
如果你习惯使用 `docker` 命令,可以简单地设置别名:
@@ -72,6 +78,7 @@ $ podman run -d --pod mypod --name webbing nginx
```bash
$ alias docker=podman
```
+
#### Systemd 集成
Podman 可以生成 systemd 单元文件,让容器像普通系统服务一样管理。
@@ -89,6 +96,7 @@ $ podman generate systemd --name myweb --files --new
$ systemctl --user enable --now container-myweb.service
```
+
#### Podman Compose
虽然 Podman 兼容 Docker Compose,但在某些场景下你可能需要明确使用 `podman-compose`。
diff --git a/17_ecosystem/17.4_buildah.md b/17_ecosystem/17.4_buildah.md
index c32fd1a..ed7df2d 100644
--- a/17_ecosystem/17.4_buildah.md
+++ b/17_ecosystem/17.4_buildah.md
@@ -30,6 +30,7 @@ $ sudo dnf install -y buildah
$ sudo apt-get update
$ sudo apt-get -y install buildah
```
+
### 基础用法示例
#### 1. 从现有的 Dockerfile 构建镜像
diff --git a/17_ecosystem/17.5_skopeo.md b/17_ecosystem/17.5_skopeo.md
index dd3c6be..20c2df8 100644
--- a/17_ecosystem/17.5_skopeo.md
+++ b/17_ecosystem/17.5_skopeo.md
@@ -35,6 +35,7 @@ $ sudo apt-get -y install skopeo
```bash
$ brew install skopeo
```
+
### 基础用法示例
#### 1. 远程检查镜像
diff --git a/18_security/18.1_kernel_ns.md b/18_security/18.1_kernel_ns.md
index 4048b40..5581be9 100644
--- a/18_security/18.1_kernel_ns.md
+++ b/18_security/18.1_kernel_ns.md
@@ -60,6 +60,7 @@ dockremap:165536:65536
```bash
$ sudo systemctl restart docker
```
+
#### 验证映射效果
我们可以运行一个简单的容器并执行 `sleep` 命令,同时在宿主机上观察进程的所有者:
diff --git a/18_security/18.5_other_feature.md b/18_security/18.5_other_feature.md
index 4c1f08f..8106a60 100644
--- a/18_security/18.5_other_feature.md
+++ b/18_security/18.5_other_feature.md
@@ -53,6 +53,7 @@ $ docker run --rm -it \
--security-opt apparmor=custom-nginx-profile \
nginx
```
+
### 18.5.3 容器镜像漏洞静态扫描
现代防护的防御已经不仅仅在运行阶段,而向“左”延伸至了构建与分发时期控制。很多安全隐患并不是用户代码中的直接逻辑异常,而是打包环境或者引入库的基础 `APT` 安装层面潜伏了开源界众所周知的历史漏洞。
diff --git a/18_security/18.6_image_security.md b/18_security/18.6_image_security.md
index c63c0ae..3e2605f 100644
--- a/18_security/18.6_image_security.md
+++ b/18_security/18.6_image_security.md
@@ -41,6 +41,7 @@ trivy image --severity HIGH,CRITICAL \
--exit-code 1 \
myregistry.com/myapp:v1.0.0
```
+
#### Grype - 支持多种软件包的扫描器
Grype 由 Anchore 开发,支持更广泛的软件包管理器和语言。
@@ -67,6 +68,7 @@ grype sbom:sbom.json
# 扫描特定目录
grype dir:/path/to/app
```
+
#### Snyk - 完整的安全平台
Snyk 提供了商业级的安全扫描服务,特别适合企业环境。
@@ -130,6 +132,7 @@ syft dir:/path/to/app -o json > sbom.json
# 从 OCI 镜像档案生成
syft oci-archive:image.tar -o json > sbom.json
```
+
#### CycloneDX 与 SPDX 格式
两种主流的 SBOM 格式:
@@ -173,6 +176,7 @@ syft oci-archive:image.tar -o json > sbom.json
]
}
```
+
#### SBOM 的应用场景
**漏洞关联:**
@@ -249,6 +253,7 @@ cosign verify myregistry.com/myapp:v1.0.0 \
--certificate-identity https://github.com/myorg/myrepo/.github/workflows/build.yml@refs/heads/main \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
```
+
#### Docker Content Trust 与 Notary
Docker Content Trust 使用 Notary 实现镜像签名,是 Docker 官方的签名解决方案。
@@ -276,6 +281,7 @@ docker push --disable-content-trust myregistry.com/myapp:v1.0.0
# 查看签名信息
docker inspect --format='{{.RepoDigests}}' myregistry.com/myapp:v1.0.0
```
+
### 18.6.4 供应链安全最佳实践
#### 1. 基础镜像安全
@@ -289,6 +295,7 @@ RUN apt-get update && apt-get install -y curl
FROM ubuntu:22.04@sha256:a6d2b38300ce017add71440577d5b0a90460d0e6e0e14...(完整 64 位哈希)
RUN apt-get update && apt-get install -y curl=7.68.0-1ubuntu1
```
+
#### 2. 构建时扫描
在 Dockerfile 中集成安全扫描:
@@ -308,6 +315,7 @@ RUN go build -o app .
FROM alpine:3.17@sha256:abcd1234...(请替换为实际完整的 64 位摘要哈希)
COPY --from=builder /app/app /app
```
+
#### 3. 运行时镜像扫描策略
```bash
@@ -320,6 +328,7 @@ trivy image --severity HIGH,CRITICAL \
# 定期扫描已部署的镜像
trivy image --scanners vuln,misconfig registry:5000/myapp:latest
```
+
#### 4. 镜像仓库安全配置
**Harbor(私有镜像仓库)的安全扫描:**
@@ -335,6 +344,7 @@ trivy:
scan_on_push: true # 推送时自动扫描
scan_all: true # 扫描仓库中的所有镜像
```
+
#### 5. 政策执行
在 Kubernetes 环境中使用 Admission Webhook 强制镜像签名和扫描:
@@ -359,6 +369,7 @@ webhooks:
admissionReviewVersions: ["v1"]
sideEffects: None
```
+
### 18.6.5 CI/CD 中集成安全扫描
#### GitHub Actions 工作流示例
@@ -445,6 +456,7 @@ jobs:
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
```
+
#### GitLab CI 工作流示例
```yaml
@@ -509,6 +521,7 @@ push:
only:
- main
```
+
### 18.6.6 常见问题与最佳实践
**Q: 扫描报告中有过时的 CVE,如何处理?**
diff --git a/18_security/README.md b/18_security/README.md
index 813261d..e014fdf 100644
--- a/18_security/README.md
+++ b/18_security/README.md
@@ -23,6 +23,7 @@ flowchart LR
Proc --> Mech
end
```
+
## 本章内容
本章涵盖 Docker 安全的多个层面,从内核隔离机制到运行时防护和供应链安全。
diff --git a/19_observability/19.1_prometheus.md b/19_observability/19.1_prometheus.md
index 644be04..8e9862e 100644
--- a/19_observability/19.1_prometheus.md
+++ b/19_observability/19.1_prometheus.md
@@ -48,6 +48,7 @@ scrape_configs:
rule_files:
- /etc/prometheus/rules.yml
```
+
#### 2. 编写 Docker Compose 文件
创建 `compose.yaml` (或 `docker-compose.yml`):
@@ -105,6 +106,7 @@ networks:
volumes:
prometheus_data:
```
+
#### 3. 启动服务
```bash
diff --git a/19_observability/19.2_elk.md b/19_observability/19.2_elk.md
index 767549e..352110d 100644
--- a/19_observability/19.2_elk.md
+++ b/19_observability/19.2_elk.md
@@ -71,6 +71,7 @@ volumes:
networks:
logging:
```
+
#### 2. 配置 Fluentd
创建 `fluentd/conf/fluent.conf`:
@@ -101,6 +102,7 @@ networks:
```
+
#### 3. 配置应用容器使用 fluentd 驱动
启动一个测试容器,指定日志驱动为 `fluentd`:
diff --git a/19_observability/19.3_performance_optimization.md b/19_observability/19.3_performance_optimization.md
index 35792e5..bc20b89 100644
--- a/19_observability/19.3_performance_optimization.md
+++ b/19_observability/19.3_performance_optimization.md
@@ -91,6 +91,7 @@ done
# MEM % 接近 100%:容器即将 OOM,需要增加内存或排查内存泄漏
# 如果 NET I/O 中 dropped 为非零:网络拥塞或丢包
```
+
### 19.3.3 cAdvisor 容器监控系统
cAdvisor 是 Google 开发的容器监控工具,提供比 `docker stats` 更详细的性能数据。
@@ -150,6 +151,7 @@ scrape_configs:
- targets: ['localhost:8080']
metrics_path: '/metrics'
```
+
### 19.3.4 Prometheus 容器监控配置
使用 Prometheus 和 node-exporter 进行长期的容器性能监控。
@@ -275,6 +277,7 @@ container_memory_cache_bytes / container_memory_usage_bytes
# 按镜像统计容器数
count(container_memory_usage_bytes) by (image)
```
+
### 19.3.5 容器 OOM 排查与内存限制调优
#### OOM 问题诊断
@@ -293,6 +296,7 @@ docker logs 2>&1 | grep -i "out of memory\|oom"
dmesg | grep -i "oom\|kill"
journalctl -u docker -n 100 | grep -i "oom"
```
+
#### 内存泄漏检测
使用专项工具分析应用内存使用:
@@ -347,6 +351,7 @@ jstat -gc 1000 # 每秒采样一次
# S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU
# 6144 6144 0 6144 39424 12288 149504 84320 50552 47689 6464 5989
```
+
#### 内存限制最佳实践
```bash
@@ -385,6 +390,7 @@ services:
memory: 2G
memory_reservation: 1G # 预留 1GB,允许突发到 2GB
```
+
### 19.3.6 镜像体积优化与多阶段构建
#### 镜像体积分析工具
@@ -411,6 +417,7 @@ chmod +x hadolint
# 检查 Dockerfile 最佳实践
./hadolint Dockerfile
```
+
#### 多阶段构建最佳实践
**Go 应用的最小化镜像构建:**
@@ -528,6 +535,7 @@ EXPOSE 5000
CMD ["python", "app.py"]
```
+
#### 镜像体积优化检查清单
```bash
@@ -558,6 +566,7 @@ RUN apt-get update && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
```
+
### 19.3.7 常见性能问题及解决方案
**问题 1: 容器频繁被 OOM 杀死**
diff --git a/20_cases_os/20.1_busybox.md b/20_cases_os/20.1_busybox.md
index 60ab74b..815dcaf 100644
--- a/20_cases_os/20.1_busybox.md
+++ b/20_cases_os/20.1_busybox.md
@@ -30,6 +30,7 @@ $ docker image ls
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
busybox latest e72ac664f4f0 6 weeks ago 2.433 MB
```
+
### 20.1.3 运行 busybox
启动一个 `busybox` 容器,并在容器中执行 `grep` 命令。
diff --git a/20_cases_os/20.2_alpine.md b/20_cases_os/20.2_alpine.md
index e47a13e..c2c2ae2 100644
--- a/20_cases_os/20.2_alpine.md
+++ b/20_cases_os/20.2_alpine.md
@@ -25,6 +25,7 @@ debian latest 4d6ce913b130 84.98 MB
ubuntu latest b39b81afc8ca 188.3 MB
centos latest 8efe422e6104 210 MB
```
+
### 20.2.2 获取并使用官方镜像
由于镜像很小,下载时间往往很短,读者可以直接使用 `docker run` 指令直接运行一个 `Alpine` 容器,并指定运行的 Linux 指令,例如:
@@ -33,6 +34,7 @@ centos latest 8efe422e6104 210 MB
$ docker run alpine echo '123'
123
```
+
### 20.2.3 迁移至 Alpine 基础镜像
目前,大部分 Docker 官方镜像都已经支持 `Alpine` 作为基础镜像,可以很容易进行迁移。
@@ -60,6 +62,7 @@ $ apk --update add --no-cache
RUN sed -i "s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g" /etc/apk/repositories \
&& apk add --no-cache
```
+
### 20.2.4 相关资源
* `Alpine` 官网:https://www.alpinelinux.org/
diff --git a/20_cases_os/20.4_centos.md b/20_cases_os/20.4_centos.md
index 172fac3..ae54d52 100644
--- a/20_cases_os/20.4_centos.md
+++ b/20_cases_os/20.4_centos.md
@@ -28,6 +28,7 @@ Status: Downloaded newer image for centos:7
[root@43eb3b194d48 /]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
```
+
### 20.4.2 Fedora 系统简介
下图直观地展示了本节内容:
diff --git a/21_case_devops/21.1_devops_workflow.md b/21_case_devops/21.1_devops_workflow.md
index bcf1bf7..e167044 100644
--- a/21_case_devops/21.1_devops_workflow.md
+++ b/21_case_devops/21.1_devops_workflow.md
@@ -35,6 +35,7 @@ WORKDIR /app
COPY --from=builder /app/main .
CMD ["./main"]
```
+
#### 2. GitLab CI 配置
GitLab CI(`.gitlab-ci.yml`)配置如下:
@@ -74,6 +75,7 @@ deploy_staging:
only:
- develop
```
+
### 21.1.3 最佳实践
1. **不可变基础设施**:一旦镜像构建完成,在各个环境(Dev、Staging、Prod)中都应该使用同一个镜像 tag(通常是 commit hash),而不是重新构建。
diff --git a/21_case_devops/21.2_github_actions.md b/21_case_devops/21.2_github_actions.md
index 20c7274..f11e1fe 100644
--- a/21_case_devops/21.2_github_actions.md
+++ b/21_case_devops/21.2_github_actions.md
@@ -46,6 +46,7 @@ jobs:
with:
args: go version
```
+
## 21.2.3 参考资料
* [Actions Docs](https://docs.github.com/en/actions)
diff --git a/21_case_devops/21.3_drone.md b/21_case_devops/21.3_drone.md
index 1c6d282..584c3d4 100644
--- a/21_case_devops/21.3_drone.md
+++ b/21_case_devops/21.3_drone.md
@@ -70,6 +70,7 @@ trigger:
├── .drone.yml
└── app.go
```
+
## 21.3.3 推送项目源代码到 GitHub
```bash
@@ -79,6 +80,7 @@ git commit -m "test drone ci"
git push origin master
```
+
## 21.3.4 查看项目构建过程及结果
打开我们部署好的 `Drone` 网站或者 Drone Cloud,即可看到构建结果。
diff --git a/21_case_devops/21.6_vsCode.md b/21_case_devops/21.6_vsCode.md
index cdf5bf9..7e266a3 100644
--- a/21_case_devops/21.6_vsCode.md
+++ b/21_case_devops/21.6_vsCode.md
@@ -39,6 +39,7 @@ VS Code 会拉取镜像并启动容器,随后你就可以在容器内运行:
```bash
go test ./...
```
+
## 21.6.3 结合 Docker Compose(可选)
如果项目同时依赖数据库/缓存(例如 Postgres/Redis),可以使用 `dockerComposeFile`
diff --git a/21_case_devops/21.7_practical_examples.md b/21_case_devops/21.7_practical_examples.md
index d05408c..f52d333 100644
--- a/21_case_devops/21.7_practical_examples.md
+++ b/21_case_devops/21.7_practical_examples.md
@@ -120,6 +120,7 @@ require (
// 如果需要依赖
)
```
+
#### 带依赖的 Go 应用
**应用代码(使用 Gin 框架):**
@@ -182,6 +183,7 @@ EXPOSE 8080
CMD ["./app"]
```
+
### 21.7.2 Rust 应用的最小化镜像构建
Rust 因其性能和安全性在系统级应用中备受青睐。
@@ -273,6 +275,7 @@ curl http://localhost:8080/health | jq .
# Rust 应用通常比 Go 更小:5-20MB(取决于依赖)
docker images rust-app
```
+
### 21.7.3 数据库容器化最佳实践
#### PostgreSQL 生产部署
@@ -455,6 +458,7 @@ services:
volumes:
postgres_data:
```
+
#### MySQL/MariaDB 部署
```dockerfile
@@ -495,6 +499,7 @@ server_id = 1
log_bin = mysql-bin
binlog_format = ROW
```
+
#### Redis 缓存部署
```dockerfile
@@ -545,6 +550,7 @@ client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
```
+
### 21.7.4 微服务架构的 Docker Compose 编排
**三层微服务架构示例:**
@@ -736,6 +742,7 @@ server {
}
}
```
+
### 21.7.5 使用 VS Code Dev Containers
Dev Containers 让整个开发环境容器化,提升团队一致性。
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5e1f8f8..88dbf9e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -33,6 +33,7 @@ $ git rebase upstream/master
$ git push -f origin master
```
+
## 排版规范
本开源书籍遵循[中文排版指南](https://github.com/mzlogin/chinese-copywriting-guidelines)规范。
diff --git a/appendix/best_practices.md b/appendix/best_practices.md
index 98b5b38..73c4667 100644
--- a/appendix/best_practices.md
+++ b/appendix/best_practices.md
@@ -44,6 +44,7 @@ RUN apt-get update && apt-get install -y \
mercurial \
subversion
```
+
#### 构建缓存
在镜像的构建过程中,Docker 会遍历 `Dockerfile` 文件中的指令,然后按顺序执行。在执行每条指令之前,Docker 都会在缓存中查找是否已经存在可重用的镜像,如果有就使用现存的镜像,不再重复创建。如果你不想在构建过程中使用缓存,你可以在 `docker build` 命令中使用 `--no-cache=true` 选项。
@@ -300,6 +301,7 @@ $ docker run postgres postgres --help
```bash
$ docker run --rm -it postgres bash
```
+
#### VOLUME
`VOLUME` 指令用于暴露任何数据库存储文件,配置文件,或容器创建的文件和目录。强烈建议使用 `VOLUME` 来管理镜像中的可变部分和用户可以改变的部分。
diff --git a/appendix/debug.md b/appendix/debug.md
index 16af33a..61ecb95 100644
--- a/appendix/debug.md
+++ b/appendix/debug.md
@@ -22,6 +22,7 @@ $ sudo kill -SIGHUP $(pidof dockerd)
$ sudo dmesg |grep dockerd
$ sudo dmesg |grep runc
```
+
### Docker 不响应时处理
可以杀死 dockerd 进程查看其堆栈调用情况。
@@ -29,6 +30,7 @@ $ sudo dmesg |grep runc
```bash
$ sudo kill -SIGUSR1 $(pidof dockerd)
```
+
### 重置 Docker 本地数据
*注意,本操作会移除所有的 Docker 本地数据,包括镜像和容器等。*
@@ -43,6 +45,7 @@ $ docker system prune
```bash
$ sudo rm -rf /var/lib/docker
```
+
### 常见故障排查
#### 容器启动失败
diff --git a/appendix/faq/README.md b/appendix/faq/README.md
index 21237ea..64170aa 100644
--- a/appendix/faq/README.md
+++ b/appendix/faq/README.md
@@ -52,6 +52,7 @@
```bash
docker inspect --format '{{ .State.Pid }}'
```
+
### 如何获取某个容器的 IP 地址?
答:可以使用
@@ -59,6 +60,7 @@ docker inspect --format '{{ .State.Pid }}'
```bash
docker inspect --format '{{ .NetworkSettings.IPAddress }}'
```
+
### 如何给容器指定一个固定 IP 地址,而不是每次重启容器 IP 地址都会变?
答:使用以下命令启动容器可以使容器 IP 固定不变
@@ -68,6 +70,7 @@ $ docker network create -d bridge --subnet 172.25.0.0/16 my-net
$ docker run --network=my-net --ip=172.25.3.3 -itd --name=my-container busybox
```
+
### 如何临时退出一个正在交互的容器的终端,而不终止它?
答:按 `Ctrl-p Ctrl-q`。如果按 `Ctrl-c` 往往会让容器内应用进程终止,进而会终止容器。
@@ -123,6 +126,7 @@ tmpfs 48G 228K 48G 1% /dev/shm
lrwxrwxrwx. 1 root root 15 11月 17 13:43 docker -> /storage/docker
[root@s26 lib]# service docker start
```
+
### 使用内存和 swap 限制启动容器时候报警告:“WARNING:Your kernel does not support cgroup swap limit。WARNING:Your kernel does not support swap limit capabilities。Limitation discarded。”?
答:这是因为系统默认没有开启对内存和 swap 使用的统计功能,引入该功能会带来性能的下降。要开启该功能,可以采取如下操作:
@@ -198,6 +202,7 @@ $ sudo ip netns show
```bash
$ sudo ip netns exec 1234 ifconfig eth0 172.17.0.100/16
```
+
### 如何获取容器绑定到本地那个 veth 接口上?
答:Docker 容器启动后,会通过 veth 接口对连接到本地网桥,veth 接口命名跟容器命名毫无关系,十分难以找到对应关系。
diff --git a/appendix/learning_roadmap.md b/appendix/learning_roadmap.md
index 1845d15..135c03d 100644
--- a/appendix/learning_roadmap.md
+++ b/appendix/learning_roadmap.md
@@ -53,6 +53,7 @@ Docker 安装配置
3. 提交修改为新镜像
4. 推送镜像到 Docker Hub(需创建账户)
```
+
#### 第二阶段:核心开发(2-6 周)
**学习目标:**
@@ -135,6 +136,7 @@ Docker Compose
- 数据持久化
- 备份恢复策略
```
+
#### 第三阶段:生产优化(6-12 周)
**学习目标:**
@@ -248,6 +250,7 @@ CI/CD 集成
- 部署有状态应用
- 配置持久化存储
```
+
#### 第四阶段:专家深造(12+ 周)
**学习目标:**
@@ -376,6 +379,7 @@ Kubernetes 进阶 (Week 24-36)
├── 成本优化
└── 开源贡献
```
+
### 推荐学习资源
#### 官方文档
@@ -475,6 +479,7 @@ docker volume / network / service
docker compose up / down / logs / ps
docker stats / events / inspect
```
+
#### Kubernetes 认证
**认证路径:**
@@ -561,6 +566,7 @@ A(要点):
4. SELinux / AppArmor(强制访问控制)
```
+
#### Dockerfile 面试题
**Q4: 如何优化 Docker 镜像大小?**
@@ -614,6 +620,7 @@ CMD ["--port", "8000"]
# 运行 docker run image --debug 会执行:
# python app.py --debug
```
+
#### 网络和存储面试题
**Q6: Docker 网络驱动的区别?**
@@ -664,6 +671,7 @@ tmpfs:
- 用于临时文件、敏感数据
- 性能最好,重启丢失
```
+
#### 安全和生产面试题
**Q8: 如何提高 Docker 安全性?**
@@ -758,6 +766,7 @@ A(要点):
5. 触发 ArgoCD / Flux 自动部署
6. 监控部署状态
```
+
### 学习进度跟踪模板
```markdown
@@ -805,6 +814,7 @@ A(要点):
- [ ] 监控和日志系统
- [ ] CI/CD 流程实现
```
+
### 快速参考速查表
**常用命令速查:**
diff --git a/appendix/repo/centos.md b/appendix/repo/centos.md
index 8453c43..2fce379 100644
--- a/appendix/repo/centos.md
+++ b/appendix/repo/centos.md
@@ -25,6 +25,7 @@ $ docker run --name rocky -it rockylinux:9 bash
```bash
$ docker run --name centos -it centos:7 bash
```
+
### Dockerfile
请到 [CentOS 官方镜像文档目录](https://github.com/docker-library/docs/tree/master/centos) 查看。
diff --git a/appendix/repo/minio.md b/appendix/repo/minio.md
index 44a88a1..4ccb4a5 100644
--- a/appendix/repo/minio.md
+++ b/appendix/repo/minio.md
@@ -13,6 +13,7 @@ MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结
```bash
$ docker run -d -p 9000:9000 -p 9090:9090 minio/minio server /data --console-address ':9090'
```
+
### 离线部署
许多生产环境是一般是没有公网资源的,这就需要从有公网资源的服务器上把镜像导出,然后导入到需要运行镜像的内网服务器。
@@ -33,6 +34,7 @@ $ docker save -o minio.tar minio/minio:latest
```bash
$ docker load -i minio.tar
```
+
#### 运行 minio
- 把 `/mnt/data` 改成要替换的数据目录
@@ -49,6 +51,7 @@ $ sudo docker run -d -p 9000:9000 -p 9090:9090 --name minio1 \
--restart=always \
minio/minio server /data --console-address ':9090'
```
+
#### 访问 web 管理页面
打开 `http://:9090` 访问 Web 控制台。
diff --git a/appendix/repo/mongodb.md b/appendix/repo/mongodb.md
index fe363b1..dbc7a1c 100644
--- a/appendix/repo/mongodb.md
+++ b/appendix/repo/mongodb.md
@@ -33,6 +33,7 @@ $ docker run -it --rm \
mongo \
sh -c 'exec mongo "some-mongo:27017/test"'
```
+
### Dockerfile
请到 [Mongo 官方镜像文档目录](https://github.com/docker-library/docs/tree/master/mongo) 查看。
diff --git a/appendix/repo/nginx.md b/appendix/repo/nginx.md
index eb8b060..e09ad6e 100644
--- a/appendix/repo/nginx.md
+++ b/appendix/repo/nginx.md
@@ -39,6 +39,7 @@ $ docker run -d \
-v /path/nginx.conf:/etc/nginx/nginx.conf:ro \
nginx
```
+
### Dockerfile
请到 [Nginx 官方镜像文档目录](https://github.com/docker-library/docs/tree/master/nginx) 查看。
diff --git a/appendix/repo/nodejs.md b/appendix/repo/nodejs.md
index 3e428d1..8f50b25 100644
--- a/appendix/repo/nodejs.md
+++ b/appendix/repo/nodejs.md
@@ -35,6 +35,7 @@ $ docker run -it --rm \
node:20-alpine \
node your-daemon-or-script.js
```
+
### Dockerfile
请到 [Node 官方镜像文档目录](https://github.com/docker-library/docs/tree/master/node) 查看。
diff --git a/appendix/repo/php.md b/appendix/repo/php.md
index 32a02fc..2d7e5ba 100644
--- a/appendix/repo/php.md
+++ b/appendix/repo/php.md
@@ -13,6 +13,7 @@
```bash
$ docker run -it --rm -v "$PWD":/app -w /app php:alpine php your-script.php
```
+
### Dockerfile
请到 [PHP 官方镜像文档目录](https://github.com/docker-library/docs/tree/master/php) 查看。
diff --git a/appendix/repo/redis.md b/appendix/repo/redis.md
index bc7fec7..59cd4e6 100644
--- a/appendix/repo/redis.md
+++ b/appendix/repo/redis.md
@@ -40,6 +40,7 @@ $ docker run -it --rm \
redis \
sh -c 'exec redis-cli -h some-redis'
```
+
### Dockerfile
请到 [Redis 官方镜像文档目录](https://github.com/docker-library/docs/tree/master/redis) 查看。
diff --git a/appendix/repo/ubuntu.md b/appendix/repo/ubuntu.md
index 9b221b7..f2a6b63 100644
--- a/appendix/repo/ubuntu.md
+++ b/appendix/repo/ubuntu.md
@@ -14,6 +14,7 @@
$ docker run --name some-ubuntu -it ubuntu:20.04
root@523c70904d54:/#
```
+
### Dockerfile
请到 [Ubuntu 官方镜像文档目录](https://github.com/docker-library/docs/tree/master/ubuntu) 查看。