Compare commits

..
10 Commits
45 changed files with 100 additions and 93 deletions
+1 -1
View File
@@ -172,7 +172,7 @@ registry.example.com/myproject/myapp:v1.2.3
## 简写(使用 Docker Hub
nginx:1.28
nginx:1.30
ubuntu:24.04
## 省略标签(默认使用 latest)
+6 -6
View File
@@ -1,6 +1,6 @@
## 2.3 仓库
> **版本说明**本节示例基于 Docker v29.x 和常见镜像版本编写示例中的版本号 `nginx:1.28``mysql:8.0``mysql:5.7` 为演示用途实际使用时请访问 [Docker Hub 官方页面](https://hub.docker.com) 或相应镜像的发布页确认最新可用版本和标签。
> **版本说明**本节示例基于 Docker v29.x 和常见镜像版本编写示例中的版本号 `nginx:1.30``mysql:8.4``mysql:5.7` 为演示用途实际使用时请访问 [Docker Hub 官方页面](https://hub.docker.com) 或相应镜像的发布页确认最新可用版本和标签。
Docker Registry 是镜像分发和管理的核心组件本节将介绍 Registry 的基本概念公共和私有服务的选择以及镜像的安全管理
@@ -73,7 +73,7 @@ registry.example.com/mycompany/myapp:v1.2.3
## Docker Hub 官方镜像(省略 registry 和用户名)
nginx:1.28
nginx:1.30
ubuntu:24.04
## Docker Hub 用户镜像
@@ -217,7 +217,7 @@ $ docker login registry.example.com # 登录其他 Registry
## 拉取镜像
$ docker pull nginx:1.28
$ docker pull nginx:1.30
## 标记镜像(准备推送)
@@ -261,9 +261,9 @@ someuser/myapp # ⚠️ 需要评估
```bash
## 准备一个你有写权限的镜像地址
$ export IMAGE=<你的仓库名>/nginx:1.27
$ docker pull nginx:1.27
$ docker tag nginx:1.27 $IMAGE
$ export IMAGE=<你的仓库名>/nginx:1.30
$ docker pull nginx:1.30
$ docker tag nginx:1.30 $IMAGE
$ docker push $IMAGE
## 生成签名密钥(会生成 cosign.key / cosign.pub
+1 -1
View File
@@ -4,7 +4,7 @@
> **版本号最佳实践**
>
> - **永远指定版本号**避免使用 `latest` 标签应指定具体的版本 `ubuntu:24.04``nginx:1.27`以确保镜像内容稳定一致
> - **永远指定版本号**避免使用 `latest` 标签应指定具体的版本 `ubuntu:24.04``nginx:1.30`以确保镜像内容稳定一致
> - **在生产环境使用摘要**优先使用镜像摘要SHA256而非标签 `nginx@sha256:abc123...`因为摘要不可变
> - **定期评估依赖**即使指定了版本号仍应定期检查依赖的基础镜像是否有安全更新
+3 -3
View File
@@ -10,7 +10,7 @@
现在让我们以定制一个 Web 服务器为例子来讲解镜像是如何构建的
> **版本提示**以下示例中 `nginx` 镜像使用默认 `latest` 标签生产环境建议指定具体版本号 `nginx:1.27`以避免镜像更新带来的不兼容性
> **版本提示**以下示例中 `nginx` 镜像使用默认 `latest` 标签生产环境建议指定具体版本号 `nginx:1.30`以避免镜像更新带来的不兼容性
```bash
$ docker run --name webserver -d -p 8080:80 nginx
@@ -89,11 +89,11 @@ sha256:07e33465974800ce65751acc279adc6ed2dc5ed4e0838f8b86f0c87aa1795214
$ docker image ls nginx
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 07e334659748 9 seconds ago 181.5 MB
nginx 1.27 05a60462f8ba 12 days ago 181.5 MB
nginx 1.30 05a60462f8ba 12 days ago 181.5 MB
nginx latest e43d811ce2f4 4 weeks ago 181.5 MB
```
> **版本说明**上面示例中 `nginx:1.27` 代表 1.27 系列的最新 patch 版本际应用中应根据需求选择确切的版本号而不是盲目使用 `latest`
> **版本说明**上面示例中 `nginx:1.30` 代表 1.30 系列的最新 patch 版本际应用中应根据需求选择确切的版本号而不是盲目使用 `latest`
我们还可以用 `docker history` 具体查看镜像内的历史记录例如先执行 `docker history nginx:v2`再对比 `docker history nginx:latest`就能看到我们刚刚提交出来的新层
+1 -1
View File
@@ -26,7 +26,7 @@ $ touch Dockerfile
```
其内容为
> **版本提示**下面示例中 `FROM nginx` 使用的是 `latest` 标签在实际应用中应使用明确的版本号 `FROM nginx:1.27`以确保 Dockerfile 的可重现性和稳定性
> **版本提示**下面示例中 `FROM nginx` 使用的是 `latest` 标签在实际应用中应使用明确的版本号 `FROM nginx:1.30`以确保 Dockerfile 的可重现性和稳定性
```docker
FROM nginx
+1 -1
View File
@@ -60,7 +60,7 @@ Docker 镜像的每一层都有一个唯一的 ID,这个 ID 是根据该层的
Docker 使用联合文件系统 (Union FS) 与写时复制思路来实现这种分层挂载传统的实现方式常见于 `overlay2``aufs``btrfs``zfs` 等存储驱动而在 Docker Engine 29.0 及之后的全新安装中默认镜像后端已经变为 containerd image store它使用 snapshotter 来管理这些层
> **版本背景**Docker Engine 29.0发布于 2024 2 是一个重要版本分界点引入了 containerd image store 作为默认镜像存储后端这对镜像管理OCI 合规性和供应链安全都有深远影响如果你的 Docker 版本低于 29.0镜像存储仍使用传统的 classic store 路径
> **版本背景**Docker Engine 29.0发布于 2026 1 是一个重要版本分界点在全新安装场景下默认启用 containerd image store 作为镜像存储后端这对镜像管理OCI 合规性和供应链安全都有深远影响如果你的 Docker 版本低于 29.0镜像存储仍使用传统的 classic store 路径
虽然底层实现细节不同但它们都遵循上述的 **分层 + CoW** 模型因此无论你看到的是 `overlay2` 还是 containerd snapshotter理解镜像层容器层和写时复制的方式都是一样重要的
+2 -2
View File
@@ -126,14 +126,14 @@ $ docker run -d -p 80:80 nginx:latest
## 数据库
$ docker run -d -p 3306:3306 mysql:8.0
$ docker run -d -p 3306:3306 mysql:8.4
## 缓存服务
$ docker run -d -p 6379:6379 redis:latest
```
> **版本说明**示例使用常见的标签如 `latest` 或稳定大版本号如 `mysql:8.0`具体版本可根据需求调整生产环境建议明确指定版本号 `mysql:8.0.35`而非使用 `latest`
> **版本说明**示例使用常见的标签如 `latest` 或稳定大版本号如 `mysql:8.4`具体版本可根据需求调整生产环境建议明确指定版本号 `mysql:8.4.4`而非使用 `latest`
#### 2. 调试时先用前台模式
+1 -1
View File
@@ -212,7 +212,7 @@ FROM node:22-alpine
CMD ["node", "server.js"]
```
> **版本说明**示例使用 `node:22-alpine`这是一个精简的 Node.js 22 版本镜像可根据需求替换为其他版本 `node:20-alpine``node:latest`
> **版本说明**示例使用 `node:22-alpine`这是一个精简的 Node.js 22 版本镜像可根据需求替换为其他版本 `node:24-alpine``node:latest`
#### Q容器无法停止
+3 -3
View File
@@ -10,11 +10,11 @@
本章示例涉及多个 Docker 镜像遵循以下版本号最佳实践
- **官方镜像** `ubuntu``nginx``mysql`使用具体大版本号 `ubuntu:24.04``mysql:8.0`而非 `latest`确保示例的可重复性
- **官方镜像** `ubuntu``nginx``mysql`使用具体大版本号 `ubuntu:24.04``mysql:8.4`而非 `latest`确保示例的可重复性
- **镜像标签约定**
- `latest` `v1.0.0` 带标签的自定义镜像示例中指定具体版本
- `24.04``8.0`官方镜像的稳定版本分支
- 生产环境建议指定确版本号 `nginx:1.24.0``mysql:8.0.35`而非仅大版本号
- `24.04``8.4`官方镜像的稳定版本分支
- 生产环境建议指定确版本号 `nginx:1.30.0``mysql:8.4.4`而非仅大版本号
* [启动容器](5.1_run.md)
* [守护态运行](5.2_daemon.md)
+4 -4
View File
@@ -82,9 +82,9 @@ RUN pwd # 输出 /app
```docker
## 构建阶段
## 建议使用 node:20 node: 等具体版本标签避免使用 latest
## 建议使用 node:22 node: 等具体版本标签避免使用 latest
FROM node:20 AS builder
FROM node:22 AS builder
WORKDIR /build
COPY package*.json ./
RUN npm install
@@ -105,8 +105,8 @@ COPY --from=builder /build/dist .
#### 1. 尽早设置 WORKDIR
```docker
# 建议使用 node:20 等主/次版本号标签
FROM node:20
# 建议使用 node:22 等主/次版本号标签
FROM node:22
WORKDIR /app # 尽早设置
COPY package*.json ./
+4 -4
View File
@@ -35,7 +35,7 @@ flowchart LR
#### 创建并切换用户
```docker
FROM node:20-alpine
FROM node:22-alpine
## 1. 创建用户和组
@@ -173,7 +173,7 @@ $ docker run -u root myimage
切换用户后确保应用有权访问文件
```docker
FROM node:20-alpine
FROM node:22-alpine
## 创建用户
@@ -229,14 +229,14 @@ USER 1000:1000
```docker
## 构建阶段可以用 root
FROM node:20 AS builder
FROM node:22 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
## 生产阶段用非 root
FROM node:20-alpine
FROM node:22-alpine
RUN adduser -D appuser
WORKDIR /app
COPY --from=builder --chown=appuser:appuser /app/dist .
+1 -1
View File
@@ -34,7 +34,7 @@ Starting ──成功──> Healthy ──失败N次──> Unhealthy
#### Web 服务检查
```docker
# nginx 镜像推荐使用具体的版本标签 nginx:1.28-alpine
# nginx 镜像推荐使用具体的版本标签 nginx:1.30-alpine
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
+2 -2
View File
@@ -30,7 +30,7 @@ ONBUILD <其它指令>
**基础镜像 (my-node-base)**
```docker
FROM node:20-alpine
FROM node:22-alpine
WORKDIR /app
## 这些指令将在子镜像构建时执行
@@ -126,7 +126,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/
建议在镜像标签中添加 `-onbuild` 后缀明确告知使用者该镜像包含触发器
```bash
node:20-onbuild
node:22-onbuild
python:3.12-onbuild
```
+1 -1
View File
@@ -176,5 +176,5 @@ $ docker build --target builder -t username/imagename:tag .
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件我们也可以复制任意镜像中的文件
```docker
COPY --from=nginx:1.28-alpine /etc/nginx/nginx.conf /nginx.conf
COPY --from=nginx:1.30-alpine /etc/nginx/nginx.conf /nginx.conf
```
@@ -60,8 +60,8 @@ server {
第一阶段进行前端构建
```docker
# node 镜像推荐使用具体的版本标签 node:20-alpine
FROM node:20-alpine as frontend
# node 镜像推荐使用具体的版本标签 node:22-alpine
FROM node:22-alpine as frontend
COPY package.json /app/
@@ -128,8 +128,8 @@ RUN set -x ; cd ${LARAVEL_PATH} \
### 7.18.5 最后一个阶段构建 NGINX 镜像
```docker
# nginx 镜像推荐使用具体的版本标签 nginx:1.28-alpine
FROM nginx:1.28-alpine as nginx
# nginx 镜像推荐使用具体的版本标签 nginx:1.30-alpine
FROM nginx:1.30-alpine as nginx
ARG LARAVEL_PATH=/app/laravel
@@ -179,8 +179,8 @@ $ docker run -dit --rm --network=laravel -p 8080:80 my/nginx
完整的 `Dockerfile` 文件如下
```docker
# 生产环境推荐使用具体的版本标签 node:20-alpinecomposer:2.xphp:8.3-fpm-alpinenginx:1.28-alpine
FROM node:20-alpine as frontend
# 生产环境推荐使用具体的版本标签 node:22-alpinecomposer:2.xphp:8.3-fpm-alpinenginx:1.30-alpine
FROM node:22-alpine as frontend
COPY package.json /app/
@@ -229,7 +229,7 @@ RUN set -x ; cd ${LARAVEL_PATH} \
&& chmod -R 777 storage \
&& php artisan package:discover
FROM nginx:1.28-alpine as nginx
FROM nginx:1.30-alpine as nginx
ARG LARAVEL_PATH=/app/laravel
+1 -1
View File
@@ -178,7 +178,7 @@ ADD app.tar.gz /app/
```docker
## 构建阶段
FROM node:20 AS builder
FROM node:22 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
+2 -2
View File
@@ -6,8 +6,8 @@
这是 Dockerfile 使用中最常见的困惑之一简单的答案是
- **CMD**定义容器的默认命令如果用户在 `docker run` 时提供命令CMD 会被覆盖
- **ENTRYPOINT**定义容器的入口脚本通常用于启动应用的某个特定部分
- **CMD**定义容器的默认命令如果用户在 `docker run` 时提供命令CMD 会被覆盖
- **ENTRYPOINT**定义容器的入口脚本通常用于启动应用的某个特定部分
**决策树**
+3 -3
View File
@@ -158,15 +158,15 @@ $ docker build --build-arg NODE_VERSION=18 -t myapp .
```docker
## 版本集中管理
ENV NGINX_VERSION=1.25 \
NODE_VERSION=20 \
ENV NGINX_VERSION=1.30 \
NODE_VERSION=22 \
PYTHON_VERSION=3.12
RUN apt-get install nginx=${NGINX_VERSION}
## 版本分散在各处
RUN apt-get install nginx=1.25
RUN apt-get install nginx=1.30
```
#### 2. 不要存储敏感信息
+4 -4
View File
@@ -93,14 +93,14 @@ RUN echo "Node version: $NODE_VERSION"
```docker
ARG BASE_VERSION=alpine
FROM node:20-${BASE_VERSION} AS builder
FROM node:22-${BASE_VERSION} AS builder
## 需要重新声明
ARG NODE_VERSION=20
RUN echo "Building with Node $NODE_VERSION"
FROM node:20-${BASE_VERSION}
FROM node:22-${BASE_VERSION}
## 每个阶段都需要重新声明
@@ -125,8 +125,8 @@ $ docker build --build-arg ALPINE_VERSION=3.19 .
#### 2. 设置软件版本
```docker
# 使用次版本号 (1.25) 而非完整版本号 (1.25.0)以便自动更新到最新补丁版本
ARG NGINX_VERSION=1.25
# 使用次版本号 (1.30) 而非完整版本号 (1.30.0)以便自动更新到最新补丁版本
ARG NGINX_VERSION=1.30
RUN curl -fsSL https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz | tar -xz
```
+7 -7
View File
@@ -44,7 +44,7 @@ flowchart LR
#### 定义单个卷
```docker
FROM mysql:8.0
FROM mysql:8.4
VOLUME /var/lib/mysql
```
@@ -63,7 +63,7 @@ VOLUME ["/data", "/logs", "/config"]
如果运行时未指定挂载Docker 会自动创建匿名卷
```bash
$ docker run mysql:8.0
$ docker run mysql:8.4
$ docker volume ls
DRIVER VOLUME NAME
local a1b2c3d4e5f6... # 自动创建的匿名卷
@@ -74,7 +74,7 @@ local a1b2c3d4e5f6... # 自动创建的匿名卷
```bash
## 使用命名卷替代匿名卷
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
$ docker run -v mysql_data:/var/lib/mysql mysql:8.4
```
#### 3. 可被 Bind Mount 覆盖
@@ -82,7 +82,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.0
```bash
## 使用宿主机目录替代
$ docker run -v /my/data:/var/lib/mysql mysql:8.0
$ docker run -v /my/data:/var/lib/mysql mysql:8.4
```
---
@@ -145,7 +145,7 @@ VOLUME /app/uploads
```bash
## 查看镜像定义的 VOLUME
$ docker inspect mysql:8.0 --format '{{json .Config.Volumes}}' | jq
$ docker inspect mysql:8.4 --format '{{json .Config.Volumes}}' | jq
{
"/var/lib/mysql": {}
}
@@ -196,7 +196,7 @@ volumes:
```bash
## 使用 --rm 运行的容器匿名卷会在容器删除时一起删除
$ docker run --rm mysql:8.0
$ docker run --rm mysql:8.4
## 容器停止后数据丢失
@@ -205,7 +205,7 @@ $ docker run --rm mysql:8.0
**解决**始终使用命名卷
```bash
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
$ docker run -v mysql_data:/var/lib/mysql mysql:8.4
```
---
+1 -1
View File
@@ -80,7 +80,7 @@ docker build -t my-image:1.0 .
本章中的 Dockerfile 示例使用的基础镜像标签遵循以下原则
- **通用标签** `ubuntu:24.04``alpine``nginx`保持原样无需修改
- **基础镜像版本号** `node:20``python:3.12`使用主或次版本号而非完整版本号patch这样可以自动获取最新的补丁版本确保获得安全更新
- **基础镜像版本号** `node:22``python:3.12`使用主或次版本号而非完整版本号patch这样可以自动获取最新的补丁版本确保获得安全更新
- **避免**不建议使用 `latest` 标签和完整的 patch 版本号 `20.10.0`作为基础镜像因为这会导致构建的不可重现性或安全风险
读者在使用这些示例时应根据实际生产环境需求选择合适的版本号
@@ -1,4 +1,4 @@
FROM node:20-alpine as frontend
FROM node:22-alpine as frontend
COPY package.json /app/
@@ -47,7 +47,7 @@ RUN set -x ; cd ${LARAVEL_PATH} \
&& chmod -R 777 storage \
&& php artisan package:discover
FROM nginx:1.28-alpine as nginx
FROM nginx:1.30-alpine as nginx
ARG LARAVEL_PATH=/app/laravel
+1
View File
@@ -21,6 +21,7 @@ ghi789... none null local
| **none** | 禁用网络 | 完全隔离的容器 |
| **overlay** | 跨主机网络 | Docker Swarm 集群 |
| **macvlan** | 容器拥有独立 MAC 地址 | 需要直接接入物理网络 |
| **ipvlan** | 容器共享父接口 MAC独享 IP | 同网段大量容器 MAC 数量受限的网络 |
### 9.2.2 Bridge 网络默认
+1 -1
View File
@@ -39,7 +39,7 @@ $ docker buildx build --sbom=true -t myimage .
> ** 注意与失败模式**
> 要使 SBOM (或其它 attestation 元数据) 成功附着并可见对底层的存储格式有前置要求默认的 classic image store 不支持 manifest list/index 这种存放 attestation 的结构
>
> 如果只简单运行上述命令你可能会面临 **命令成功执行但本地镜像中看不到 SBOM** 的体会落差
> 如果只简单运行上述命令你可能会面临 **命令成功执行但本地镜像中看不到 SBOM** 的体会落差
>
> **正确的解决路径有两条**
> 1. **推送到远端仓库**使用 `docker buildx build --sbom=true --push -t myimage:tag` SBOM 会正确保存到远端仓库远端 OCI 兼容的镜像仓库能够完整存储这些元数据
+1 -1
View File
@@ -490,7 +490,7 @@ volumes:
```yaml
services:
my_src:
image: mysql:8.0
image: mysql:8.4
volumes:
- mysql_data:/var/lib/mysql
+3 -3
View File
@@ -28,13 +28,13 @@ services:
# 数据库服务
db:
image: mysql:8.0
image: mysql:8.4
container_name: wordpress_db
restart: always
command:
# 使用原生密码认证旧版 WP 兼容性
# 用原生密码认证MySQL 8.4 默认禁用旧版 WP 兼容性需要
- --default-authentication-plugin=mysql_native_password
- --mysql-native-password=ON
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
environment:
+2 -2
View File
@@ -2,9 +2,9 @@
services:
db:
image: mysql:8.0
image: mysql:8.4
command:
- --default_authentication_plugin=mysql_native_password
- --mysql-native-password=ON
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
+1 -1
View File
@@ -41,7 +41,7 @@ flowchart TD
每个 Dockerfile 指令创建一层只有变化的层需要重建
```docker
FROM node:20 # 层1基础镜像
FROM node:22 # 层1基础镜像
COPY package.json ./ # 层2依赖定义
RUN npm install # 层3安装依赖
COPY . . # 层4应用代码
+2 -2
View File
@@ -166,7 +166,7 @@ spec:
spec:
containers:
- name: nginx
image: nginx:1.28
image: nginx:1.30
ports:
- containerPort: 80
```
@@ -200,7 +200,7 @@ spec:
spec:
containers:
- name: mysql
image: mysql:8.0
image: mysql:8.4
volumeMounts:
- name: data
mountPath: /var/lib/mysql
+2 -2
View File
@@ -31,7 +31,7 @@ spec:
spec:
containers:
- name: nginx
image: nginx:1.28
image: nginx:1.30
ports:
- containerPort: 80
```
@@ -73,7 +73,7 @@ kubectl get svc nginx-service
### 13.5.4 步骤 3模拟滚动更新
修改 `nginx-deployment.yaml`将镜像版本改为 `nginx:1.28-alpine`
修改 `nginx-deployment.yaml`将镜像版本改为 `nginx:1.30-alpine`
```bash
kubectl apply -f nginx-deployment.yaml
+4 -2
View File
@@ -138,12 +138,14 @@ $ sysctl --system
为了让 kubelet 正确运行我们需要对其进行一些必要的配置
#### 修改 `kubelet.service`
#### 修改 `kubelet.service`可选IPVS 模式
> **注意**kube-proxy IPVS 模式已在 Kubernetes 1.35 中被标记为弃用并计划在后续版本中移除新部署建议使用默认的 iptables 模式或 nftables 模式Kubernetes 1.31+ 可用以下 IPVS 配置仅供需要兼容旧环境的场景参考
`/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容
```bash
# 启用 ipvs 相关内核模块
# 启用 ipvs 相关内核模块已弃用建议迁移至 nftables
[Service]
ExecStartPre=-/sbin/modprobe ip_vs
+4 -2
View File
@@ -169,12 +169,14 @@ $ sysctl --system
为了让 kubelet 正确运行我们需要对其进行一些必要的配置
#### 修改 `kubelet.service`
#### 修改 `kubelet.service`可选IPVS 模式
> **注意**kube-proxy IPVS 模式已在 Kubernetes 1.35 中被标记为弃用并计划在后续版本中移除新部署建议使用默认的 iptables 模式或 nftables 模式Kubernetes 1.31+ 可用以下 IPVS 配置仅供需要兼容旧环境的场景参考
`/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容
```bash
# 启用 ipvs 相关内核模块
# 启用 ipvs 相关内核模块已弃用建议迁移至 nftables
[Service]
ExecStartPre=-/sbin/modprobe ip_vs
+2 -2
View File
@@ -193,10 +193,10 @@ $ kubectl label pods -l app=nginx version=v1
```bash
# 添加注解
$ kubectl annotate pod my-pod description=Production pod
$ kubectl annotate pod my-pod description="Production pod"
# 修改注解
$ kubectl annotate pod my-pod description=Staging pod --overwrite
$ kubectl annotate pod my-pod description="Staging pod" --overwrite
# 删除注解
$ kubectl annotate pod my-pod description-
+1 -1
View File
@@ -4,7 +4,7 @@
`etcd` 基于 `Go` 语言实现因此用户可以从[项目主页](https://github.com/etcd-io/etcd)下载源代码自行编译,也可以下载编译好的二进制文件,甚至直接使用制作好的 `Docker` 镜像文件来体验。
> 注意etcd 官方仅维护最新两个次版本当前为 3.5 3.6本章示例基于 etcd `3.5.x` 版本编写etcd 3.6.x 可用于新部署请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本。
> 注意etcd 官方仅维护最新两个次版本当前为 3.5 3.6etcd 3.4 已于 2026 5 月结束支持EOL仍在使用 3.4 的用户应尽快升级本章示例基于 etcd `3.5.x` 版本编写etcd 3.6.x 可用于新部署请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本。
### 15.2.1 二进制文件方式下载
+4 -2
View File
@@ -111,9 +111,11 @@ hello
```
支持的选项为
`--sort` 对结果进行排序
`--sort-by` 指定排序字段CREATE / KEY / MODIFY / VALUE / VERSION
`--consistent` 将请求发给主节点保证获取内容的一致性
`--order` 指定排序顺序ASCEND / DESCEND
`--consistency` 指定一致性级别`l` 线性一致`s` 串行
#### del
+3 -3
View File
@@ -2,7 +2,7 @@ version: "3.6"
services:
node1:
image: quay.io/coreos/etcd:v3.5.17
image: quay.io/coreos/etcd:v3.5.29
volumes:
- node1-data:/etcd-data
expose:
@@ -34,7 +34,7 @@ services:
- docker-etcd
node2:
image: quay.io/coreos/etcd:v3.5.17
image: quay.io/coreos/etcd:v3.5.29
volumes:
- node2-data:/etcd-data
networks:
@@ -66,7 +66,7 @@ services:
- docker-etcd
node3:
image: quay.io/coreos/etcd:v3.5.17
image: quay.io/coreos/etcd:v3.5.29
volumes:
- node3-data:/etcd-data
networks:
+1 -1
View File
@@ -8,7 +8,7 @@
Skopeo 是一个由 Red Hat 赞助开源的命令行工具它可以在不需要运行容器守护进程 Docker Daemon的前提下对容器镜像进行极其高效的操作和管理包括检查复制删除和签名等操作
Skopeo 最大的特点是其可以在不将镜像拉取到本地的情况下直接在远端 Registry镜像仓库之间完成检查和搬运从而大幅度节省带宽和磁盘空间这也是它在容器运维和分发领域非常受欢迎的原因
Skopeo 最大的特点是其可以在不将镜像拉取到本地的情况下直接在远端 Registry镜像仓库之间完成检查和搬运从而大幅度节省带宽和磁盘空间这也是它在容器运维和分发领域非常受欢迎的原因
### 17.5.2 核心特性
+1 -1
View File
@@ -40,7 +40,7 @@
Kubernetes 作为一个容器编排系统为了屏蔽底层不同容器运行时的实现差异引入了 CRIContainer Runtime Interface标准
- 早期版本中Kubernetes 默认使用 docker 作为运行时通过一个名为 `dockershim` 的桥接组件对接 DockerDocker 再对接 containerd
- 随着 containerd 原生支持了 CRI 插件Kubernetes 开始直接与 containerd 通信去掉了 `dockershim` `dockerd` 的中间层这就是为什么从 Kubernetes 1.24+ 开始弃用 Docker引发了广泛关注实际上 Kubernetes 只是弃用 `dockershim`底层依然在使用从 Docker 基因中诞生的 containerd参见 [Kubernetes 官方文档](https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd)。
- 随着 containerd 原生支持了 CRI 插件Kubernetes 开始直接与 containerd 通信去掉了 `dockershim` `dockerd` 的中间层这就是为什么从 Kubernetes 1.24+ 开始弃用 Docker引发了广泛关注实际上 Kubernetes 只是弃用 `dockershim`底层依然在使用从 Docker 基因中诞生的 containerd参见 [Kubernetes 官方文档](https://kubernetes.io/docs/setup/production-environment/container-runtimes/#containerd)。
- containerd 2.0+ 移除了已弃用的 CRI v1alpha2 接口仅保留 CRI v1Kubernetes 1.26+ 仅支持 CRI v1如果集群中仍有依赖 CRI v1alpha2 的组件升级 containerd 2.x 前需先完成迁移containerd 2.3+ 2.x 系列首个 LTS 版本支持从 1.7 LTS 直接升级生产环境推荐使用详见 [containerd 发布说明](https://github.com/containerd/containerd/releases)。
### 17.6.3 为什么直接使用 containerd
+1 -1
View File
@@ -10,7 +10,7 @@
尽管这种方式在性能和启动速度上拥有巨大优势但也带来了一个显著的缺点**隔离性Isolation不足**如果某个容器内的恶意进程利用了宿主机内核的漏洞完成了越狱Privilege Escalation它将对整个宿主机以及其上运行的所有其他容器造成毁灭性威胁
如果在公有云环境多租户场景或运行不可信的第三方代码时共享内核显然是不够安全的为了解决这一问题社区推出了安全容器Secure Containers/Sandboxed Containers的概念安全容器的核心理念是提供类似虚拟机的强隔离性同时保持类似容器的轻量快速启动和标准化管理
如果在公有云环境多租户场景或运行不可信的第三方代码时共享内核显然是不够安全的为了解决这一问题社区推出了安全容器Secure Containers/Sandboxed Containers的概念安全容器的核心理念是提供类似虚拟机的强隔离性同时保持类似容器的轻量快速启动和标准化管理
### 17.7.2 什么是 Kata Containers
+1 -1
View File
@@ -14,7 +14,7 @@ Docker 守护进程在启动容器时,会在后台为容器创建一套独立
尽管命名空间提供了很好的隔离性但我们必须认识到**所有的容器依然共享同一个宿主机的 Linux 内核**
这意味着一旦宿主机的内核存在提权漏洞如著名的 Dirty COW 漏洞攻击者有可能通过突破 Namespace 的限制直接在内核层面执行恶意代码从而实现容器逃逸
这意味着一旦宿主机的内核存在提权漏洞如著名的 Dirty COW 漏洞攻击者有可能通过突破 Namespace 的限制直接在内核层面执行恶意代码从而实现容器逃逸
> [!WARNING]
> 为了缓解内核漏洞带来的威胁生产环境务必保持宿主机 Linux 内核的及时修补与更新或者借助诸如 gVisorKata Containers 等提供了独立内核的安全容器技术同时需要及时修补容器运行时 runC的漏洞2025 11 月披露的一系列 runC 容器逃逸漏洞CVE-2025-31133CVE-2025-52565CVE-2025-52881就表明即使内核保持更新运行时层的缺陷仍然可能导致容器隔离被突破
+2 -2
View File
@@ -434,8 +434,8 @@ jobs:
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Run Trivy vulnerability scan
# 安全提醒2026 3 Trivy GitHub Actions 遭受供应链攻击
# 75 个版本标签被劫持务必使用不可变的 commit SHA 引用而非可变标签
# 安全提醒2026 3 19 Trivy GitHub Actions 遭受供应链攻击
# 76 个版本标签被劫持务必使用不可变的 commit SHA 引用而非可变标签
# 使用前请到 https://github.com/aquasecurity/trivy-action/releases 核实 SHA 对应正确版本。
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
with:
+1 -1
View File
@@ -9,7 +9,7 @@
- **容器监控** Prometheus 为主讲解如何采集和展示容器性能指标
- **日志管理** ELK (Elasticsearch, Logstash, Kibana) 套件为例介绍集中式日志收集平台
为了让读者能够在生产环境中真正用起来本章会补齐以下最小闭环
为了让读者能够在生产环境中真正用起来本章会补齐以下最小闭环
* 关键指标与日志的验证方法
* 常见故障排查路径
+1 -1
View File
@@ -5,7 +5,7 @@
* **指标监控** Prometheus + Grafana 为主完成指标采集存储与可视化
* **日志管理** EFK/ELK 为例完成容器日志的集中采集检索与分析
生产环境中建议将可观测性当成一个完整闭环**采集 -> 存储 -> 展示 -> 告警 -> 排错 -> 容量治理**
生产环境中建议将可观测性当成一个完整闭环**采集 -> 存储 -> 展示 -> 告警 -> 排错 -> 容量治理**
## 扩展阅读Docker 日志驱动
+1 -1
View File
@@ -12,7 +12,7 @@
## DevOps 背景介绍
DevOps 是一种重要的开发和运维文化强调开发团队和运维团队之间的协作和自动化它致力于通过自动化和流程优化加快软件交付速度同时提高系统的稳定性和可靠性Docker 作为容器化技术的领导者已成为现代 DevOps 工作流中不可或缺的工具通过容器化应用开发团队可以确保一次构建处处运行消除开发测试和生产环境的差异大大简化了部署流程
DevOps 是一种重要的开发和运维文化强调开发团队和运维团队之间的协作和自动化它致力于通过自动化和流程优化加快软件交付速度同时提高系统的稳定性和可靠性Docker 作为容器化技术的领导者已成为现代 DevOps 工作流中不可或缺的工具通过容器化应用开发团队可以确保一次构建处处运行消除开发测试和生产环境的差异大大简化了部署流程
## Docker DevOps 中的角色
+2 -2
View File
@@ -11,7 +11,7 @@
在项目中创建一个 Dockerfile
```docker
FROM node:20
FROM node:22
## replace this with your application's default port
@@ -32,7 +32,7 @@ $ docker run -it --rm \
--mount type=bind,src="$(pwd)",target=/usr/src/myapp \
-w /usr/src/myapp \
node:20-alpine \
node:22-alpine \
node your-daemon-or-script.js
```