fix(content): harden Docker practice guide

This commit is contained in:
yeasy
2026-06-16 21:23:21 -07:00
parent f4e684afeb
commit 9fdffa9d91
67 changed files with 343 additions and 278 deletions
+1 -4
View File
@@ -11,12 +11,9 @@
"forwardPorts": [
4000
],
"runArgs": [
"--cap-add=SYS_ADMIN"
],
"postStartCommand": [
"sh",
"-cx",
"pwd ; cd /workspaces/docker_practice ; mkdir -p ${PWD}/node_modules; mkdir -p ${PWD}/_book; mount --bind /srv/gitbook/node_modules ${PWD}/node_modules ; mount --bind /mnt ${PWD}/_book"
"pwd ; cd /workspaces/docker_practice ; mkdir -p ${PWD}/node_modules ${PWD}/_book"
]
}
+6
View File
@@ -15,6 +15,12 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Check project rules
run: python3 check_project_rules.py
- name: Check release metadata
run: npm test
- name: Install Chromium and CJK fonts
uses: browser-actions/setup-chrome@v2
with:
+2
View File
@@ -18,6 +18,8 @@ jobs:
- uses: actions/checkout@v6
- name: Check project rules
run: python3 check_project_rules.py
- name: Check release metadata
run: npm test
- name: Install Chromium and CJK fonts
uses: browser-actions/setup-chrome@v2
with:
+6
View File
@@ -22,6 +22,12 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Check project rules
run: python3 check_project_rules.py
- name: Check release metadata
run: npm test
- name: Install Chromium and CJK fonts
uses: browser-actions/setup-chrome@v2
with:
+1
View File
@@ -14,6 +14,7 @@ package-lock.json
docker-compose.override.yml
06_repository/demo/auth/nginx.htpasswd
11_compose/demo/wordpress/secrets/
# Editor configs
.obsidian/
+3 -1
View File
@@ -2,11 +2,13 @@
> **版本说明**本节示例基于 Docker v29.x 编写示例中使用的 `nginx:alpine` 镜像标签为演示用途请查阅 [Docker Hub - nginx](https://hub.docker.com/_/nginx) 确认最新可用版本。
开始前请先完成 [ 3 章安装 Docker](../03_install/README.md)并确认 `docker version` `docker run hello-world` 可以正常执行若你只是先浏览流程可以读完本节后再回到安装章实践
本节将通过一个简单的 Web 应用例子带你快速体验 Docker 的核心流程构建镜像运行容器
### 为什么选择 Nginx + HTML 作为入门例子
在学习 Docker 之前我们先来理解为什么这个例子是最适合初学者Docker 的核心价值在于**一致性交付**无论你在本地云端还是他人的机器上运行容器应用行为都是完全一致这个 Nginx + 静态 HTML 的例子之所以被广泛采用是因为它展现了 Docker 工作流的三个核心阶段
在学习 Docker 之前我们先来理解为什么这个例子适合初学者Docker 的核心价值在于**一致性交付**在相同镜像CPU 架构内核能力配置和外部依赖都满足的前提下应用行为可以保持高度一致这个 Nginx + 静态 HTML 的例子之所以被广泛采用是因为它展现了 Docker 工作流的三个核心阶段
1. **镜像定义Image Layer**通过 Dockerfile 描述如何把应用打包成一个自包含的单元
2. **镜像构建Build**执行 `docker build`Docker 根据 Dockerfile 逐层构建镜像
+2 -2
View File
@@ -4,11 +4,11 @@ Docker 是彻底改变了软件开发和交付方式的革命性技术。本节
### 1.2.1 一句话理解 Docker
> **Docker 是一种轻量级的虚拟化技术它让应用程序及其依赖环境可以被打包成一个标准化的单元任何地方都能一致地运行** 如果用一个生活中的类比**Docker 之于软件就像集装箱之于货物**
> **Docker 是一种轻量级的虚拟化技术它让应用程序及其依赖环境可以被打包成一个标准化的单元满足架构内核能力和外部依赖前提的环境中高度一致地运行** 如果用一个生活中的类比**Docker 之于软件就像集装箱之于货物**
在集装箱发明之前货物的运输是一件麻烦的事情不同的货物需要不同的包装不同的装卸方式换一种运输工具就要重新装卸集装箱的出现改变了这一切无论里面装的是什么集装箱的外形是标准的可以用同样的方式装卸堆放和运输
Docker 做的事情类似无论你的应用是用 PythonJavaNode.js 还是其他语言写的无论它需要什么样的依赖库和环境一旦被打包成 Docker 镜像就可以用同样的方式在任何支持 Docker 的机器上运行
Docker 做的事情类似无论你的应用是用 PythonJavaNode.js 还是其他语言写的无论它需要什么样的依赖库和环境一旦被打包成 Docker 镜像就可以用同样的方式在兼容的 Docker 环境中运行
### 1.2.2 Docker 的核心价值
+3 -3
View File
@@ -63,10 +63,10 @@ flowchart LR
#### 1. 环境一致性
Docker 镜像包含了应用运行所需的 **一切**代码运行时系统工具配置这意味着
Docker 镜像包含了应用运行所需的大部分用户态依赖代码运行时系统工具和默认配置它不包含宿主机内核也不能消除 CPU 架构内核能力外部服务网络卷和运行时配置差异这意味着
- 开发环境和生产环境完全一致
- 不会再有 在我机器上能跑 的问题
- 开发环境和生产环境可以显著减少差异
- 大幅降低 在我机器上能跑 的问题
- 新人入职一条命令就能启动开发环境
```bash
+1 -3
View File
@@ -50,9 +50,7 @@ $ sudo dnf -y install dnf-plugins-core
执行下面的命令添加 `dnf` 软件源
```bash
$ sudo dnf config-manager \
--add-repo \
https://download.docker.com/linux/fedora/docker-ce.repo
$ sudo dnf config-manager addrepo --from-repofile https://download.docker.com/linux/fedora/docker-ce.repo
```
如果需要测试版本的 Docker 请使用以下命令
+2 -2
View File
@@ -80,7 +80,7 @@ Registry Mirrors:
### 3.9.6 Kubernetes 官方镜像地址迁移
可以登录 [阿里云容器镜像服务](https://www.aliyun.com/product/acr?source=5176.11533457&userCode=8lx5zmtu&type=copy),在 **镜像中心** -> **镜像搜索** 中查找。
可以登录 [阿里云容器镜像服务](https://www.aliyun.com/product/acr),在 **镜像中心** -> **镜像搜索** 中查找。
Kubernetes 社区已将官方镜像地址从 `k8s.gcr.io` 迁移到 `registry.k8s.io`建议优先使用新地址
@@ -108,4 +108,4 @@ $ docker pull registry.k8s.io/xxx
某些云服务商提供了 **仅供内部** 访问的镜像服务当您的 Docker 运行在云平台时可以选择它们
* [腾讯云 `https://mirror.ccs.tencentyun.com`](https://cloud.tencent.com/act/cps/redirect?redirect=10058&cps_key=3a5255852d5db99dcd5da4c72f05df61)
* [腾讯云 `https://mirror.ccs.tencentyun.com`](https://cloud.tencent.com/product/tke)
+1 -1
View File
@@ -18,7 +18,7 @@ Docker Engine 主要提供 `stable` 和 `test` 两个更新频道;`test.docker
**开发环境**本地开发机测试服务器
- 使用**脚本自动安装****包管理器直接安装**
- 配置 **Docker 官方源后** 使用包管理器安装或在一次性测试环境使用官方脚本自动安装
- 如果你想快速上手官方脚本`get.docker.com`是最便捷的选择
- 国内用户注意这一步一定要选对镜像源否则网络卡顿会严重影响体验
+6 -14
View File
@@ -1,4 +1,4 @@
# syntax = docker/dockerfile:experimental
# syntax=docker/dockerfile:1
FROM node:alpine as builder
@@ -6,24 +6,16 @@ WORKDIR /app
COPY package.json /app/
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
--mount=type=cache,target=/root/.npm,id=npm_cache \
npm i --registry=https://registry.npmmirror.com
RUN --mount=type=cache,target=/root/.npm,id=npm_cache \
npm install --registry=https://registry.npmmirror.com
COPY src /app/src
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
# --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \
npm run build
RUN npm run build
FROM nginx:alpine
# COPY --from=builder /app/dist /app/dist
# 为了更直观的说明 from source 指令这里使用 RUN 指令
RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
# --mount=type=cache,target/tmp/dist,from=my_app_dist,sharing=locked \
mkdir -p /app/dist && cp -r /tmp/dist/* /app/dist
COPY --from=builder /app/dist /app/dist
RUN --mount=type=bind,from=php:alpine,source=/usr/local/bin/docker-php-entrypoint,target=/docker-php-entrypoint \
cat /docker-php-entrypoint
@@ -32,6 +24,6 @@ RUN --mount=type=tmpfs,target=/temp \
mount | grep /temp
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
cat /root/.aws/credentials
test -s /root/.aws/credentials && echo "credentials mounted"
# docker build -t test --secret id=aws,src=$PWD/aws.txt --progress=plain -f Dockerfile.buildkit .
+2 -2
View File
@@ -4,7 +4,7 @@
本节介绍如何使用本地仓库
[Docker Registry](https://docs.docker.com/registry/) 是官方提供的工具,可以用于构建私有的镜像仓库。本文内容基于 [distribution/distribution](https://github.com/distribution/distribution) v2.x 版本
[Docker Registry](https://docs.docker.com/registry/) 是官方提供的工具,可以用于构建私有的镜像仓库。本文示例沿用 [distribution/distribution](https://github.com/distribution/distribution) v2.x 兼容路径;新生产部署应评估 Distribution 3.x,并核对配置路径、迁移说明和生态兼容性
### 6.2.1 安装运行 docker-registry
@@ -18,7 +18,7 @@
$ docker run -d -p 5000:5000 --restart=always --name registry registry:2
```
> **版本说明**使用 `registry:2` 表示 Docker Registry 2.x 版本这是当前推荐的版本旧版本 Registry 1.x 已停止维护不建议使用
> **版本说明**使用 `registry:2` 表示 Docker Registry 2.x 兼容示例Distribution 3.x 已发布稳定版本不要直接把本章 v2 配置原样套到 v3 生产环境升级前应阅读迁移说明并做兼容测试旧版本 Registry 1.x 已停止维护不建议使用
这将使用官方的 `registry` 镜像来启动私有仓库默认情况下仓库会被创建在容器的 `/var/lib/registry` 目录下你可以通过 `-v` 参数来将镜像文件存放在本地的指定路径例如下面的例子将上传的镜像放到本地的 `/opt/data/registry` 目录
```bash
+2 -2
View File
@@ -116,7 +116,7 @@ health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
threshold: 3
```
### 6.3.3 生成 http 认证文件
@@ -156,7 +156,7 @@ volumes:
本书配套的 `06_repository/demo/` 也采用同样约定容器内 registry 监听 `:5000`宿主机通过 `443:5000` 暴露 HTTPS 服务这样可以避免在容器内占用特权端口同时仍让客户端使用 `https://docker.domain.com` 访问
> **版本说明**Compose 配置中明确指定 `registry:2` 版本生产环境建议固定版本 `registry:2.8.3`而非使用 `latest`以保证部署的可重复性
> **版本说明**Compose 配置中明确指定 `registry:2` 版本生产环境建议固定具体补丁版本 `registry:2.8.x`并在新部署时评估 Distribution 3.x不要使用 `latest`以保证部署的可重复性
### 6.3.5 修改 Hosts 文件
+1 -1
View File
@@ -10,7 +10,7 @@
本章涉及的 Registry 和相关工具版本说明
- **Docker Registry**使用 `registry:2` 推荐版本已停止维护的 `registry:1` 不建议使用
- **Docker Registry / CNCF Distribution**本章示例使用 `registry:2` 兼容路径新生产部署应评估 Distribution 3.x并核对配置路径迁移说明和生态兼容性已停止维护的 `registry:1` 不建议使用
- **Nexus 3**建议指定具体版本 `sonatype/nexus3:3.69`而非 `latest`避免自动升级带来的兼容性问题
- **镜像标签规范**
- 生产环境推送至仓库时应明确指定版本号 `myapp:v1.0.0`
+1 -1
View File
@@ -59,7 +59,7 @@ LABEL maintainer="user@example.com" \
```docker
LABEL org.opencontainers.image.authors="yeasy" \
org.opencontainers.image.documentation="https://yeasy.gitbooks.io" \
org.opencontainers.image.documentation="https://yeasy.gitbook.io/docker_practice/" \
org.opencontainers.image.source="https://github.com/yeasy/docker_practice" \
org.opencontainers.image.licenses="MIT"
```
+2 -2
View File
@@ -2,9 +2,9 @@
### 官方文档
* `Dockerfile` 官方参考手册https://docs.docker.com/engine/reference/builder/
* `Dockerfile` 官方参考手册https://docs.docker.com/reference/dockerfile/
* `Dockerfile` 最佳实践指南https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
* `Dockerfile` 最佳实践指南https://docs.docker.com/build/building/best-practices/
* `Docker` 官方镜像 `Dockerfile` https://github.com/docker-library/docs
+29 -28
View File
@@ -4,12 +4,12 @@
在开始前让我们直言不讳**在大多数情况下你应该使用 COPY而不是 ADD**
`ADD` `COPY` 基础上增加了两个额外功能但这些功能往往引入复杂性而非便利
`ADD` `COPY` 基础上增加了两个额外功能它不是 `COPY` 的通用替代品但在少数场景中更合适
1. 自动解压 tar 压缩包有时你想复制一个 .tar.gz 本身 ADD 会意外地解压它
2. 支持从 URL 下载文件这个功能由于网络不稳定已被广泛认为是反模式
2. 支持从 URL 下载公开远程文件并可配合 `--checksum` 做校验
**实践中的建议**除非你明确需要自动解压功能比如官方基础镜像构建根文件系统否则始终使 COPY原因很简单显式优于隐式你的 Dockerfile 6 个月后被接手维护时清晰的意图会让团队少走很多弯路
**实践中的建议**本地普通文件默认 COPY本地 tar 自动解压或公开远程 artifact 下载并校验时用 ADD需要认证请求头重试或自定义解压流程时用 `RUN curl/wget`
### 7.3.1 基本语法
@@ -20,7 +20,7 @@ ADD [选项] ["<源路径>", ... "<目标路径>"]
`ADD` `COPY` 基础上增加了两个功能
1. 自动解压 tar 压缩包
2. 支持从 URL 下载文件 (不推荐)
2. 支持从 URL 下载文件
---
@@ -30,11 +30,11 @@ ADD [选项] ["<源路径>", ... "<目标路径>"]
|------|------|-----|
| 复制本地文件 | | |
| 自动解压 tar | | |
| 支持 URL | | (不推荐)|
| 支持 URL | | (公开 artifact 可配合校验使用)|
| 行为可预测性 | | |
| 推荐程度 | **优先使用** | 解压场景 |
| 推荐程度 | **普通复制优先使用** | 解压本地 Git/公开远程 artifact |
> **笔者建议**除非需要自动解压 tar 文件否则始终使用 COPY明确的行为比隐式的魔法更好
> **笔者建议**普通复制始终优先 COPY只有当你明确需要 ADD 的额外语义时再使用 ADD并把意图写清楚
---
@@ -79,7 +79,7 @@ app.tar.gz 包含: /app/ 目录结果:
```
---
### 7.3.4 URL 下载功能不推荐
### 7.3.4 URL 下载功能谨慎使用
#### 基本用法
@@ -89,32 +89,29 @@ app.tar.gz 包含: /app/ 目录结果:
ADD https://example.com/app.zip /app/app.zip
```
#### 为什么不推荐
#### 使用边界
| 问题 | 说明 |
| 场景 | 建议 |
|------|------|
| 权限固定 | 下载的文件权限为 600通常需要额外 RUN 修改 |
| 不会解压 | URL 下载的压缩包不会自动解压 |
| 缓存问题 | URL 内容变化时不会重新下载 |
| 层数增加 | 需要额外 RUN 清理 |
| 公开版本固定的远程 artifact | 使用 `ADD --checksum=sha256:... URL dest` |
| 需要认证请求头或复杂重试 | 使用 `RUN curl/wget` |
| 下载后需要复杂解压校验或清理 | 使用 `RUN curl/wget`把流程显式写出 |
| URL 内容可变但无校验 | 不建议直接写入 Dockerfile |
#### 推荐替代方案
#### 推荐写法
```docker
## 不推荐使用 ADD 下载
## 公开 artifact使用 ADD 并固定校验值
ADD https://example.com/app.tar.gz /tmp/
ADD --checksum=sha256:<digest> https://example.com/app.tar.gz /tmp/app.tar.gz
RUN tar -xzf /tmp/app.tar.gz -C /app && rm /tmp/app.tar.gz
## 推荐使用 RUN + curl
## 需要认证请求头或特殊处理使用 RUN + curl
RUN curl -fsSL https://example.com/app.tar.gz | tar -xz -C /app
```
优势
`ADD --checksum` 的优势是缓存更精确并且校验值直接绑定到 Dockerfile`RUN curl/wget` 的优势是控制力更强适合企业内网认证下载或复杂处理
- 一条 RUN 完成下载解压清理
- 减少镜像层数
- 更清晰的构建意图
---
@@ -139,6 +136,10 @@ ADD rootfs.tar.gz /
## 解压应用包
ADD dist.tar.gz /app/
## 下载公开 artifact 并校验
ADD --checksum=sha256:<digest> https://example.com/app.tar.gz /tmp/app.tar.gz
```
#### 不适合使用 ADD
@@ -149,9 +150,9 @@ ADD dist.tar.gz /app/
ADD package.json /app/ #
COPY package.json /app/ #
## 下载文件 RUN + curl
## 需要认证或复杂下载逻辑 RUN + curl/wget
ADD https://example.com/file / # ❌
ADD https://example.com/file / # ❌ 无法传认证信息,也没有显式处理
RUN curl -fsSL ... -o /file #
## 需要保留 tar 不解压 COPY
@@ -203,14 +204,14 @@ COPY . /app/
ADD app.tar.gz /app/
```
#### 3. 不要 ADD 下载文件
#### 3. 远程 artifact 使 ADD 时必须固定校验值
```docker
## 避免
## 公开 artifact
ADD https://example.com/file.tar.gz /tmp/
ADD --checksum=sha256:<digest> https://example.com/file.tar.gz /tmp/file.tar.gz
## 推荐
## 认证下载或复杂处理
RUN curl -fsSL https://example.com/file.tar.gz | tar -xz -C /app
```
+2 -2
View File
@@ -65,7 +65,7 @@ CMD echo $HOME
CMD ["sh", "-c", "echo $HOME"]
```
**优点**可以使用环境变量管道等 shell 特性
**优点**可以使用 `$HOME` 这类 shell 变量展开管道等 shell 特性
**缺点**主进程是 sh信号无法正确传递给应用
@@ -77,7 +77,7 @@ CMD ["sh", "-c", "echo $HOME"]
|------|----------|-----------|
| 主进程 | 指定的程序 | `/bin/sh` |
| 信号传递 | 正确 | 无法传递 |
| 环境变量 | 需要 shell 包装 | 自动解析 |
| `$VAR` shell 展开 | 不自动展开环境变量仍会传入进程 | 自动展开 |
| 推荐使用 | 大多数场景 | 需要 shell 特性时 |
#### 信号传递问题示例
+1 -1
View File
@@ -212,7 +212,7 @@ ENV HOST=localhost \
#### Q环境变量在 CMD 中不展开
exec 格式不会自动展开环境变量
exec 格式不会自动执行 shell 展开因此命令参数里的 `$PORT` 会按字面值传给进程但环境变量本身仍会注入进程环境应用可以通过语言运行时读取
```docker
## 不会展开 $PORT
+3 -3
View File
@@ -88,17 +88,17 @@ $ docker run -v /my/data:/var/lib/mysql mysql:8.4
### 7.8.5 VOLUME 在构建时的特殊行为
> **重要**VOLUME 之后该目录的修改会被丢弃
> **重要**`VOLUME` 之后再写入该目录的构建语义取决于 builderlegacy builder 会丢弃这些修改BuildKit 会保留但运行容器时一旦该路径挂载了卷卷会遮蔽镜像内同路径的内容
```docker
FROM ubuntu
VOLUME /data
## 这个文件不会出现在镜像中
## legacy builder 会丢弃BuildKit 会保留但运行时挂载卷会遮蔽它
RUN echo "hello" > /data/test.txt
```
**原因**在构建过程中VOLUME 指令会为该目录创建一个临时匿名卷后续 RUN 指令对该目录的写入实际发生在这个临时卷中而非镜像层当该 RUN 指令结束后临时卷被丢弃因此写入的内容不会保存到最终镜像中注意这与容器运行时创建的匿名卷是不同的运行时创建的卷会在容器生命周期内持续存在
**原因** builder 在构建过程中为该目录创建临时匿名卷后续写入发生在临时卷中BuildKit 则会把修改保留在镜像层为了避免不同 builder 下出现不同结果也为了避免运行时卷遮蔽镜像内初始化数据不要把必须存在的初始化文件写在 `VOLUME` 之后
#### 正确做法
+2 -2
View File
@@ -7,12 +7,12 @@
| **FROM** | 指定基础镜像 | 必须是第一条指令 |
| **RUN** | 在新层执行命令 | 合并命令清理缓存以减小体积 |
| **COPY** | 复制文件 | 优先使用支持 `--from` |
| **ADD** | 更高级的复制 | 自动解压 tar不推荐用于下载 |
| **ADD** | 更高级的复制 | 自动解压 tar公开远程 artifact 应配合 `--checksum` |
| **CMD** | 容器启动默认命令 | 可被 `docker run` 参数覆盖 |
| **ENTRYPOINT** | 容器入口点 | 固定启动命令CMD 作为默认参数 |
| **ENV** | 设置环境变量 | 构建时 + 运行时均生效 |
| **ARG** | 构建参数 | 仅构建时生效FROM 后需重新声明 |
| **VOLUME** | 定义匿名卷 | VOLUME 之后的修改会丢失 |
| **VOLUME** | 定义匿名卷 | 运行时挂载会遮蔽镜像内目录构建后续写入语义依赖 builder |
| **EXPOSE** | 声明端口 | 仅文档作用不自动映射 |
| **WORKDIR** | 指定工作目录 | 替代 `RUN cd`目录不存在会自动创建 |
| **USER** | 指定运行用户 | 用户必须已存在推荐 gosu |
+2
View File
@@ -122,6 +122,8 @@ $ docker run -d \
#### 场景四共享 SSH 密钥
只读挂载可以防止容器修改主机密钥但不能防止容器读取并外传密钥只有在镜像完全可信密钥作用域很窄且可随时轮换时才考虑这种做法更稳妥的方式是使用 SSH agent socket 转发一次性 deploy key或在 CI/构建场景中使用 BuildKit `--ssh`
```bash
## 挂载 SSH 密钥只读
+8 -2
View File
@@ -20,7 +20,7 @@ ghi789... none null local
| **host** | 容器直接使用宿主机网络栈 | 需要最高网络性能时 |
| **none** | 禁用网络 | 完全隔离的容器 |
| **overlay** | 跨主机网络 | Docker Swarm 集群 |
| **macvlan** | 容器拥有独立 MAC 地址 | 需要直接接入物理网络 |
| **macvlan** | 容器拥有独立 MAC 地址 | Linux 主机上需要直接接入物理网络 |
| **ipvlan** | 容器共享父接口 MAC独享 IP | 同网段大量容器 MAC 数量受限的网络 |
### 9.2.2 Bridge 网络默认
@@ -45,6 +45,8 @@ $ docker run -d --network host nginx
```
这种模式下网络性能最高但容器之间和宿主机之间没有网络隔离
> 注意host 网络优先用于明确需要高性能或大量端口的 Linux 主机场景Docker Desktop 仅在较新版本中支持且需要在设置中启用使用 host 网络时 `-p` / `--publish` 端口映射不会生效普通 Web 服务默认仍建议使用 bridge 网络并显式发布端口
### 9.2.4 None 网络
使用 `--network none` 参数启动的容器只有 `lo` 回环网卡完全没有外部网络连接适用于只需要运行计算任务不需要网络的容器
@@ -55,7 +57,11 @@ $ docker run -it --network none alpine ip addr
inet 127.0.0.1/8 scope host lo
```
### 9.2.5 数据流向
### 9.2.5 Macvlan 与平台限制
Macvlan 适合少数需要让容器像物理主机一样直接出现在二层网络中的场景它只支持 Linux 主机不支持 Docker Desktop for Mac / Windows也不支持 rootless 模式多数云厂商网络会阻断或限制 macvlan默认情况下macvlan 容器与宿主机直接通信也需要额外路由或接口配置
### 9.2.6 数据流向
容器网络中的数据流向可以分为以下几种情况
+6 -5
View File
@@ -39,10 +39,10 @@ $ docker run -d -p 8080:80 nginx
| 格式 | 含义 | 示例 |
|------|------|------|
| `ip:hostPort:containerPort` | 绑定指定 IP 的特定端口 | `-p 127.0.0.1:8080:80` (仅本机访问) |
| `ip:hostPort:containerPort` | 绑定指定 IP 的特定端口 | `-p 127.0.0.1:8080:80` ( IPv4 本机访问) |
| `ip::containerPort` | 绑定指定 IP 的随机端口 | `-p 127.0.0.1::80` |
| `hostPort:containerPort` | 绑定所有 IP (0.0.0.0) 的特定端口 | `-p 8080:80` (默认) |
| `containerPort` | 绑定所有 IP 的随机端口 | `-p 80` |
| `hostPort:containerPort` | 绑定所有地址通常包括 `0.0.0.0` `[::]`的特定端口 | `-p 8080:80` (默认) |
| `containerPort` | 绑定所有地址的随机端口 | `-p 80` |
#### 2. 随机映射
@@ -93,14 +93,15 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web
#### 1. 限制监听 IP
默认情况下`-p 8080:80` 会监听 `0.0.0.0:8080`这意味着任何人只要能连接你的宿主机 IP就能访问该服务
默认情况下`-p 8080:80` 会监听所有可用地址常见输出包括 `0.0.0.0:8080` `[::]:8080`这意味着任何人只要能连接你的宿主机 IP就能访问该服务
如果不希望对外暴露 (例如数据库服务)应绑定到 `127.0.0.1`
如果不希望对外暴露 (例如数据库服务)应绑定到回环地址IPv4 使用 `127.0.0.1`IPv6 使用 `[::1]`
```bash
## 仅允许本机访问
$ docker run -d -p 127.0.0.1:3306:3306 mysql
$ docker run -d -p '[::1]:3306:3306' mysql
```
#### 2. 避免端口冲突
+9 -21
View File
@@ -2,7 +2,7 @@
**BuildKit** 是下一代的镜像构建组件 [moby/buildkit](https://github.com/moby/buildkit) 开源。
> **重要** Docker 23 BuildKit 已成为 **默认稳定构建器**无需手动启用Docker Engine 29 进一步将 Containerd 镜像存储设为默认提升与 Kubernetes 的互操作性
> **重要** Docker 23 BuildKit 已成为 **默认稳定构建器**无需手动启用Docker Engine 29 在新安装场景中进一步将 containerd image store 设为默认提升多平台镜像SBOM/Provenance OCI 元数据能力
目前Docker Hub 自动构建已经支持 BuildKit具体请参考 [docker-practice/docker-hub-buildx](https://github.com/docker-practice/docker-hub-buildx)。
@@ -46,7 +46,7 @@ COPY --from=builder /app/dist /app/dist
```
使用多阶段构建构建的镜像中只包含了目标文件夹 `dist`但仍然存在一些问题 `package.json` 文件变动时`RUN npm i && rm -rf ~/.npm` 这一层会重新执行变更多次后生成了大量的中间层镜像
为解决这个问题进一步的我们可以设想一个类似 **数据卷** 的功能在镜像构建时把 `node_modules` 文件夹挂载上去在构建完成后这个 `node_modules` 文件夹会自动卸载实际的镜像中并不包含 `node_modules` 这个文件夹这样我们就省去了每次获取依赖的时间大大增加了镜像构建效率同时也避免了生成了大量的中间层镜像
为解决这个问题可以把包管理器的下载缓存挂载到构建步骤中例如 npm `/root/.npm`注意`type=cache` 只能作为性能优化不能成为构建正确性的前提缓存目录可能被并发构建改写也可能被 GC 清理所以不要把 `node_modules`编译产物等必须存在的内容只放在 cache mount
`BuildKit` 提供了 `RUN --mount=type=cache` 指令可以实现上边的设想
@@ -59,35 +59,23 @@ WORKDIR /app
COPY package.json /app/
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
--mount=type=cache,target=/root/.npm,id=npm_cache \
npm i --registry=https://registry.npmmirror.com
RUN --mount=type=cache,target=/root/.npm,id=npm_cache \
npm install --registry=https://registry.npmmirror.com
COPY src /app/src
RUN --mount=type=cache,target=/app/node_modules,id=my_app_npm_module,sharing=locked \
## --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \
npm run build
RUN npm run build
FROM nginx:alpine
## COPY --from=builder /app/dist /app/dist
## 为了更直观的说明 from source 指令这里使用 RUN 指令
RUN --mount=type=cache,target=/tmp/dist,from=builder,source=/app/dist \
# --mount=type=cache,target=/tmp/dist,from=my_app_dist,sharing=locked \
mkdir -p /app/dist && cp -r /tmp/dist/* /app/dist
COPY --from=builder /app/dist /app/dist
```
第一个 `RUN` 指令执行后`id` `my_app_npm_module` 的缓存文件夹挂载到了 `/app/node_modules` 文件夹中多次执行也不会产生多个中间层镜像
第一个 `RUN` 指令执行后`id` `npm_cache` 的缓存文件夹挂载到了 `/root/.npm`后续构建可复用下载缓存
第二个 `RUN` 指令执行时需要用到 `node_modules` 文件夹`node_modules` 已经挂载命令也可以正确执行
第二个 `RUN` 指令执行时`node_modules` 已经作为上一层真实写入到 builder 阶段的文件系统中构建不依赖缓存目录内容
第三个 `RUN` 指令将上一阶段产生的文件复制到指定位置`from` 指明缓存的来源这里 `builder` 表示缓存来源于构建的第一阶段`source` 指明缓存来源的文件夹
最后使用 `COPY --from=builder` 将上一阶段产生的文件复制到最终镜像跨阶段复制构建产物应使用 `COPY --from`如果只是临时读取上一阶段文件可使用 `RUN --mount=type=bind,from=builder,source=/app/dist,target=/tmp/dist,ro`
上面的 `Dockerfile` `--mount=type=cache,...` 中指令作用如下
+1 -1
View File
@@ -45,7 +45,7 @@ Buildx 支持在构建时直接生成 SBOM (Software Bill of Materials),这对
```bash
$ docker buildx build --sbom=true -t myimage .
```
该命令会在构建结果中包含 SPDX CycloneDX 格式的 SBOM 数据
该命令会 SBOM 作为构建 attestation 附加到构建结果中BuildKit 默认使用 SPDX SBOM attestation需要 CycloneDX 文件时可使用 SyftDocker Scout 等工具另行生成或转换
> ** 注意与失败模式**
> 要使 SBOM (或其它 attestation 元数据) 成功附着并可见对底层的存储格式有前置要求默认的 classic image store 不支持 manifest list/index 这种存放 attestation 的结构
+23 -4
View File
@@ -1,17 +1,32 @@
## 11.2 安装与卸载
`Compose` Docker 官方的开源项目负责实现 Docker 容器集群的快速编排
`Compose` Docker 官方的开源项目负责实现本地或单机多容器应用的快速编排跨主机集群编排应使用 SwarmKubernetes 或云厂商托管服务
当前的 Compose `docker compose` 子命令的形式提供Docker Desktop macOSWindows Linux 上默认包含它如果你已经在 Linux 上单独安装了 Docker Engine Docker CLI也可以再安装 Compose CLI 插件
### 11.2.1 Linux
Linux 你可以通过 Docker 官方发布页安装 Compose CLI 插件把二进制文件保存到 `$DOCKER_CONFIG/cli-plugins/docker-compose`并赋予执行权限即可
Linux 默认建议通过 Docker 官方软件仓库安装 Compose CLI 插件这样可以随系统包管理器更新
Ubuntu / Debian
```bash
$ sudo apt-get update
$ sudo apt-get install docker-compose-plugin
```
Fedora / CentOS / RHEL 兼容发行版
```bash
$ sudo dnf install docker-compose-plugin
```
如果是离线环境需要锁定特定版本或包管理器暂不覆盖你的架构可以从 Docker 官方发布页手工安装手工安装不会自动更新下载 URL 中的版本号和架构 `x86_64``aarch64`需要按目标机器替换
```bash
$ DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
$ mkdir -p $DOCKER_CONFIG/cli-plugins
$ curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
$ curl -SL https://github.com/docker/compose/releases/download/v5.1.2/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
$ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
```
@@ -24,8 +39,12 @@ Docker Compose version v5.x.x
### 11.2.3 卸载
如果是二进制包方式安装删除二进制文件即可
如果是仓库方式安装使用包管理器卸载如果是二进制包方式安装删除二进制文件即可
```bash
$ sudo apt-get remove docker-compose-plugin
#
$ sudo dnf remove docker-compose-plugin
$ rm $DOCKER_CONFIG/cli-plugins/docker-compose
```
+2 -2
View File
@@ -228,7 +228,7 @@ $ docker compose run --no-deps web python manage.py shell
#### `scale`
当前 Compose CLI 更稳妥的扩缩容写法是通过 `docker compose up --scale` 完成
当前 Compose CLI 仍支持 `docker compose scale`实际使用中更常见也更便于和创建/重建流程放在一起的写法是通过 `docker compose up --scale` 完成
例如
@@ -238,7 +238,7 @@ $ docker compose up -d --scale web=3 --scale db=2
将启动 3 个容器运行 `web` 服务2 个容器运行 `db` 服务
> **说明**有些旧环境或实验性入口中仍可能出现 `docker compose scale`但它不应再被视为当前 Compose 的通用稳定默认命令
> **说明**如果 Compose 文件为服务指定了 `container_name`该服务无法扩展到多个容器需要扩缩容的服务应使用 Compose 自动生成的容器名并通过服务名做 DNS 访问
一般的当指定数目多于该服务当前实际运行容器将新创建并启动容器反之将停止容器
+8
View File
@@ -582,6 +582,14 @@ $ docker compose --profile debug up # 启动 web + debug
$ docker compose up # 仅启动 web
```
也可以通过环境变量激活
```bash
$ COMPOSE_PROFILES=debug,test docker compose up
```
如果在命令行里显式指定某个带 profile 的服务Compose 会自动启动这个目标服务及其声明的依赖但不会自动启动同一 profile 下的其它服务除非也显式指定或通过 `--profile` / `COMPOSE_PROFILES` 启用
### 11.5.35 读取变量
Compose 模板文件支持动态读取主机的系统环境变量和当前目录下的 `.env` 文件中的变量
+1 -1
View File
@@ -4,7 +4,7 @@
> - MySQL8.4可替换为其他 8.x 版本或使用 MariaDB 替代
> - WordPresslatest建议在生产环境指定具体版本 6.x
WordPress 是全球最流行的内容管理系统 (CMS)使用 Docker Compose 可以在几分钟内搭建一个包含数据库Web 服务和持久化存储的生产级 WordPress 环境
WordPress 是全球最流行的内容管理系统 (CMS)使用 Docker Compose 可以在几分钟内搭建一个包含数据库Web 服务和持久化存储的本地练习/单机演示环境
---
+1 -1
View File
@@ -1,6 +1,6 @@
# 第十一章 Docker Compose
`Docker Compose` Docker 官方编排 (Orchestration) 项目之一负责快速的部署分布式应用
`Docker Compose` Docker 官方编排 (Orchestration) 项目之一负责快速定义和启动本地或单机多容器应用跨主机集群编排应交给 SwarmKubernetes 或云厂商托管服务
> **重要提示Compose V1 已停止支持**
>
+17 -1
View File
@@ -2,9 +2,18 @@
services:
db:
image: postgres
image: postgres:16
environment:
POSTGRES_DB: django_db
POSTGRES_USER: django_user
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U django_user -d django_db"]
interval: 5s
timeout: 5s
retries: 5
web:
build: .
@@ -13,6 +22,13 @@ services:
- .:/code
ports:
- "8000:8000"
depends_on:
db:
condition: service_healthy
environment:
# 与书中 11.6 节一致settings.py 从环境变量读取数据库密码
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}
DATABASE_URL: postgres://django_user:${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD}@db:5432/django_db
volumes:
postgres_data:
+1 -1
View File
@@ -24,7 +24,7 @@ services:
- db
image: wordpress:latest
ports:
- "8000:80"
- "127.0.0.1:8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
+1 -1
View File
@@ -100,7 +100,7 @@ flowchart TD
Docker Engine v29.x 开始架构进一步简化和标准化
- **Containerd 镜像存储 (Image Store)** v29.x 的新安装场景中默认启用Docker 直接使用 Containerd 的镜像管理能力不再维护自己的一套 graphdriver
- **优势**多平台镜像支持更好镜像拉取更快 (lazy pulling) K8s 共享镜像
- **优势**多平台镜像支持更好可保存 SBOM/Provenance attestations并可使用 containerd snapshotters lazy pulling 等能力
- **实验性 nftables 支持**随着主流 Linux 发行版逐步弃用 iptablesDocker v29.x 引入了实验性 nftables 后端启用方式为 `dockerd --firewall-backend=nftables`可直接创建 nftables 规则而无需依赖 iptables-nft 转换层生产环境请谨慎使用
---
+7 -7
View File
@@ -92,11 +92,11 @@ Docker 的存储驱动经历了从早期各式各样的机制(如 aufs, device
| 存储后端 / 驱动 | 核心特性说明 | 推荐程度 |
|---------|------|---------|
| **containerd image store**| (v29.x 新一代默认后端新装默认) 基于 containerd snapshotters原生支持 OCI image index多架构镜像与 Attestations 构建溯源元数据存储 | **强烈推荐 (现代默认)** |
| **containerd image store**| (v29.x 新一代默认后端新装默认) 基于 containerd snapshotters原生支持 OCI image index多架构镜像与 Attestations 构建溯源元数据存储启用 `userns-remap` 时不可用 | **强烈推荐 (现代默认)** |
| **overlay2**| (经典 Graph Driver) 传统架构下的现代 Linux 默认驱动性能优秀但在处理复杂溯源元数据索引时受限 | **推荐 (主要后备)** |
| **aufs** | 早期默认兼容性好 | 遗留系统 |
| **aufs** | 早期默认已从现代 Docker Engine 移除 | 历史资料 |
| **btrfs**/**zfs** | 使用原生稳定文件系统快照能力 | 特定场景 |
| **devicemapper** | 块设备级存储 | 遗留系统 (已被逐步弃用) |
| **devicemapper** | 块设备级存储已从现代 Docker Engine 移除 | 历史资料 |
| **vfs** | 不使用 CoW每层完整复制 | 仅测试 |
#### Classic Graph Drivers Snapshotters 的核心差异
@@ -104,7 +104,7 @@ Docker 的存储驱动经历了从早期各式各样的机制(如 aufs, device
传统模型 `overlay2`将镜像拉取解包的过程由 Docker graph drivers 处理而新的 `containerd image store` 则将这一职责彻底下放给了 `containerd` 自身的 `snapshotters`底层在 Linux 发行版通常依然利用操作系统的 overlayfs这种架构改变带来了
1. 本地免拉取查看多平台镜像 index manifest attestations (SBOMProvenance)
2. 避免了以前绕过 CRI 获取本地镜像的问题带来更好的原生 Kubernetes 生态兼容性
2. 允许 Docker 使用 containerd snapshotters 管理镜像层便于与现代 OCI 生态能力对齐它不表示 kubelet/containerd 会自动复用 Docker 本地镜像Kubernetes 镜像分发仍应以 registry镜像拉取策略和运行时配置为准
#### 查看当前存储驱动与后端
@@ -114,14 +114,14 @@ $ docker info | grep "Storage Driver"
Storage Driver: overlay2
## Engine v29.x 可以通过如下输出验证是否开启了 containerd 镜像后端
$ docker info | grep "containerd image store"
containerd image store: true
$ docker info -f '{{ .DriverStatus }}'
[[driver-type io.containerd.snapshotter.v1]]
```
---
### 12.4.5 overlay2 工作原理
overlay2 是目前最推荐的存储驱动
在经典 graph driver 体系下overlay2 仍是 Linux 上的主要推荐驱动Docker Engine 29 新安装场景默认走 containerd image store/snapshotter
```mermaid
flowchart TD
+2 -2
View File
@@ -4,9 +4,9 @@
| 技术 | 作用 | 要点 |
|------|------|------|
| **Namespace** | 资源隔离 | PIDNETMNTUTSIPCUSER 六种命名空间 |
| **Namespace** | 资源隔离 | 常见核心包括 PIDNETMNTUTSIPCUSERCgroupTime namespace 通常默认不启用 |
| **Cgroups** | 资源限制 | 限制 CPU内存磁盘 I/O进程数 |
| **Union FS** | 分层存储 | overlay2 为推荐驱动支持 Copy-on-Write |
| **Union FS** | 分层存储 | 镜像分层与 Copy-on-Write 是核心Engine 29 新装默认 containerd image storeoverlay2 是经典 graph driver 场景的主要后备 |
| Namespace | 隔离内容 | 一句话说明 |
|-----------|---------|-----------|
+7 -6
View File
@@ -7,13 +7,13 @@
13-2Kubernetes 基本概念示意图
* 节点 (`Node`)一个节点是一个运行 Kubernetes 中的主机
* 容器组 (`Pod`)一个 Pod 对应于由若干容器组成的一个容器同个组内的容器共享一个存储 (volume)
* 容器组 (`Pod`)Kubernetes 中最小的可部署和调度单元一个 Pod 包含一个或多个紧密协作的容器共享网络身份并可共享一个或多个 (volume)
* 容器组生命周期 (`pod-states`)包含所有容器状态集合包括容器组状态类型容器组生命周期事件重启策略
* 服务 (`services`)一个 Kubernetes 服务是容器组逻辑的高级抽象同时也对外提供访问容器组的策略
* (`volumes`)一个卷就是一个目录容器对其有访问权限
* 标签 (`labels`)标签是用来连接一组对象的比如容器组标签可以被用来组织和选择子对象
* 接口权限 (`accessing_the_api`)端口IP 地址和代理的防火墙规则
* web 界面 (`ux`)用户可以通过 web 界面操作 Kubernetes
* web 界面 (`ux`)用户可以通过 Headlamp 等仍在维护的 web 界面观察和操作 Kubernetes历史 Dashboard 已停止维护
* 命令行操作 (`cli`)`kubectl` 命令
### 13.2.1 节点
@@ -82,7 +82,7 @@ $ kubectl drain worker-1 --ignore-daemonsets
### 13.2.2 容器组
Kubernetes 使用的最小调度单位是容器组 (Pod)它是创建调度管理的最小单位一个 Pod 包含一个或多个紧密协作的容器它们共享网络命名空间存储卷
Kubernetes 使用的最小调度单位是容器组 (Pod)它是创建调度管理的最小单位一个 Pod 包含一个或多个紧密协作的容器它们共享网络命名空间并可共享一个或多个存储卷
Pod 通常不会被直接创建而是通过 Deployment 等控制器来管理当节点发生故障时控制器会在其他可用节点上重新创建 Pod
@@ -96,7 +96,7 @@ Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理
在一个容器组中容器都使用相同的网络地址和端口可以通过本地网络来相互通信每个容器组都有独立的 IP可以通过网络来和其他物理主机或者容器通信
容器组一组存储卷 (挂载点)主要是为了让容器在重启之后可以不丢失数据
容器组可以挂载一组存储卷 (挂载点)卷不只用于持久化也可用于 `emptyDir` 临时交换ConfigMap/Secret 投射日志旁路收集等场景真正需要跨 Pod 生命周期保留的数据应使用 PersistentVolume / PersistentVolumeClaim 等持久化机制
#### 容器组管理
@@ -121,7 +121,7 @@ Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理
#### 容器组的生命状态
包括若干状态值`Pending``Running``Succeeded``Failed`
Pod phase 包括若干状态值`Pending``Running``Succeeded``Failed``Unknown`
| 状态 | 说明 |
|------|------|
@@ -129,6 +129,7 @@ Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理
| **Running** | Pod 已被调度到节点并且所有容器都已启动至少有一个容器处于运行状态|
| **Succeeded** | Pod 中的所有容器都正常退出且不会被重启|
| **Failed** | Pod 中的所有容器都已终止且至少有一个容器以失败状态退出|
| **Unknown** | 集群无法获取 Pod 状态常见原因是节点失联|
#### 容器组生命周期与重启策略
@@ -140,7 +141,7 @@ Pod 的重启策略 (`restartPolicy`) 决定了容器退出后的行为:
| **OnFailure** | 不重启 | 重启容器 |
| **Never** | 不重启 | 不重启 |
当节点故障或不可达时节点控制器会将该节点上所有 Pod 的状态标记 `Failed`如果这些 Pod Deployment 等控制器管理控制器会自动在其他节点上重新创建
当节点故障或不可达时Pod 可能先表现为 `Unknown`之后根据控制器驱逐策略和垃圾回收机制转 `Failed` 或被重新创建如果这些 Pod Deployment 等控制器管理控制器会自动在其他节点上重新创建
### 13.2.3 Deployment ReplicaSet
+17 -3
View File
@@ -1,12 +1,18 @@
## 13.5 实战练习
本章将通过一个具体的案例部署一个 Nginx 网站并为其配置 Service Ingress来串联前面学到的知识
本章将通过一个具体的案例部署一个 Nginx 网站并为其配置 Service来串联前面学到的知识
开始前请先准备好可用的 Kubernetes 集群和 `kubectl` 上下文你可以先完成 [14.3 Docker Desktop](../14_kubernetes_setup/14.3_docker-desktop.md) [14.4 Kind](../14_kubernetes_setup/14.4_kind.md)并确认
```bash
kubectl get nodes
```
### 13.5.1 目标
1. 部署一个 Nginx Deployment
2. 创建一个 Service 暴露 Nginx
3. (可选) 通过 Ingress 访问服务
3. 通过端口转发或 NodePort 访问服务
### 13.5.2 步骤 1创建 Deployment
@@ -69,7 +75,15 @@ kubectl apply -f nginx-service.yaml
```bash
kubectl get svc nginx-service
```
如果输出端口是 `80:30080/TCP`你可以通过 `http://<NodeIP>:30080` 访问 Nginx
如果输出端口是 `80:30080/TCP`你可以通过 `http://<NodeIP>:30080` 访问 NginxDocker DesktopKind 等本地集群中NodePort 到宿主机的可达性取决于集群实现更稳定的本地访问方式是端口转发
```bash
kubectl port-forward svc/nginx-service 8080:80
```
然后访问 `http://localhost:8080`
> Ingress 只有在集群中已安装 Ingress controller 且配置了 IngressClass 时才会生效当前练习只覆盖 ServiceIngress/Gateway API 建议在完成第 14 章后再单独练习
### 13.5.4 步骤 3模拟滚动更新
+1 -1
View File
@@ -171,13 +171,13 @@ $ sudo systemctl enable containerd
$ sudo systemctl start containerd
$ sudo kubeadm init \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--pod-network-cidr 10.244.0.0/16 \
--cri-socket unix:///run/containerd/containerd.sock \
--v 5
```
* `--pod-network-cidr 10.244.0.0/16` 参数与后续 CNI 插件有关这里以 `flannel` 为例若后续部署其他类型的网络插件请更改此参数
* kubeadm 默认使用 `registry.k8s.io` 拉取 Kubernetes 控制平面镜像受限网络环境可通过 kubeadm 配置文件中的 `imageRepository` 指向受信任镜像仓库不要把第三方镜像仓库当成通用默认值
> `kubeadm` 预检失败应按提示修复缺失依赖内核参数swap 或运行时配置实验环境确需忽略预检时只忽略明确理解且可接受的单项检查不建议使用 `--ignore-preflight-errors=all`
+2 -2
View File
@@ -197,14 +197,14 @@ $ sudo systemctl daemon-reload
#### master
```bash
$ sudo kubeadm init --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--pod-network-cidr 10.244.0.0/16 \
$ sudo kubeadm init --pod-network-cidr 10.244.0.0/16 \
--cri-socket unix:///var/run/cri-dockerd.sock \
--v 5
```
* `--cri-socket unix:///var/run/cri-dockerd.sock` 参数指定使用 cri-dockerd 作为容器运行时接口
* `--pod-network-cidr 10.244.0.0/16` 参数与后续 CNI 插件有关这里以 `flannel` 为例若后续部署其他类型的网络插件请更改此参数
* kubeadm 默认使用 `registry.k8s.io` 拉取 Kubernetes 控制平面镜像受限网络环境可通过 kubeadm 配置文件中的 `imageRepository` 指向受信任镜像仓库不要把第三方镜像仓库当成通用默认值
> `kubeadm` 预检失败应按提示修复缺失依赖内核参数swap 或运行时配置实验环境确需忽略预检时只忽略明确理解且可接受的单项检查不建议使用 `--ignore-preflight-errors=all`
+5 -3
View File
@@ -4,15 +4,17 @@
### 14.3.1 启用 Kubernetes
Docker Desktop 设置页面点击 `Kubernetes`选择 `Enable Kubernetes`稍等片刻看到左下方 `Kubernetes` 变为 `running`Kubernetes 启动成功
Docker Desktop 设置页面进入 `Kubernetes`创建或启用集群较新的 Docker Desktop 可选择 `kind` `kubeadm` 作为集群创建方式日常本地开发优先选择 `kind`因为它支持多节点和版本选择
![](../_images/settings-kubernetes.png)
> 注意Kubernetes 的镜像存储在 `registry.k8s.io`如果国内网络无法直接访问可以在 Docker Desktop 配置中 `Docker Engine` 处配置镜像加速器或者利用国内云服务商的镜像仓库手动拉取镜像并 retag
> 注意Docker Desktop Kubernetes 的控制平面镜像默认从 Docker Hub 拉取例如 `docker.io/docker/desktop-*` `docker.io/kindest/node:<tag>`如果企业网络不能访问 Docker Hub应按 Docker Desktop `KubernetesImagesRepository` 设置镜像仓库并用 `docker desktop kubernetes images list`Docker Desktop 4.44+ `docker ps` 确认实际镜像标签普通 Docker Engine `registry-mirrors` 不会自动改写这些控制平面镜像
### 14.3.2 测试
```bash
$ kubectl version
$ kubectl config use-context docker-desktop
$ kubectl get nodes
```
如果正常输出信息则证明 Kubernetes 成功启动
如果 `kubectl get nodes` 显示节点为 `Ready`则证明 Kubernetes 成功启动
+22 -11
View File
@@ -1,12 +1,27 @@
## 14.7 部署 Dashboard
## 14.7 可视化管理界面
[Kubernetes Dashboard](https://github.com/kubernetes/dashboard) 是基于网页的 Kubernetes 用户界面
[Kubernetes Dashboard](https://github.com/kubernetes-retired/dashboard) 是历史上常用的 Kubernetes Web UI,但项目已停止维护
> **注意** `kubernetes/dashboard` 项目已于 2026 1 21 日归档停止维护推荐使用 [Headlamp](https://headlamp.dev/) 等替代方案。以下内容仅供历史参考,基于归档前的最新 Helm 安装方式
> **注意**Kubernetes 官方文档已将 Dashboard 标记为 deprecated and unmaintained新安装建议考虑 [Headlamp](https://headlamp.dev/) 等仍在维护的替代方案。以下 Dashboard 内容仅供历史迁移或存量环境参考
![](../_images/kubernetes-dashboard-ui.png)
### 14.7.1 部署
### 14.7.1 推荐替代Headlamp
Headlamp Kubernetes SIG UI 下的现代 Web UI可通过 Helm 安装
```bash
$ helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/
$ helm install headlamp headlamp/headlamp --namespace kube-system
```
本地访问时优先使用端口转发避免直接把管理界面暴露到公网
```bash
$ kubectl -n kube-system port-forward svc/headlamp 4466:80
```
### 14.7.2 历史 Dashboard 部署
Dashboard 7.0+ 版本仅支持通过 Helm 安装
@@ -17,7 +32,7 @@ $ helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-da
--create-namespace --namespace kubernetes-dashboard
```
### 14.7.2 访问
### 14.7.3 访问
通过端口转发访问 Dashboard
@@ -27,19 +42,15 @@ $ kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-pro
然后在浏览器打开 `https://localhost:8443` 即可访问
### 14.7.3 登录
### 14.7.4 登录
为历史 Dashboard 创建只读服务账户并获取短期登录令牌不要为 Dashboard 创建 `cluster-admin` 绑定如果确实需要临时管理员权限应走单独的 break-glass 审批和审计流程
```bash
$ kubectl create sa dashboard-readonly -n kubernetes-dashboard
$ kubectl create clusterrole dashboard-readonly \
--verb=get,list,watch \
--resource=pods,deployments,services,configmaps,namespaces,nodes
$ kubectl create clusterrolebinding dashboard-readonly \
--clusterrole=dashboard-readonly \
--clusterrole=view \
--serviceaccount=kubernetes-dashboard:dashboard-readonly
$ kubectl create token dashboard-readonly -n kubernetes-dashboard --duration=1h
+2 -2
View File
@@ -1,6 +1,6 @@
# 第十四章 部署 Kubernetes
目前Kubernetes 支持在多种环境下使用包括本地主机 (UbuntuDebianCentOSFedora )云服务 ([腾讯云](https://cloud.tencent.com/act/cps/redirect?redirect=10058&cps_key=3a5255852d5db99dcd5da4c72f05df61)、[阿里云](https://www.aliyun.com/product/kubernetes?source=5176.11533457&userCode=8lx5zmtu&type=copy)、[百度云](https://cloud.baidu.com/product/cce.html)等)。
目前Kubernetes 支持在多种环境下使用包括本地主机 (UbuntuDebianCentOSFedora )云服务 ([腾讯云 TKE](https://cloud.tencent.com/product/tke)、[阿里云 ACK](https://cn.aliyun.com/product/ack)、[百度云](https://cloud.baidu.com/product/cce.html)等)。
你可以使用以下几种方式部署 Kubernetes接下来的小节会对各种方式进行详细介绍
@@ -11,7 +11,7 @@
* [Kind - Kubernetes IN Docker](14.4_kind.md)
* [K3s - 轻量级 Kubernetes](14.5_k3s.md)
* [一步步部署 Kubernetes 集群](14.6_systemd.md)
* [部署 Dashboard](14.7_dashboard.md)
* [可视化管理界面Headlamp 与历史 Dashboard](14.7_dashboard.md)
* [Kubernetes 命令行 kubectl](14.8_kubectl.md)
除了上述方式企业生产环境中还有两个常见的部署工具值得关注
+1 -1
View File
@@ -13,7 +13,7 @@
### 延伸阅读
- [容器编排基础](../13_kubernetes_concepts/README.md)Kubernetes 核心概念
- [Dashboard](14.7_dashboard.md)部署可视化管理界面
- [可视化管理界面](14.7_dashboard.md)Headlamp 与历史 Dashboard 迁移参考
- [kubectl](14.8_kubectl.md)命令行工具使用指南
---
+11 -1
View File
@@ -136,7 +136,17 @@ docker push ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
#### TKE 集群中使用 TCR 镜像
配置镜像拉取凭证后 Deployment 中直接引用 TCR 镜像
配置镜像拉取凭证后 Deployment 中直接引用 TCR 镜像Secret 必须创建在使用它的 namespace 下面示例使用 `default` namespace
```bash
$ kubectl create secret docker-registry tcr-secret \
--docker-server=ccr.ccs.tencentyun.com \
--docker-username=<username> \
--docker-password=<token-or-password> \
--namespace=default
```
> 安全提示在命令行直接输入密码或 token 可能进入 shell 历史记录生产环境可先 `docker login`再基于受保护的 `~/.docker/config.json` 创建 `kubernetes.io/dockerconfigjson` Secret或使用云厂商提供的托管凭据集成
```yaml
apiVersion: apps/v1
+3 -3
View File
@@ -6,11 +6,11 @@
16-3阿里云标识
[阿里云](https://www.aliyun.com/?source=5176.11533457\&userCode=8lx5zmtu\&type=copy)创立于 2009 年,是中国较早的云计算平台。阿里云致力于提供安全、可靠的计算和数据处理能力。
[阿里云](https://www.aliyun.com/)创立于 2009 年,是中国较早的云计算平台。阿里云致力于提供安全、可靠的计算和数据处理能力。
[阿里云](https://www.aliyun.com/?source=5176.11533457\&userCode=8lx5zmtu\&type=copy)的客户群体中,活跃着微博、虎牙、魅族、优酷等一大批明星互联网公司。在天猫双 11 全球狂欢节等极富挑战的应用场景中,阿里云保持着良好的运行纪录。
[阿里云](https://www.aliyun.com/)的客户群体中,活跃着微博、虎牙、魅族、优酷等一大批明星互联网公司。在天猫双 11 全球狂欢节等极富挑战的应用场景中,阿里云保持着良好的运行纪录。
[阿里云容器服务 Kubernetes ACK](https://www.aliyun.com/product/kubernetes?source=5176.11533457\&userCode=8lx5zmtu\&type=copy) 提供了高性能、可伸缩的容器应用管理服务,支持在一组云服务器上通过 Docker 容器来进行应用生命周期管理。容器服务极大简化了用户对容器管理集群的搭建工作,无缝整合了阿里云虚拟化、存储、网络和安全能力。容器服务提供了多种应用发布方式和流水线般的持续交付能力,原生支持微服务架构,助力用户无缝上云和跨云管理。
[阿里云容器服务 Kubernetes ACK](https://cn.aliyun.com/product/ack) 提供了高性能、可伸缩的容器应用管理服务,支持在一组云服务器上通过 Docker 容器来进行应用生命周期管理。容器服务极大简化了用户对容器管理集群的搭建工作,无缝整合了阿里云虚拟化、存储、网络和安全能力。容器服务提供了多种应用发布方式和流水线般的持续交付能力,原生支持微服务架构,助力用户无缝上云和跨云管理。
<!-- 注意原阿里云容器服务截图链接已失效请参考阿里云官方文档获取最新界面截图 -->
<!-- 原链接: https://img.alicdn.com/tps/TB10yjtPpXXXXacXXXXXXXXXXXX-1531-1140.png -->
+1 -1
View File
@@ -4,7 +4,7 @@
Docker 目前已经得到了众多公有云平台的支持并成为除虚拟机之外的核心云业务
除了 AWSGoogleAzure 国内的各大公有云厂商基本上都同时支持了虚拟机服务和基于 Kubernetes 的容器云业务有的还推出了其他服务例如[容器镜像服务](https://cloud.tencent.com/act/cps/redirect?redirect=11588&cps_key=3a5255852d5db99dcd5da4c72f05df61)让用户在云上享有安全高效的镜像托管、分发等服务。
除了 AWSGoogleAzure 国内的各大公有云厂商基本上都同时支持了虚拟机服务和基于 Kubernetes 的容器云业务有的还推出了其他服务例如[容器镜像服务](https://cloud.tencent.com/document/product/1141)让用户在云上享有安全高效的镜像托管、分发等服务。
## 本章内容
+2 -2
View File
@@ -1,8 +1,8 @@
## 17.1 Fedora CoreOS 简介
> **版本说明**Fedora CoreOS 定期发布更新建议访问 [官方下载页面](https://getfedora.org/coreos/download/) 获取最新版本和兼容性信息。
> **版本说明**Fedora CoreOS 定期发布更新建议访问 [官方下载页面](https://fedoraproject.org/coreos/download/) 获取最新版本和兼容性信息。
[Fedora CoreOS](https://getfedora.org/coreos/) 是一个自动更新的,最小的,整体的,以容器为中心的操作系统,不仅适用于集群,而且可独立运行,并针对运行 Kubernetes 进行了优化。它旨在结合 CoreOS Container Linux 和 Fedora Atomic Host 的优点,将 Container Linux 中的 [Ignition](https://github.com/coreos/ignition) 与 [rpm-ostree](https://github.com/coreos/rpm-ostree) 和 Project Atomic 中的 SELinux 强化等技术相集成。其目标是提供最佳的容器主机,以安全,大规模地运行容器化的工作负载。
[Fedora CoreOS](https://fedoraproject.org/coreos/) 是一个自动更新的,最小的,整体的,以容器为中心的操作系统,不仅适用于集群,而且可独立运行,并针对运行 Kubernetes 进行了优化。它旨在结合 CoreOS Container Linux 和 Fedora Atomic Host 的优点,将 Container Linux 中的 [Ignition](https://github.com/coreos/ignition) 与 [rpm-ostree](https://github.com/coreos/rpm-ostree) 和 Project Atomic 中的 SELinux 强化等技术相集成。其目标是提供最佳的容器主机,以安全,大规模地运行容器化的工作负载。
### 17.1.1 FCOS 特性
+1 -1
View File
@@ -2,7 +2,7 @@
### 17.2.1 下载 ISO
[下载页面](https://getfedora.org/coreos/download/) `Bare Metal & Virtualized` 标签页下载 ISO。
[下载页面](https://fedoraproject.org/coreos/download/) `Bare Metal & Virtualized` 标签页下载 ISO。
### 17.2.2 编写 Butane 配置
+1 -1
View File
@@ -20,7 +20,7 @@ Docker 守护进程在启动容器时,会在后台为容器创建一套独立
> 为了缓解内核漏洞带来的威胁生产环境务必保持宿主机 Linux 内核的及时修补与更新或者借助诸如 gVisorKata Containers 等提供了独立内核的安全容器技术同时需要及时修补容器运行时 runC的漏洞2025 11 月披露的一系列 runC 容器逃逸漏洞CVE-2025-31133CVE-2025-52565CVE-2025-52881就表明即使内核保持更新运行时层的缺陷仍然可能导致容器隔离被突破
通过命名空间Docker 也能限制进程从外部环境获取信息
例如由于进程环境被隔离进程在内部其实是无法感知外部宿主机的存在的它既不能获取其他容器的进程列表也无法通过网络与其他系统进行交互除非经过配置
例如由于进程环境被隔离进程在内部通常无法直接感知外部宿主机的进程和挂载命名空间网络命名空间隔离的是网络栈默认 bridge 网络通常允许容器主动访问外部网络限制的是外部直接访问容器服务若要限制出站访问需要使用 `none` 网络防火墙Kubernetes NetworkPolicy 或运行时策略
### 18.1.3 用户命名空间与提权防护
+44 -37
View File
@@ -217,7 +217,7 @@ grype sbom:sbom.json --add-cpes-if-none
### 18.6.3 镜像签名与验证
镜像签名确保镜像的来源可信且未被篡改两种主流方案是 Cosign Notary
镜像签名确保镜像的来源可信且未被篡改新项目通常优先评估 Cosign (Sigstore) Notary Project NotationDocker Content Trust / Notary v1 属于历史路径
#### Cosign - 现代签名解决方案
@@ -269,13 +269,25 @@ cosign verify --key cosign.pub "$IMAGE_DIGEST"
# GitHub Actions CI 中无需存储密钥
cosign sign --yes "$IMAGE_DIGEST"
# 验证时自动使用 OIDC 令牌验证身份
# 验证时检查签名证书中的 OIDC 身份声明是否匹配预期 workflow issuer
cosign verify "$IMAGE_DIGEST" \
--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
#### Notary Project / Notation
Notation Notary Project OCI 签名工具适合希望采用 CNCF Notary Project 规范或使用 registry/云厂商原生集成的团队 Cosign 类似生产环境应围绕不可变 digest 做签名和策略校验
```bash
# 签名已推送的镜像 digest
notation sign myregistry.com/myapp@sha256:<digest>
# 验证签名
notation verify myregistry.com/myapp@sha256:<digest>
```
#### Docker Content Trust Notary v1
> **注意DCT 退役时间线**
>
@@ -283,7 +295,7 @@ cosign verify "$IMAGE_DIGEST" \
>
> 新项目应优先使用上文介绍的 **Cosign (Sigstore)** registry 原生签名/证明能力现有 DCT 用户应先盘点依赖验证替代方案再制定迁移计划
Docker Content Trust 使用 Notary 实现镜像签名 Docker 官方的传统签名解决方案
Docker Content Trust 使用 Notary v1 实现镜像签名 Docker 官方的传统签名解决方案不建议新项目采用
**历史用法示例不建议新项目采用**
@@ -353,17 +365,7 @@ trivy image --scanners vuln,misconfig registry:5000/myapp:latest
**Harbor私有镜像仓库的安全扫描**
```yaml
# harbor.yml 配置示例
trivy:
enabled: true
# 启用镜像扫描
image_source: "Official"
# 默认扫描配置
scan_on_push: true # 推送时自动扫描
scan_all: true # 扫描仓库中的所有镜像
```
Harbor 的扫描器应在管理界面的 **Interrogation Services / Scanner** 中配置推送自动扫描通常在项目级 **Configuration** 中启用不要把扫描策略误写成通用 `harbor.yml` 顶层字段实际部署时应按所用 Harbor 版本文档配置 scanner项目策略和漏洞阻断阈值
#### 5. 政策执行
@@ -427,13 +429,33 @@ jobs:
if: github.event_name == 'push'
uses: sigstore/cosign-installer@v3
- name: Build Docker image for scan
- name: Login to Registry
if: github.event_name == 'push'
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
if: github.event_name == 'push'
id: build-push
uses: docker/build-push-action@v7
with:
context: .
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
provenance: mode=max
sbom: true
- name: Build Docker image for pull request scan
if: github.event_name == 'pull_request'
uses: docker/build-push-action@v7
with:
context: .
push: false
load: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
tags: local/${{ env.IMAGE_NAME }}:pr
- name: Run Trivy vulnerability scan
# 安全提醒2026 3 19 Trivy GitHub Actions 遭受供应链攻击
@@ -441,7 +463,7 @@ jobs:
# 使用前请到 https://github.com/aquasecurity/trivy-action/releases 核实 SHA 对应正确版本。
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
image-ref: ${{ github.event_name == 'push' && format('{0}/{1}@{2}', env.REGISTRY, env.IMAGE_NAME, steps.build-push.outputs.digest) || format('local/{0}:pr', env.IMAGE_NAME) }}
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'HIGH,CRITICAL'
@@ -454,7 +476,7 @@ jobs:
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
image: ${{ github.event_name == 'push' && format('{0}/{1}@{2}', env.REGISTRY, env.IMAGE_NAME, steps.build-push.outputs.digest) || format('local/{0}:pr', env.IMAGE_NAME) }}
format: cyclonedx-json
output-file: sbom-cyclonedx.json
@@ -464,23 +486,6 @@ jobs:
name: sbom
path: sbom-cyclonedx.json
- name: Login to Registry and Push
if: github.event_name == 'push'
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push image
if: github.event_name == 'push'
id: build-push
uses: docker/build-push-action@v7
with:
context: .
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Sign image with Cosign
if: github.event_name == 'push'
run: |
@@ -529,7 +534,9 @@ generate:sbom:
- syft docker-archive://image.tar -o cyclonedx > sbom.xml
artifacts:
reports:
sbom: sbom.xml
cyclonedx: sbom.xml
# 如需让 GitLab 安全面板摄取容器扫描结果应输出 GitLab 兼容的 container_scanning 报告
push:
stage: push
+8 -6
View File
@@ -66,7 +66,7 @@ services:
- ./rules.yml:/etc/prometheus/rules.yml
- prometheus_data:/prometheus
ports:
- "9090:9090"
- "127.0.0.1:9090:9090"
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
@@ -77,9 +77,9 @@ services:
grafana:
image: grafana/grafana:13.0.1
ports:
- "3000:3000"
- "127.0.0.1:3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD:?set GRAFANA_ADMIN_PASSWORD}
networks:
- monitoring
depends_on:
@@ -88,14 +88,14 @@ services:
node-exporter:
image: prom/node-exporter:v1.11.1
ports:
- "9100:9100"
- "127.0.0.1:9100:9100"
networks:
- monitoring
cadvisor:
image: ghcr.io/google/cadvisor:v0.56.2
ports:
- "8080:8080"
- "127.0.0.1:8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
@@ -119,7 +119,9 @@ $ docker compose up -d
启动后访问以下地址
* Prometheus: `http://localhost:9090`
* Grafana`http://localhost:3000` (默认账号密码admin/admin首次登录后务必立即修改密码)
* Grafana`http://localhost:3000` (账号为 `admin`密码来自 `GRAFANA_ADMIN_PASSWORD`)
> 安全提示cAdvisor 需要读取宿主机 `/sys``/var/run`Docker 数据目录等路径才能采集容器指标即使是只读挂载也会暴露宿主机和容器元数据只在受控监控节点使用并把 PrometheusGrafanacAdvisor 端口绑定到本机或受保护网络
### 19.1.3 配置 Grafana 面板
-4
View File
@@ -42,8 +42,6 @@ services:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
ports:
- "5601:5601"
links:
- elasticsearch
networks:
- logging
@@ -59,8 +57,6 @@ services:
ports:
- "24224:24224"
- "24224:24224/udp"
links:
- elasticsearch
volumes:
- ./fluentd/conf:/fluentd/etc
networks:
@@ -6,44 +6,18 @@
#### 核心性能指标体系
容器性能监控涉及以下关键指标
容器性能监控涉及 Docker CLIPrometheus/cAdvisor 指标和底层 cgroup 文件现代 Linux Kubernetes 新版本通常使用 cgroup v2旧系统或兼容环境仍可能看到 cgroup v1 名称
**CPU 相关指标**
- `cpu.usage_usec`容器 CPU 使用时间微秒
- `cpu.stat.nr_throttled`CPU 限流发生次数
- `cpu.stat.throttled_usec`CPU 限流总时间
- `cpu_percent`CPU 使用百分比
- `cpu_quota`CPU 配额设置微秒
**内存相关指标**
- `memory.usage_bytes`当前内存使用量
- `memory.max_usage_bytes`内存使用峰值
- `memory.limit_in_bytes`内存限制
- `memory.fail_cnt`OOMOut of Memory失败次数
- `memory.stat.cache`页面缓存占用
- `memory.stat.rss`实际内存占用RSS
- `memory.stat.swap`SWAP 使用量
**网络相关指标**
- `rx_bytes`接收字节数
- `tx_bytes`发送字节数
- `rx_packets`接收包数
- `tx_packets`发送包数
- `rx_errors`接收错误数
- `tx_errors`发送错误数
- `rx_dropped`接收丢包数
- `tx_dropped`发送丢包数
**I/O 相关指标**
- `io_service_bytes`I/O 操作字节数
- `io_service_time`I/O 操作耗时
- `io_queued`I/O 队列长度
- `fs_limit_bytes`文件系统限制
- `fs_usage_bytes`文件系统使用量
| 类型 | Docker / Prometheus 常见指标 | cgroup v2 文件 | cgroup v1 兼容名 |
|------|------------------------------|----------------|------------------|
| CPU 使用 | `CPU %``container_cpu_usage_seconds_total` | `cpu.stat` 中的 `usage_usec` | `cpuacct.usage` |
| CPU 限流 | `container_cpu_cfs_throttled_periods_total` | `cpu.stat` 中的 `nr_throttled``throttled_usec` | `cpu.stat.nr_throttled``cpu.stat.throttled_time` |
| 内存使用 | `MEM USAGE``container_memory_working_set_bytes` | `memory.current` | `memory.usage_in_bytes` |
| 内存限制 | `MEM USAGE / LIMIT` | `memory.max` | `memory.limit_in_bytes` |
| OOM 次数 | `container_oom_events_total` 或运行时事件 | `memory.events` 中的 `oom` / `oom_kill` | `memory.failcnt` |
| 网络收发 | `NET I/O``container_network_receive_bytes_total` / `transmit_bytes_total` | 网络命名空间接口计数 | `rx_bytes` / `tx_bytes` |
| I/O | `BLOCK I/O``container_fs_*` / `container_blkio_*` | `io.stat` | `blkio.throttle.io_service_bytes` |
| 文件系统 | `container_fs_usage_bytes` / `container_fs_limit_bytes` | 运行时或文件系统采集 | `fs_usage_bytes` / `fs_limit_bytes` |
### 19.3.2 使用 docker stats 实时监控
@@ -246,6 +220,16 @@ networks:
```
**Prometheus 配置文件prometheus.yml**
如果需要采集 Docker daemon 自身指标需要先在 Docker daemon 配置中开启 metrics
```json
{
"metrics-addr": "127.0.0.1:9323"
}
```
Prometheus 运行在容器里并使用 `host.docker.internal:9323` 抓取时daemon 必须监听容器可达的主机地址若改为 `0.0.0.0:9323`会把指标端口暴露给更大网络必须配合防火墙和可信网络边界
```yaml
global:
scrape_interval: 15s
+3
View File
@@ -72,6 +72,8 @@ jobs:
ghcr.io/${{ github.repository }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
provenance: mode=max
sbom: true
```
关键说明
@@ -79,6 +81,7 @@ jobs:
* `docker/login-action` 负责认证支持 Docker HubGHCRECR 等主流 Registry
* `cache-from` / `cache-to` 使用 GitHub Actions 原生缓存`type=gha`无需额外配置即可加速增量构建
* 标签同时使用 commit hash `latest`兼顾版本追溯与部署便利
* `provenance: mode=max` `sbom: true` 会把构建来源证明和 SBOM 附加到推送的镜像上只做本地 `load: true` 的构建无法完整保留这些 attestation
### 21.2.3 最佳实践
+2
View File
@@ -7,6 +7,8 @@
本小节以 `GitHub` + `Drone` 来演示 `Drone` 的工作流程
当然在实际开发过程中你的代码也许不在 GitHub 托管那么你可以尝试使用 `Gogs` + `Drone` 来进行 CI/CD
> 安全提示Docker runner 如果挂载宿主机 `/var/run/docker.sock`流水线就具备近似宿主机 root 的控制能力下面配置只适合可信代码单租户本地演示环境生产环境应使用隔离的临时 runner/虚拟机Kubernetes runnerrootless 方案或更严格的权限边界并为不同项目隔离密钥
### 21.3.1 关联项目
GitHub 新建一个名为 `drone-demo` 的仓库
+2 -5
View File
@@ -557,6 +557,8 @@ client-output-buffer-limit pubsub 32mb 8mb 60
**三层微服务架构示例**
> 下面示例聚焦服务拓扑网络健康检查和资源限制为便于阅读密码仍通过环境变量串接生产环境应改用 Compose secrets外部密钥系统或云厂商密钥服务并避免把敏感值写入 `DATABASE_URL` / `REDIS_URL`
```yaml
services:
# 前端服务
@@ -564,7 +566,6 @@ services:
build:
context: ./frontend
dockerfile: Dockerfile
container_name: frontend
ports:
- "3000:3000"
environment:
@@ -586,7 +587,6 @@ services:
build:
context: ./api
dockerfile: Dockerfile
container_name: api
ports:
- "8000:8000"
environment:
@@ -619,7 +619,6 @@ services:
# PostgreSQL 数据库
postgres:
image: postgres:16-alpine
container_name: postgres
environment:
POSTGRES_DB: myappdb
POSTGRES_USER: appuser
@@ -641,7 +640,6 @@ services:
# Redis 缓存
redis:
image: redis:8-alpine
container_name: redis
command: ["sh", "-c", "redis-server --appendonly yes --requirepass \"$$REDIS_PASSWORD\""]
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:?set REDIS_PASSWORD}
@@ -659,7 +657,6 @@ services:
# Nginx 反向代理
nginx:
image: nginx:alpine
container_name: nginx
ports:
- "80:80"
- "443:443"
+1
View File
@@ -25,6 +25,7 @@ services:
depends_on:
- drone-server
volumes:
# Trusted single-tenant demo only: Docker socket access is host-root equivalent.
- /var/run/docker.sock:/var/run/docker.sock:rw
environment:
- DRONE_RPC_PROTO=http
+9 -9
View File
@@ -48,10 +48,10 @@
graph LR
Start[Docker 学习入口] --> Ch1[第1章Docker 简介]
Ch1 --> Role1["运维新手<br/>第1-4章"]
Ch1 --> Role2["开发者<br/>第1-3章 → 第5-8章"]
Ch1 --> Role3["DevOps 工程师<br/>第1章 → 第9-14章 → 第18章"]
Ch1 --> Role4["架构师<br/>第1章 → 第15-21章"]
Ch1 --> Role1["运维新手<br/>第1-6章"]
Ch1 --> Role2["开发者<br/>第1-8章 → 第11章"]
Ch1 --> Role3["DevOps 工程师<br/>第1-11章 → 第13-14章 → 第18-21章"]
Ch1 --> Role4["架构师<br/>第1-6章 → 第12-17章 → 第18-19章"]
Role1 --> End1["掌握基本操作"]
Role2 --> End2["构建与部署应用"]
@@ -60,14 +60,14 @@ graph LR
```
| 读者角色 | 学习重点 | 核心成果 |
|---------|---------|---------|
| **运维新手** | 第1-4 | 掌握容器的基本概念与操作 |
| **开发者** | 第1-3 5-8 | 学会容器化应用的构建与部署 |
| **DevOps 工程师** | 第1章 9-14 第18章 | 实现容器编排与自动化部署流程 |
| **架构师** | 第1章 第15-21 | 设计高可用高性能的容器基础设施 |
| **运维新手** | 第1-6 | 掌握容器的基本概念与操作 |
| **开发者** | 第1-8 11 | 学会容器化应用的构建与部署 |
| **DevOps 工程师** | 第1-11 13-14 第18-21 | 实现容器编排与自动化部署流程 |
| **架构师** | 第1-6 第12-17 第18-19 | 设计高可用高性能的容器基础设施 |
## 在线阅读
本书在线阅读可直接访问 [GitBook](https://yeasy.gitbook.io/docker_practice/)。也可访问 [GitHub 仓库目录](https://github.com/yeasy/docker_practice/blob/master/SUMMARY.md) 或 [镜像站点](https://vuepress.mirror.docker-practice.com/)
本书在线阅读可直接访问 [GitBook](https://yeasy.gitbook.io/docker_practice/)。也可访问 [GitHub 仓库目录](https://github.com/yeasy/docker_practice/blob/master/SUMMARY.md)。
## 下载离线版本
+1 -1
View File
@@ -129,7 +129,7 @@
* [14.4 Kind - Kubernetes IN Docker](14_kubernetes_setup/14.4_kind.md)
* [14.5 K3s - 轻量级 Kubernetes](14_kubernetes_setup/14.5_k3s.md)
* [14.6 一步步部署 Kubernetes 集群](14_kubernetes_setup/14.6_systemd.md)
* [14.7 部署 Dashboard](14_kubernetes_setup/14.7_dashboard.md)
* [14.7 可视化管理界面](14_kubernetes_setup/14.7_dashboard.md)
* [14.8 Kubernetes 命令行 kubectl](14_kubernetes_setup/14.8_kubectl.md)
* [本章小结](14_kubernetes_setup/summary.md)
* [第十五章 Etcd 项目](15_etcd/README.md)
+1 -1
View File
@@ -1,6 +1,6 @@
## 附录四Dockerfile 最佳实践
本附录是笔者对 Docker 官方文档中 [Best practices for writing Dockerfiles](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) 的理解与翻译。
本附录是笔者对 Docker 官方文档中 [Building best practices](https://docs.docker.com/build/building/best-practices/) 的理解与翻译。
### 一般性的指南和建议
+2
View File
@@ -73,6 +73,8 @@ $ 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
```
这个固定 IP 主要用于同一 Docker daemon 内的容器间通信Docker Desktop 上不要依赖宿主机直接访问 Linux 容器 IP宿主机访问容器服务仍应使用端口映射或 `host.docker.internal` 等机制
### 如何临时退出一个正在交互的容器的终端而不终止它
`Ctrl-p Ctrl-q`如果按 `Ctrl-c` 往往会让容器内应用进程终止进而会终止容器
+3 -3
View File
@@ -116,8 +116,8 @@ Docker Compose
**学习资源**
- 本书第 4-11 进阶篇
- [Docker 官方最佳实践](https://docs.docker.com/develop/dev-best-practices/)
- [Dockerfile 参考](https://docs.docker.com/engine/reference/builder/)
- [Docker 官方最佳实践](https://docs.docker.com/build/building/best-practices/)
- [Dockerfile 参考](https://docs.docker.com/reference/dockerfile/)
**时间投入**
@@ -477,7 +477,7 @@ Kubernetes 进阶 (Week 24-36)
# 1. 学习本书第 1-11 基础到中级
# 2. 完成 20+ 个实战项目
# 3. 参考官方学习指南
# 参考 KodeKloud DCA 认证指南https://kodekloud.com/blog/docker-certified-associate-guide/
# 参考 Docker 官方学习入口https://www.docker.com/resources/
# 4. 模拟考试
- Linux Academy DCA 练习题
+1 -1
View File
@@ -13,7 +13,7 @@
```bash
$ docker run --name some-redis -d -p 6379:6379 redis
```
另外还可以启用[持久存储](https://redis.io/topics/persistence)。
另外还可以启用[持久存储](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/)。
```bash
$ docker run --name some-redis -d -p 6379:6379 redis redis-server --appendonly yes
+1 -1
View File
@@ -24,7 +24,7 @@
* [Docker CLI 参考](https://docs.docker.com/engine/reference/commandline/docker/)
* [Dockerfile 参考](https://docs.docker.com/reference/dockerfile/)
* [Docker 构建最佳实践](https://docs.docker.com/build/building/best-practices/)
* [Docker 远端应用 API](https://docs.docker.com/develop/sdk/)
* [Docker 远端应用 API](https://docs.docker.com/reference/api/engine/sdk/)
* [Docker 存储文档](https://docs.docker.com/engine/storage/)
* [Docker 网络文档](https://docs.docker.com/engine/network/)
-12
View File
@@ -24,15 +24,3 @@ services:
vuepress-offline:
<< : *mdpress-offline
image: dockerpracticesig/docker_practice:vuepress
# developer test docker image
development:
build: ./.travis
image: yeasy/docker_practice:latest
ports:
- 4000:4000
volumes:
- ./:/srv/gitbook-src
command: server
# command: build