Compare commits

..
64 Commits
Author SHA1 Message Date
yeasy 32f5c53d76 Refresh image CLI docs 2026-04-27 09:15:19 -07:00
yeasy 109112d146 Fix mongosh, DCA price, compose healthcheck and cleanup 2026-04-27 14:17:57 +00:00
yeasy 233b0ca96f Update Docker image tags and etcd commands 2026-04-27 11:18:08 +00:00
yeasy 11369ba10a Fix Docker Hub rate limits and etcdctl API version 2026-04-27 05:13:02 +00:00
yeasy 0dadce28d9 Fix Docker Hub rate limits, DCT timeline, image tags, etcd and Alertmanager 2026-04-27 01:15:52 +00:00
yeasy 9de6b523c4 Update Gateway API docs and image security practices 2026-04-26 00:18:39 +00:00
yeasy abd4f6e5cd Add nftables support and Time namespace documentation 2026-04-26 00:18:39 +00:00
yeasy 8f13ff9dfa 更新 Namespace/Gateway API/nftables/DCT 退役时间线
- ch12: 添加 TIME namespace (Linux 5.6+),内核 namespace 类型从 7 更新为 8
- ch12: 补充 Docker Engine v29.x 实���性 nftables 支持
- ch13: Ingress-NGINX 退役通知,添加 Gateway API 推荐方案和示例
- ch13: 添加 Pod Security Standards 章节(替代已移除的 PSP)
- ch18: 补充 DCT 退役时间线(2028-03-31 完全移除)和迁移建议
2026-04-26 00:12:59 +00:00
yeasy 89a66c645a Update Prometheus to v3.11.2, fix etcdctl version 2026-04-25 22:39:33 +00:00
yeasy 89bbbe94a5 Fix network IPs, compose healthcheck, update GH Actions versions 2026-04-25 21:11:50 +00:00
yeasy 2917ec2f27 Add official doc links to install guides 2026-04-25 21:11:50 +00:00
yeasy 423b6c7060 Add version notes and image tag best practices 2026-04-25 21:11:50 +00:00
yeasy 0aba9e50a9 Update docker0 default subnet to 172.17.0.0/16 2026-04-25 21:03:39 +00:00
yeasy 109733421f Document depends_on condition and healthcheck 2026-04-25 21:03:39 +00:00
yeasy e641ff3c90 Accurate cgroup v2 description, update Actions versions 2026-04-25 20:42:35 +00:00
yeasy 8440b48566 Fix broken code block in laravel multistage Dockerfile 2026-04-25 20:42:18 +00:00
yeasy 12070a093d Add version notes and official doc links 2026-04-25 15:58:42 +00:00
Baohua Yang b16aa3976e chore: lint cleanup and version corrections
- Accept benign linter changes (version notes, explicit tags, formatting)
- Fix incorrect version downgrades introduced by linter:
  - golang:1.22→1.26 (restored)
  - rust:1.82→1.95 (restored)
- 23 files updated
2026-04-25 15:58:27 +00:00
yeasy 396cdf0744 Update Grafana to v13, add version notes 2026-04-25 15:50:13 +00:00
yeasy e3861040ec Add blank lines before lists per CommonMark 2026-04-25 15:13:27 +00:00
yeasy f4fa272dc5 Update Kubernetes to v1.36, build-push-action to v7 2026-04-25 15:10:51 +00:00
yeasy 57b203832f Update versions and fix formatting issues 2026-04-25 15:10:43 +00:00
yeasy b0408f633b Add Docker Scout, remove deprecated type_name 2026-04-25 15:02:24 +00:00
yeasy 73f29570d4 Update etcd to v3.5.29 2026-04-25 15:00:47 +00:00
yeasy 73d230f3b7 Update node-exporter to v1.11.1, fcct to butane 2026-04-25 14:58:40 +00:00
yeasy 7d2ab6cd28 Add blank lines before lists per CommonMark 2026-04-25 14:57:09 +00:00
yeasy a101822a00 Update containerd config path for 2.x 2026-04-25 14:22:55 +00:00
yeasy dacb3d9c7e Update content and fix issues 2026-04-25 02:14:58 +00:00
yeasy b34cb3c9ba Clarify image build semantics 2026-04-24 10:51:49 -07:00
yeasy b628da8dba Fix straight quotes to curly quotes in mirror doc 2026-04-24 13:24:52 +00:00
yeasy 1ee3a4f97f Fix Ubuntu codenames and containerd LTS description 2026-04-24 03:16:05 +00:00
yeasy 67695cd45b Fix apt cache cleanup path in Dockerfile example 2026-04-23 13:16:21 -07:00
yeasy e6459efb63 Pin Prometheus and Grafana image versions 2026-04-22 12:24:31 -07:00
yeasy 2d7740ffb5 Add runC CVEs and AuthZ plugin guidance 2026-04-22 12:24:31 -07:00
yeasy 771d75ac03 Add section numbers to ecosystem headings 2026-04-22 12:24:30 -07:00
yeasy 9c47ee5dd4 Update nginx version and K8s dashboard date 2026-04-22 12:24:30 -07:00
yeasy 2392090f8b Fix Debian dates and FAQ template syntax 2026-04-22 08:43:48 -07:00
yeasy 1836416263 Refresh install guidance
# Conflicts:
#	03_install/3.1_ubuntu.md
#	03_install/3.2_debian.md
#	03_install/3.3_fedora.md
#	03_install/3.9_mirror.md
2026-04-22 08:24:38 -07:00
yeasy 7cb55a0dd6 Refresh k8s docker versions and references 2026-04-21 20:57:33 -07:00
yeasy d57fb34102 Refine Docker concepts 2026-04-21 14:39:41 -07:00
yeasy 258ef59727 Add new content and update versions 2026-04-19 22:35:33 -07:00
yeasy 14851771a8 Drop legacy plugins 2026-04-19 20:14:36 -07:00
yeasy 787c2adf57 Clarify intro chapter 2026-04-18 20:25:29 -07:00
yeasy 029da9f946 Update software versions and fix security refs 2026-04-18 19:04:14 -07:00
yeasy b0d4b23744 Fix mermaid syntax and update K8s taint labels 2026-04-18 15:17:56 -07:00
yeasy 6a876694a9 Update Kind v0.31.0 and Flannel v0.28.2 2026-04-18 13:31:43 -07:00
yeasy 69d46f78d5 Restructure README with badges and cover 2026-04-17 21:51:38 -07:00
yeasy 969f371091 Add Ubuntu 20.04 EOL exact date 2026-04-17 21:19:32 -07:00
yeasy dd4e7c91e8 Update versions and fix stale data 2026-04-17 21:17:12 -07:00
github-actions[bot]andGitHub 456918e31f Merge pull request #564 from yeasy/dependabot/github_actions/dependencies-8fe05ed821
chore(deps): bump the dependencies group with 2 updates
2026-04-15 18:46:57 +00:00
dependabot[bot]andGitHub 5c225e6c58 chore(deps): bump the dependencies group with 2 updates
Bumps the dependencies group with 2 updates: [softprops/action-gh-release](https://github.com/softprops/action-gh-release) and [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata).


Updates `softprops/action-gh-release` from 2 to 3
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v2...v3)

Updates `dependabot/fetch-metadata` from 2 to 3
- [Release notes](https://github.com/dependabot/fetch-metadata/releases)
- [Commits](https://github.com/dependabot/fetch-metadata/compare/v2...v3)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
- dependency-name: dependabot/fetch-metadata
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-15 18:46:44 +00:00
yeasy ecd1e696eb Fix Chinese curly quotes in prose text 2026-04-14 20:29:35 -07:00
yeasy 78ae7ad641 Fix figure caption punctuation and table formatting 2026-04-13 18:37:00 -07:00
yeasy e9f315147c Fix figure caption format 2026-04-09 09:02:44 -07:00
yeasy dd0368e926 Add section numbering and archive notice 2026-04-08 22:40:15 -07:00
yeasy 80772a1e97 Fix bash comment style to single hash 2026-04-08 22:39:51 -07:00
yeasy 6eecb5118d Fix mdpress port 4000 to 9000 2026-04-05 13:39:46 -07:00
yeasy ce466273be Fix typo in offline install image alt text 2026-04-05 12:59:09 -07:00
yeasy ec2897feab Remove time annotation in install docs 2026-04-05 12:58:42 -07:00
yeasy 0455c5e233 Remove duplicate release-pdf workflow 2026-04-05 08:55:52 -07:00
yeasy 28f49b6dc1 Add release-pdf CI workflow for automated PDF builds 2026-04-05 08:29:11 -07:00
yeasy d0e1a20411 Replace defunct AtomHub mirror with docker.1ms.run 2026-04-05 08:16:08 -07:00
yeasy fae0a7a092 ci: add auto-release.yml, remove release-pdf.yml, limit CI trigger to master 2026-04-05 07:57:56 -07:00
Baohua YangandClaude Opus 4.6 9074524eaa Add recommended reading paths table to README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 22:31:23 -07:00
79 changed files with 244 additions and 280 deletions
+1 -5
View File
@@ -16,13 +16,9 @@ jobs:
- uses: actions/checkout@v6
- name: Install Chromium and CJK fonts
uses: browser-actions/setup-chrome@v2
with:
chrome-version: stable
- name: Install CJK fonts
run: |
sudo apt-get update
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra
sudo apt-get install -y chromium-browser fonts-noto-cjk fonts-noto-cjk-extra
- name: Install mdpress (latest)
run: |
+1 -5
View File
@@ -17,13 +17,9 @@ jobs:
steps:
- uses: actions/checkout@v6
- name: Install Chromium and CJK fonts
uses: browser-actions/setup-chrome@v2
with:
chrome-version: stable
- name: Install CJK fonts
run: |
sudo apt-get update
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra
sudo apt-get install -y chromium-browser fonts-noto-cjk fonts-noto-cjk-extra
- name: Install mdpress (latest)
run: |
LATEST_TAG=$(curl -fsSL -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ github.token }}" https://api.github.com/repos/yeasy/mdpress/releases/latest | jq -r .tag_name)
+1 -5
View File
@@ -23,13 +23,9 @@ jobs:
- uses: actions/checkout@v6
- name: Install Chromium and CJK fonts
uses: browser-actions/setup-chrome@v2
with:
chrome-version: stable
- name: Install CJK fonts
run: |
sudo apt-get update
sudo apt-get install -y fonts-noto-cjk fonts-noto-cjk-extra
sudo apt-get install -y chromium-browser fonts-noto-cjk fonts-noto-cjk-extra
- name: Install mdpress (latest)
run: |
+1 -1
View File
@@ -172,7 +172,7 @@ registry.example.com/myproject/myapp:v1.2.3
## 简写(使用 Docker Hub
nginx:1.28
nginx:1.25
ubuntu:24.04
## 省略标签(默认使用 latest)
+10 -10
View File
@@ -1,6 +1,6 @@
## 2.3 仓库
> **版本说明**本节示例基于 Docker v29.x 和常见镜像版本编写示例中的版本号 `nginx:1.28``mysql:8.4``mysql:5.7` 为演示用途实际使用时请访问 [Docker Hub 官方页面](https://hub.docker.com) 或相应镜像的发布页确认最新可用版本和标签。
> **版本说明**本节示例基于 Docker v29.x 和常见镜像版本编写示例中的版本号 `nginx:1.25``mysql:8.0``mysql:5.7` 为演示用途实际使用时请访问 [Docker Hub 官方页面](https://hub.docker.com) 或相应镜像的发布页确认最新可用版本和标签。
Docker Registry 是镜像分发和管理的核心组件本节将介绍 Registry 的基本概念公共和私有服务的选择以及镜像的安全管理
@@ -25,8 +25,8 @@ flowchart TB
subgraph RepoNginx ["Repository(仓库): nginx"]
direction LR
N1(":latest (tag)")
N2(":1.28 (tag)")
N3(":1.26 (tag)")
N2(":1.25 (tag)")
N3(":1.24 (tag)")
N4(":alpine (tag)")
N5("...")
N1 ~~~ N2 ~~~ N3 ~~~ N4 ~~~ N5
@@ -50,7 +50,7 @@ flowchart TB
|------|------|------|
| **Registry** | 存储镜像的服务 | Docker Hubghcr.io |
| **Repository (仓库)** | 同一软件的镜像集合 | `nginx``mysql``mycompany/myapp` |
| **Tag (标签)** | 仓库内的版本标识 | `latest``1.28``alpine` |
| **Tag (标签)** | 仓库内的版本标识 | `latest``1.25``alpine` |
#### 镜像的完整名称
@@ -73,7 +73,7 @@ registry.example.com/mycompany/myapp:v1.2.3
## Docker Hub 官方镜像省略 registry 和用户名
nginx:1.28
nginx:1.25
ubuntu:24.04
## Docker Hub 用户镜像
@@ -131,7 +131,7 @@ Google 的 Container Registry 已废弃并完成下线,当前应优先使用 A
由于网络原因在国内直接访问 Docker Hub 可能会很慢可以配置 **镜像加速器** (Registry Mirror) 来加速下载配置示例如下
```jsonc
```json
// /etc/docker/daemon.json
{
"registry-mirrors": [
@@ -217,7 +217,7 @@ $ docker login registry.example.com # 登录其他 Registry
## 拉取镜像
$ docker pull nginx:1.28
$ docker pull nginx:1.25
## 标记镜像准备推送
@@ -261,9 +261,9 @@ someuser/myapp # ⚠️ 需要评估
```bash
## 准备一个你有写权限的镜像地址
$ export IMAGE=<你的仓库名>/nginx:1.28
$ docker pull nginx:1.28
$ docker tag nginx:1.28 $IMAGE
$ export IMAGE=<你的仓库名>/nginx:1.27
$ docker pull nginx:1.27
$ docker tag nginx:1.27 $IMAGE
$ docker push $IMAGE
## 生成签名密钥会生成 cosign.key / cosign.pub
+1 -1
View File
@@ -39,7 +39,7 @@ $ sudo dnf remove docker \
### 3.3.2 使用 dnf 安装
使用 dnf 包管理器安装是推荐的方式便于后续的更和管理
使用 dnf 包管理器安装是推荐的方式便于后续的更和管理
执行以下命令安装依赖包
+15 -15
View File
@@ -4,7 +4,7 @@
> **版本号最佳实践**
>
> - **永远指定版本号**避免使用 `latest` 标签应指定具体的版本 `ubuntu:24.04``nginx:1.28`以确保镜像内容稳定一致
> - **永远指定版本号**避免使用 `latest` 标签应指定具体的版本 `ubuntu:24.04``nginx:1.27`以确保镜像内容稳定一致
> - **在生产环境使用摘要**优先使用镜像摘要SHA256而非标签 `nginx@sha256:abc123...`因为摘要不可变
> - **定期评估依赖**即使指定了版本号仍应定期检查依赖的基础镜像是否有安全更新
@@ -13,24 +13,24 @@
从镜像仓库获取镜像的命令是 `docker pull`
```bash
docker pull [选项] [Registry地址/]仓库名[:标签]
docker pull [选项] [Registry地址/][命名空间/]仓库名[:标签|@摘要]
```
#### 镜像名称格式
Docker 镜像名称由 Registry 地址用户名仓库名和标签组成标准格式如下
Docker 镜像名称通常 Registry 地址命名空间仓库名和标签或摘要组成常见格式如下
```bash
docker.io / library / ubuntu : 24.04
Registry地址 用户名 仓库名 标签
(可省略) (可省略)
docker.io/library/ubuntu:24.04
Registry地址 命名空间 仓库名 标签
(可省略) (可省略)
```
| 组成部分 | 说明 | 默认值 |
|---------|------|--------|
| Registry 地址 | 镜像仓库地址 | `docker.io` (Docker Hub)|
| 用户名 | 镜像所属用户/组织 | `library` (官方镜像)|
| 命名空间 | 镜像所属用户/组织官方镜像常为 `library` | `library` (官方镜像)|
| 仓库名 | 镜像名称 | 必须指定 |
| 标签 | 版本标识 | `latest` |
@@ -89,19 +89,19 @@ docker.io/library/ubuntu:24.04
#### 分层下载
从输出可以看到镜像是 **分层下载**
从输出可以看到镜像是 **按层拉取**
```mermaid
flowchart TD
subgraph Image ["ubuntu:24.04 镜像"]
direction TB
L3["第3层 c8299583700a<br/>(已存在,跳过下载)"]
L2["第2层 be13a9d27eb8<br/>(下载中... 完成)"]
L1["第1层 92dc2a97ff99<br/>(下载中... 完成)"]
L3["第3层 c8299583700a<br/>(拉取完成)"]
L2["第2层 be13a9d27eb8<br/>(拉取完成)"]
L1["第1层 92dc2a97ff99<br/>(拉取完成)"]
L3 --- L2 --- L1
end
```
如果本地已有相同的层Docker 会跳过下载节省带宽和时间
如果本地已有相同的层Docker 通常会显示 `Already exists`本例中三层都显示 `Pull complete`表示此次拉取流程都完成了相应的层处理
---
@@ -160,7 +160,7 @@ root@e7009c6ce357:/# exit
Docker Hub 下载可能较慢可以配置镜像加速器
```jsonc
```json
// /etc/docker/daemon.json (Linux)
// ~/.docker/daemon.json (Docker Desktop)
{
+11 -11
View File
@@ -46,21 +46,21 @@ Docker 镜像的大小可能与我们通常理解的文件大小有所不同,
| 位置 | 显示大小 | 说明 |
|------|---------|------|
| Docker Hub | 29MB | 压缩后的网络传输大小 |
| docker image ls | 78MB | 本地解压后的实际大小 |
| Registry / Docker Hub 页面 | 常见为压缩后的分发大小或单平台视角 | 便于传输与分发 |
| `docker image ls` | 本地镜像及其父层累计占用大小 | 更接近主机上的实际展开占用 |
#### 实际磁盘占用
由于镜像是分层存储不同镜像可能共享相同
由于镜像是分层存储**只有基于相同父层构建** 的镜像才会共享相同层
```bash
ubuntu:24.04 nginx:latest redis:latest
共享基础
python:3.12-slim myapp:web myapp:worker
共享父层与依赖
```
因此`docker image ls` 中各镜像大小之和 > 实际磁盘占用
因此`docker image ls` 中各镜像大小之和通常会大于实际磁盘占用共享层只会在磁盘上保存一次
#### 查看实际空间占用
@@ -164,9 +164,9 @@ $ docker image prune
```bash
$ docker images -a
```
会显示很多无标签镜像这些是构建过程中产生的中间层被其他镜像依赖
会显示默认隐藏的中间层和虚悬镜像其中一部分可能来自构建过程并被其他镜像复用
> 不要删除中间层镜像它们是其他镜像的依赖删除会导致上层镜像无法使用删除顶层镜像时会自动清理不再需要的中间
> 一般不要手动逐个处理这些无标签项优先删除顶层镜像或使用 `docker image prune` 清理无用镜像 Docker 自行回收不再被引用的
---
+23 -8
View File
@@ -19,7 +19,7 @@ $ docker image rm [选项] <镜像1> [<镜像2> ...]
| 方式 | 说明 | 示例 |
|------|------|------|
| ** ID** | ID 的前几位 (通常 3-4 )| `docker rmi 501` |
| ** ID** | ID 的前几位只要足够唯一即可 | `docker rmi 501` |
| ** ID** | 完整的镜像 ID | `docker rmi 501ad78535f0...` |
| **镜像名:标签** | 仓库名和标签 | `docker rmi redis:7.0` |
| **镜像摘要** | 精确的内容摘要 | `docker rmi nginx@sha256:...` |
@@ -144,7 +144,7 @@ $ docker image prune -f
$ docker image prune -a
## 保留最近 24 小时
## 只清理 24 小时前的未使用镜像
$ docker image prune -a --filter "until=24h"
```
@@ -152,13 +152,17 @@ $ docker image prune -a --filter "until=24h"
#### 按条件删除
```bash
## 删除所有 redis 镜像
## 先列出所有 redis 相关镜像引用
$ docker rmi $(docker images -q redis)
$ docker image ls --filter reference='redis*'
## 删除 mongo:8.0 之前的所有镜像
## 确认后按仓库名:标签逐个删除需要的镜像
$ docker rmi $(docker images -q -f before=mongo:8.0)
$ docker image rm redis:7 redis:7-alpine
## 先列出所有比 mongo:8.0 更早创建的镜像
$ docker image ls --filter before=mongo:8.0
## 删除某个时间之前的镜像
@@ -217,14 +221,25 @@ Error: image has dependent child images
### 4.3.6 常用过滤条件
不同命令支持的过滤条件并不相同最常见的是 `docker image ls` 用来筛选查看对象`docker image prune` 用来清理未使用镜像
#### `docker image ls` 常用过滤条件
| 过滤条件 | 说明 | 示例 |
|---------|------|------|
| `dangling=true` | 虚悬镜像 | `-f dangling=true` |
| `before=镜像` | 在某镜像之前 | `-f before=mongo:3.2` |
| `since=镜像` | 在某镜像之后 | `-f since=mongo:3.2` |
| `before=镜像` | 仅匹配比某镜像更早创建的镜像 | `-f before=mongo:3.2` |
| `since=镜像` | 仅匹配比某镜像更晚创建的镜像 | `-f since=mongo:3.2` |
| `label=key=value` | 按标签过滤 | `-f label=version=1.0` |
| `reference=pattern` | 按名称模式 | `-f reference='*:latest'` |
#### `docker image prune` 常用过滤条件
| 过滤条件 | 说明 | 示例 |
|---------|------|------|
| `until=<时间>` | 仅清理某个时间点之前创建的未使用镜像 | `--filter "until=24h"` |
| `label=key=value` | 仅清理带指定标签的未使用镜像 | `--filter "label=stage=temp"` |
---
### 4.3.7 清理策略
+3 -3
View File
@@ -10,7 +10,7 @@
现在让我们以定制一个 Web 服务器为例子来讲解镜像是如何构建的
> **版本提示**以下示例中 `nginx` 镜像使用默认 `latest` 标签生产环境建议指定具体版本号 `nginx:1.28`以避免镜像更新带来的不兼容性
> **版本提示**以下示例中 `nginx` 镜像使用默认 `latest` 标签生产环境建议指定具体版本号 `nginx:1.27`以避免镜像更新带来的不兼容性
```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.30 05a60462f8ba 12 days ago 181.5 MB
nginx 1.27 05a60462f8ba 12 days ago 181.5 MB
nginx latest e43d811ce2f4 4 weeks ago 181.5 MB
```
> **版本说明**上面示例中 `nginx:1.30` 代表 1.30 系列的最新 patch 版本在实际应用中应根据需求选择确切的版本号而不是盲目使用 `latest`
> **版本说明**上面示例中 `nginx:1.27` 代表 1.27 系列的最新 patch 版本在实际应用中应根据需求选择确切的版本号而不是盲目使用 `latest`
我们还可以用 `docker history` 具体查看镜像内的历史记录例如先执行 `docker history nginx:v2`再对比 `docker history nginx:latest`就能看到我们刚刚提交出来的新层
+5 -5
View File
@@ -26,7 +26,7 @@ $ touch Dockerfile
```
其内容为
> **版本提示**下面示例中 `FROM nginx` 使用的是 `latest` 标签在实际应用中应使用明确的版本号 `FROM nginx:1.28`以确保 Dockerfile 的可重现性和稳定性
> **版本提示**下面示例中 `FROM nginx` 使用的是 `latest` 标签在实际应用中应使用明确的版本号 `FROM nginx:1.27`以确保 Dockerfile 的可重现性和稳定性
```docker
FROM nginx
@@ -86,7 +86,7 @@ RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
$ docker build -t nginx:v3 .
```
在当前版本的 Docker `docker build` 默认会通过 Buildx 调用 BuildKit因此你更常看到的是 `[+] Building ...` 这类输出为了帮助理解每一步如何形成镜像历史下面仍展示一种较容易阅读的经典输出形式
在当前版本的 Docker `docker build` 默认会通过 Buildx 调用 BuildKit但如果你显式设置了 `DOCKER_BUILDKIT=0`或正在使用 Windows container mode行为会回到 legacy builder因此你更常看到的是 `[+] Building ...` 这类输出为了帮助理解每一步如何形成镜像历史下面仍展示一种较容易阅读的 legacy builder 经典输出形式
```bash
Sending build context to Docker daemon 2.048 kB
@@ -98,7 +98,7 @@ Step 2 : RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
Removing intermediate container 9cdc27646c7b
Successfully built 44aa4490ce2c
```
从命令的输出结果中我们可以清晰的看到镜像的构建过程 `Step 2` 如同我们之前所说的那样`RUN` 指令启动了一个容器 `9cdc27646c7b`执行了所要求的命令并最后提交了这一层 `44aa4490ce2c`随后删除了所用到的这个容器 `9cdc27646c7b`
这段输出清晰展示了 legacy builder 的构建过程 `Step 2` `RUN` 指令对应一次临时构建容器执行命令生成新的镜像层再删除中间容器默认的 BuildKit 后端通常不会把这些中间容器和中间镜像以这种形式暴露给用户每条会改文件系统的指令都会生成新的层这一点并没有改变
这里我们使用了 `docker build` 命令进行镜像构建其格式为
@@ -111,7 +111,7 @@ docker build [选项] <上下文路径/URL/->
如果注意会看到 `docker build` 命令最后有一个 `.``.` 表示当前目录 `Dockerfile` 就在当前目录因此不少初学者以为这个路径是在指定 `Dockerfile` 所在路径这么理解其实是不准确的如果对应上面的命令格式你可能会发现这是在指定 **上下文路径**那么什么是上下文呢
首先要理解 `docker build` 的工作原理今天的 `docker build` 默认会通过 Buildx BuildKit 后端发起构建请求无论后端运行在本机还是远端位置参数指定的都是 **构建上下文**也就是构建器可以访问到的文件集合
首先要理解 `docker build` 的工作原理今天的 `docker build` 通常会通过 Buildx BuildKit 后端发起构建请求无论后端运行在本机还是远端位置参数指定的都是 **构建上下文**也就是构建器可以访问到的文件集合
当我们进行镜像构建的时候并非所有定制都会通过 `RUN` 指令完成经常还需要把本地文件复制进镜像比如通过 `COPY` 指令`ADD` 指令等因此构建器必须能够访问这些文件而它能访问的范围正是你传给 `docker build` 的那个上下文
@@ -124,7 +124,7 @@ COPY ./package.json /app/
```
这并不是要复制执行 `docker build` 命令所在的目录下的 `package.json`也不是复制 `Dockerfile` 所在目录下的 `package.json`而是复制 **上下文 (context)** 目录下的 `package.json`
因此`COPY` 这类指令中的源文件路径都应该以构建上下文为基准来理解对于 legacy builder `COPY ../package.json /app` 这样的写法会直接报错而在 BuildKit 前导的越界 `../` 会被剥离并重新解释为上下文内路径无论是哪种情况构建器都无法读取上下文之外的宿主机文件如果真的需要那些文件应该先把它们放进上下文目录或重新选择合适的上下文
因此`COPY` 这类指令中的源文件路径都应该以构建上下文为基准来理解 `COPY ../package.json /app` 这样的写法前导的越界 `../` 会被规范化掉最终仍只能在上下文根内解析换句话说构建器并不能借此读取上下文之外的宿主机文件如果真的需要那些文件应该先把它们放进上下文目录或重新选择合适的上下文
现在就可以理解刚才的命令 `docker build -t nginx:v3 .` 中的这个 `.`实际上是在指定上下文目录而不是单纯指定 `Dockerfile` 所在目录
+22 -20
View File
@@ -6,44 +6,44 @@
格式`docker import [选项] <文件>|<URL>|- [<仓库名>[:<标签>]]`
压缩包可以是本地文件远程 Web 文件甚至是从标准输入中得到压缩包将会在镜像 `/` 目录展开并直接作为镜像第一层提交
压缩包可以是本地文件远程 Web 文件甚至是从标准输入中得到压缩包将会在镜像 `/` 目录展开并直接作为镜像的文件系统内容导入若还需要补充 `CMD``ENV` 等元数据可以通过 `--change` 追加但它不支持 `RUN``COPY` 这类依赖构建上下文或会生成新文件系统层的 Dockerfile 指令
比如我们想要创建一个 [OpenVZ](https://openvz.org) 的 Ubuntu 16.04 [模板](https://wiki.openvz.org/Download/template/precreated)的镜像:
例如在 Debian/Ubuntu 主机上可以先用 `debootstrap` 生成 Ubuntu 24.04`noble` rootfs再通过标准输入导入为基础镜像
> **版本提示**示例中的 Ubuntu 16.04 (Xenial) 已于 2021 4 月停止支持如果用于生产环境建议更新至 Ubuntu 22.04 LTS 或更新版本
```bash
$ docker import \
http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz \
openvz/ubuntu:16.04
$ sudo debootstrap noble noble > /dev/null
$ sudo tar -C noble -c . | docker import - ubuntu:noble
Downloading from http://download.openvz.org/template/precreated/ubuntu-16.04-x86_64.tar.gz
sha256:412b8fc3e3f786dca0197834a698932b9c51b69bd8cf49e100c35d38c9879213
sha256:81ec9a55a92a5618161f68ae691d092bf14d700129093158297b3d01593f4ee3
```
命令自动下载了 `ubuntu-16.04-x86_64.tar.gz` 文件并且作为根文件系统展开导入并保存为镜像 `openvz/ubuntu:16.04`
命令会先得到 `noble/` 目录下的 rootfs再把它打包后导入成镜像 `ubuntu:noble`这种方式更适合制作自定义基础镜像或把现成的根文件系统快速封装成镜像
导入成功后我们可以用 `docker image ls` 看到这个导入的镜像
```bash
$ docker image ls openvz/ubuntu
$ docker image ls ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
openvz/ubuntu 16.04 412b8fc3e3f7 55 seconds ago 505MB
ubuntu noble 81ec9a55a92a 5 seconds ago 78MB
```
如果我们查看其历史的话会看到描述中有导入的文件链接
如果需要在导入时补上镜像元数据可以配合 `--change` 选项
```bash
$ 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
$ docker import \
--change 'CMD ["/bin/bash"]' \
--change 'ENV LANG=C.UTF-8' \
rootfs.tar \
custom/base:noble
```
### 4.6.2 Docker 镜像的导入和导出 `docker save` `docker load`
Docker 还提供了 `docker save` `docker load` 命令用以将镜像保存为一个文件然后传输到另一个位置上再加载进来这是在没有 Docker Registry 时的做法现在已经不推荐镜像迁移应该直接使用 Docker Registry无论是直接使用 Docker Hub 还是使用内网私有 Registry 都可以
Docker 还提供了 `docker save` `docker load` 命令用以将镜像保存为一个归档文件然后传输到另一个位置上再加载进来它们仍然适合离线备份气隙环境分发或在两台主机之间手工迁移镜像如果是团队常规分发版本管理和协作优先使用 Docker Registry无论是 Docker Hub 还是内网私有 Registry会更合适
#### 保存镜像
使用 `docker save` 命令可以将镜像保存为归档文件
使用 `docker save` 命令可以将镜像保存为归档文件归档中会包含镜像的父层以及所指定的标签如果本地镜像仓库里已有多个平台变体还可以通过 `--platform` 仅导出某个平台版本
比如我们希望保存这个 `alpine` 镜像
@@ -57,7 +57,7 @@ alpine latest baa5d63471ea 5 weeks ago
保存镜像的命令为
```bash
$ docker save alpine -o filename
$ docker image save -o filename alpine
$ file filename
filename: POSIX tar archive
```
@@ -68,14 +68,16 @@ filename: POSIX tar archive
若使用 `gzip` 压缩
```bash
$ docker save alpine | gzip > alpine-latest.tar.gz
$ docker image save alpine | gzip > alpine-latest.tar.gz
```
然后我们将 `alpine-latest.tar.gz` 文件复制到了到了另一个机器上可以用下面这个命令加载镜像
然后我们将 `alpine-latest.tar.gz` 文件复制到了另一个机器上可以用下面这个命令加载镜像
```bash
$ docker load -i alpine-latest.tar.gz
$ docker image load -i alpine-latest.tar.gz
Loaded image: alpine:latest
```
`docker load` 会恢复归档中的镜像和标签同样地在需要时也可以通过 `--platform` 只加载其中一个平台变体
如果我们结合这两个命令以及 `ssh` 甚至 `pv` 的话利用 Linux 强大的管道我们可以写一个命令完成从一个机器将镜像迁移到另一个机器并且带进度条的功能
```bash
+5 -5
View File
@@ -40,8 +40,8 @@ flowchart TD
```
* **读取文件**当容器需要读取文件时Docker 会从最上层 (容器层) 开始向下层 (镜像层) 寻找直到找到该文件为止
* **修改文件**当容器需要修改某个文件时Docker 会从下层镜像中将该文件复制到上层的容器层然后对副本进行修改这被称为 **写时复制 (Copy-on-WriteCoW)** 策略
* **删除文件**当容器删除某个文件时Docker 并不是真的去下层删除它 (因为下层是只读的)而是在容器层创建一个特殊的 白障 (Whiteout) 文件用来标记该文件已被删除从而在容器视图中隐藏它
* **修改文件**当容器需要修改某个文件时底层存储后端会以 **写时复制 (Copy-on-WriteCoW)** 的方式记录变化 `overlay2` 这类联合文件系统后端上常见表现是先把文件 `copy_up` 到容器层再修改 `btrfs``zfs` CoW 文件系统的内部实现会有所不同
* **删除文件**当容器删除某个文件时Docker 不会直接改写下层只读层而是由当前存储后端在上层记录把下层内容屏蔽掉的元数据 `overlay2` 这常表现为 whiteout opaque directory其他后端会用各自的机制达到相同效果
这就是为什么
@@ -58,10 +58,10 @@ Docker 镜像的每一层都有一个唯一的 ID,这个 ID 是根据该层的
### 4.7.4 联合文件系统
Docker 使用联合文件系统 (Union FS) 与写时复制思路来实现这种分层挂载传统的实现方式常见于 `overlay2``aufs``btrfs``zfs` 等存储驱动而在 Docker Engine 29.0 及之后的全新安装中默认镜像后端已经变为 containerd image store它使用 snapshotter 来管理这些层
Docker 分层 + CoW的思路来实现镜像与容器层叠加但具体后端并不完全相同`overlay2``aufs` 这类后端属于联合文件系统`btrfs``zfs` 更接近具备快照/克隆能力的 CoW 文件系统而在 Docker Engine 29.0 及之后的全新安装中默认镜像后端已经变为 containerd image store它使用 snapshotter 来管理这些层
> **版本背景**Docker Engine 29.0发布于 2025 11 是一个重要版本分界点在全新安装场景下默认启用 containerd image store 作为镜像存储后端这对镜像管理OCI 合规性和供应链安全都有深远影响如果你的 Docker 版本低于 29.0镜像存储仍使用传统的 classic store 路径
> **版本背景**Docker Engine 29.0发布于 2024 2 是一个重要版本分界点引入了 containerd image store 作为默认镜像存储后端这对镜像管理OCI 合规性和供应链安全都有深远影响如果你的 Docker 版本低于 29.0镜像存储仍使用传统的 classic store 路径
虽然底层实现细节不同但它们都遵循上述的 **分层 + CoW** 模型因此无论你看到的是 `overlay2` 还是 containerd snapshotter理解镜像层容器层和写时复制的方式都是一样重要的
虽然底层实现细节不同但它们都遵循下层只读上层记录差异的总体模型因此无论你看到的是 `overlay2``zfs` 还是 containerd snapshotter理解镜像层容器层和写时复制的核心思想都是一样重要的
> 想要深入了解 Overlay2 等文件系统的具体实现原理包括 WorkDirUpperDirLowerDir 等底层细节请阅读 **[第十二章 底层实现](../12_implementation/README.md)** 中的 **[联合文件系统](../12_implementation/12.4_ufs.md)** 章节
+4 -4
View File
@@ -126,14 +126,14 @@ $ docker run -d -p 80:80 nginx:latest
## 数据库
$ docker run -d -p 3306:3306 mysql:8.4
$ docker run -d -p 3306:3306 mysql:8.0
## 缓存服务
$ docker run -d -p 6379:6379 redis:latest
```
> **版本说明**示例使用常见的标签如 `latest` 或稳定大版本号如 `mysql:8.4`具体版本可根据需求调整生产环境建议明确指定版本号 `mysql:8.4.4`而非使用 `latest`
> **版本说明**示例使用常见的标签如 `latest` 或稳定大版本号如 `mysql:8.0`具体版本可根据需求调整生产环境建议明确指定版本号 `mysql:8.0.35`而非使用 `latest`
#### 2. 调试时先用前台模式
@@ -196,9 +196,9 @@ $ docker logs -t myapp
3. **以交互模式调试**
```bash
# /bin/sh 覆盖镜像原本的启动命令避免容器再次崩溃退出
# 进入 shell 后可手动执行原启动命令定位具体报错原因
$ docker run -it myimage:v1.0.0 /bin/sh
# 进入容器手动执行命令查找问题
```
#### Q容器在后台运行但无法访问服务
+1 -1
View File
@@ -212,7 +212,7 @@ FROM node:22-alpine
CMD ["node", "server.js"]
```
> **版本说明**示例使用 `node:22-alpine`这是一个精简的 Node.js 22 版本镜像可根据需求替换为其他版本 `node:24-alpine``node:latest`
> **版本说明**示例使用 `node:22-alpine`这是一个精简的 Node.js 22 版本镜像可根据需求替换为其他版本 `node:20-alpine``node:latest`
#### Q容器无法停止
+1 -2
View File
@@ -249,11 +249,10 @@ $ docker exec myapp python manage.py migrate
$ docker exec -it myapp bash
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found
## 解决方案使用调试容器需要 Docker Desktop Pro/Team/Business 订阅
## 解决方案使用调试容器
$ docker debug myapp
```
> **注意**`docker debug` Docker Desktop 4.33+ 提供的功能需要 ProTeam Business 订阅它会附加一个包含常用调试工具vimcurlhtop 的工具箱到目标容器即使目标镜像基于 `scratch` 也能使用
---
### 5.4.7 常见问题
+3 -3
View File
@@ -10,11 +10,11 @@
本章示例涉及多个 Docker 镜像遵循以下版本号最佳实践
- **官方镜像** `ubuntu``nginx``mysql`使用具体大版本号 `ubuntu:24.04``mysql:8.4`而非 `latest`确保示例的可重复性
- **官方镜像** `ubuntu``nginx``mysql`使用具体大版本号 `ubuntu:24.04``mysql:8.0`而非 `latest`确保示例的可重复性
- **镜像标签约定**
- `latest` `v1.0.0` 带标签的自定义镜像示例中指定具体版本
- `24.04``8.4`官方镜像的稳定版本分支
- 生产环境建议指定确版本号 `nginx:1.28.0``mysql:8.4.4`而非仅大版本号
- `24.04``8.0`官方镜像的稳定版本分支
- 生产环境建议指定确版本号 `nginx:1.24.0``mysql:8.0.35`而非仅大版本号
* [启动容器](5.1_run.md)
* [守护态运行](5.2_daemon.md)
+1 -1
View File
@@ -75,7 +75,7 @@ Docker Hub 对不同类型用户实施拉取速率限制(基于 6 小时周期
| **免费账户** (已登录) | 6 小时 200 次请求 |
| **Pro/Team/Business 账户** | 无限制公平使用政策 |
> **注意**Docker 曾计划于 2025 4 调整拉取限制策略但在 2025 2 月宣布取消该计划目前付费订阅用户享有无限制拉取额度匿名用户和免费账户的限制保持不变建议在 CI/CD 环境中始终配置 `docker login` 以获得更高的拉取额度
> **注意** 2025 4 所有付费订阅用户享有无限制拉取额度匿名用户和免费账户的限制保持不变建议在 CI/CD 环境中始终配置 `docker login` 以获得更高的拉取额度
#### 滥用限流
-2
View File
@@ -126,8 +126,6 @@ $ docker run --rm \
-Bbn username password > auth/nginx.htpasswd
```
> 将上面的 `username` `password` 替换为你自己的用户名和密码
>
> **安全提示**上述命令会将密码明文暴露在 shell 历史记录和进程列表中生产环境建议使用交互式方式输入密码不带 `-b` 参数或通过环境变量/文件传入
> **版本说明**使用 `httpd:2.4-alpine` 基于 Apache 2.4 的精简镜像如需其他版本可替换为 `httpd:latest` 或指定具体版本号如 `httpd:2.4.58-alpine`
+1 -1
View File
@@ -80,7 +80,7 @@ server {
ssl_certificate_key key/example.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
large_client_header_buffers 4 32k;
+4 -4
View File
@@ -82,9 +82,9 @@ RUN pwd # 输出 /app
```docker
## 构建阶段
## 建议使用 node:22 node: 等具体版本标签避免使用 latest
## 建议使用 node:20 node: 等具体版本标签避免使用 latest
FROM node:22 AS builder
FROM node:20 AS builder
WORKDIR /build
COPY package*.json ./
RUN npm install
@@ -105,8 +105,8 @@ COPY --from=builder /build/dist .
#### 1. 尽早设置 WORKDIR
```docker
# 建议使用 node:22 等主/次版本号标签
FROM node:22
# 建议使用 node:20 等主/次版本号标签
FROM node:20
WORKDIR /app # 尽早设置
COPY package*.json ./
+4 -4
View File
@@ -35,7 +35,7 @@ flowchart LR
#### 创建并切换用户
```docker
FROM node:22-alpine
FROM node:20-alpine
## 1. 创建用户和组
@@ -173,7 +173,7 @@ $ docker run -u root myimage
切换用户后确保应用有权访问文件
```docker
FROM node:22-alpine
FROM node:20-alpine
## 创建用户
@@ -229,14 +229,14 @@ USER 1000:1000
```docker
## 构建阶段可以用 root
FROM node:22 AS builder
FROM node:20 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
## 生产阶段用非 root
FROM node:22-alpine
FROM node:20-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.25-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:22-alpine
FROM node:20-alpine
WORKDIR /app
## 这些指令将在子镜像构建时执行
@@ -126,7 +126,7 @@ ONBUILD COPY dist/ /usr/share/nginx/html/
建议在镜像标签中添加 `-onbuild` 后缀明确告知使用者该镜像包含触发器
```bash
node:22-onbuild
node:20-onbuild
python:3.12-onbuild
```
+5 -13
View File
@@ -14,20 +14,12 @@ Dockerfile 中的常用指令包括:
- **FROM**: 指定基础镜像必须是第一条指令
- **RUN**: 在镜像中执行命令用于安装软件包等
- **COPY**: 复制文件到镜像中
- **ADD**: 更高级的复制文件支持 URL 和自动解压
- **CMD**: 容器默认执行的命令
- **ENTRYPOINT**: 容器启动时的入口点
- **ENV**: 设置环境变量
- **ARG**: 构建时的参数变量
- **VOLUME**: 定义匿名卷挂载点
- **EXPOSE**: 声明容器监听的端口
- **WORKDIR**: 设置工作目录
- **USER**: 指定运行容器时的用户
- **HEALTHCHECK**: 配置容器健康检查
- **ONBUILD**: 设置触发器指令在子镜像构建时执行
- **LABEL**: 为镜像添加元数据标签
- **SHELL**: 指定 RUN 等指令使用的 shell
- **COPY/ADD**: 复制文件到镜像中
- **EXPOSE**: 声明容器监听的端口
- **ENV**: 设置环境变量
- **ENTRYPOINT**: 容器启动时的入口点
- **CMD**: 容器默认执行的命令
### 最佳实践建议
+4 -15
View File
@@ -33,7 +33,7 @@ WORKDIR /go/src/github.com/go/helloworld/
COPY app.go .
RUN go mod init helloworld \
&& go get github.com/go-sql-driver/mysql \
&& go get -d -v github.com/go-sql-driver/mysql \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . \
&& cp /go/src/github.com/go/helloworld/app /root
@@ -62,8 +62,7 @@ WORKDIR /go/src/github.com/go/helloworld
COPY app.go .
RUN go mod init helloworld \
&& go get github.com/go-sql-driver/mysql \
RUN go get -d -v github.com/go-sql-driver/mysql \
&& CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
```
编写 `Dockerfile.copy` 文件
@@ -126,8 +125,7 @@ RUN apk --no-cache add git
WORKDIR /go/src/github.com/go/helloworld/
RUN go mod init helloworld \
&& go get github.com/go-sql-driver/mysql
RUN go get -d -v github.com/go-sql-driver/mysql
COPY app.go .
@@ -160,15 +158,6 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
```
很明显使用多阶段构建的镜像体积小同时也完美解决了上边提到的问题
> **Go Modules 最佳实践**上述示例为简化演示在 Dockerfile 中临时执行 `go mod init`在实际项目中通常已在代码仓库中维护好 `go.mod` `go.sum` 文件推荐的 Dockerfile 写法是先拷贝这两个文件并执行 `go mod download` 以利用 Docker 层缓存再拷贝源码并构建
>
> ```docker
> COPY go.mod go.sum ./
> RUN go mod download
> COPY . .
> RUN go build -o app .
> ```
### 7.17.4 只构建某一阶段的镜像
我们可以使用 `as` 来为某一阶段命名例如
@@ -187,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.25-alpine /etc/nginx/nginx.conf /nginx.conf
```
@@ -60,8 +60,8 @@ server {
第一阶段进行前端构建
```docker
# node 镜像推荐使用具体的版本标签 node:22-alpine
FROM node:22-alpine as frontend
# node 镜像推荐使用具体的版本标签 node:20-alpine
FROM node:20-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.25-alpine
FROM nginx:1.25-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:22-alpinecomposer:2.xphp:8.3-fpm-alpinenginx:1.28-alpine
FROM node:22-alpine as frontend
# 生产环境推荐使用具体的版本标签 node:20-alpinecomposer:2.xphp:8.3-fpm-alpinenginx:1.25-alpine
FROM node:20-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.25-alpine as nginx
ARG LARAVEL_PATH=/app/laravel
+1 -1
View File
@@ -178,7 +178,7 @@ ADD app.tar.gz /app/
```docker
## 构建阶段
FROM node:22 AS builder
FROM node:20 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.30 \
NODE_VERSION=22 \
ENV NGINX_VERSION=1.25 \
NODE_VERSION=20 \
PYTHON_VERSION=3.12
RUN apt-get install nginx=${NGINX_VERSION}
## 版本分散在各处
RUN apt-get install nginx=1.30
RUN apt-get install nginx=1.25
```
#### 2. 不要存储敏感信息
+4 -4
View File
@@ -93,14 +93,14 @@ RUN echo "Node version: $NODE_VERSION"
```docker
ARG BASE_VERSION=alpine
FROM node:22-${BASE_VERSION} AS builder
FROM node:20-${BASE_VERSION} AS builder
## 需要重新声明
ARG NODE_VERSION=20
RUN echo "Building with Node $NODE_VERSION"
FROM node:22-${BASE_VERSION}
FROM node:20-${BASE_VERSION}
## 每个阶段都需要重新声明
@@ -125,8 +125,8 @@ $ docker build --build-arg ALPINE_VERSION=3.19 .
#### 2. 设置软件版本
```docker
# 使用次版本号 (1.30) 而非完整版本号 (1.30.0)以便自动更新到最新补丁版本
ARG NGINX_VERSION=1.30
# 使用次版本号 (1.25) 而非完整版本号 (1.25.0)以便自动更新到最新补丁版本
ARG NGINX_VERSION=1.25
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.4
FROM mysql:8.0
VOLUME /var/lib/mysql
```
@@ -63,7 +63,7 @@ VOLUME ["/data", "/logs", "/config"]
如果运行时未指定挂载Docker 会自动创建匿名卷
```bash
$ docker run mysql:8.4
$ docker run mysql:8.0
$ 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.4
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
```
#### 3. 可被 Bind Mount 覆盖
@@ -82,7 +82,7 @@ $ docker run -v mysql_data:/var/lib/mysql mysql:8.4
```bash
## 使用宿主机目录替代
$ docker run -v /my/data:/var/lib/mysql mysql:8.4
$ docker run -v /my/data:/var/lib/mysql mysql:8.0
```
---
@@ -145,7 +145,7 @@ VOLUME /app/uploads
```bash
## 查看镜像定义的 VOLUME
$ docker inspect mysql:8.4 --format '{{json .Config.Volumes}}' | jq
$ docker inspect mysql:8.0 --format '{{json .Config.Volumes}}' | jq
{
"/var/lib/mysql": {}
}
@@ -196,7 +196,7 @@ volumes:
```bash
## 使用 --rm 运行的容器匿名卷会在容器删除时一起删除
$ docker run --rm mysql:8.4
$ docker run --rm mysql:8.0
## 容器停止后数据丢失
@@ -205,7 +205,7 @@ $ docker run --rm mysql:8.4
**解决**始终使用命名卷
```bash
$ docker run -v mysql_data:/var/lib/mysql mysql:8.4
$ docker run -v mysql_data:/var/lib/mysql mysql:8.0
```
---
+1 -1
View File
@@ -80,7 +80,7 @@ docker build -t my-image:1.0 .
本章中的 Dockerfile 示例使用的基础镜像标签遵循以下原则
- **通用标签** `ubuntu:24.04``alpine``nginx`保持原样无需修改
- **基础镜像版本号** `node:22``python:3.12`使用主或次版本号而非完整版本号patch这样可以自动获取最新的补丁版本确保获得安全更新
- **基础镜像版本号** `node:20``python:3.12`使用主或次版本号而非完整版本号patch这样可以自动获取最新的补丁版本确保获得安全更新
- **避免**不建议使用 `latest` 标签和完整的 patch 版本号 `20.10.0`作为基础镜像因为这会导致构建的不可重现性或安全风险
读者在使用这些示例时应根据实际生产环境需求选择合适的版本号
@@ -1,4 +1,4 @@
FROM node:22-alpine as frontend
FROM node:20-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.30-alpine as nginx
FROM nginx:1.25-alpine as nginx
ARG LARAVEL_PATH=/app/laravel
+1 -3
View File
@@ -238,7 +238,7 @@ $ docker run -u $(id -u):$(id -g) ...
Docker Desktop Bind Mount 性能通常不如 Volume因为数据需要在宿主机文件系统和 Linux VM 之间同步
```bash
## 使用 :cached :delegated 提高性能macOS Docker Desktop 4.5 及更早版本
## 使用 :cached :delegated 提高性能macOS
$ docker run -v /host/path:/container/path:cached myapp
```
@@ -248,8 +248,6 @@ $ docker run -v /host/path:/container/path:cached myapp
| `:delegated` | 容器权威宿主机读取可能延迟 |
| `:consistent` | 默认完全一致 (最慢)|
> **注意**Docker Desktop 4.6+ 默认使用 VirtioFS 文件共享引擎上述 `:cached`/`:delegated` 选项已被静默忽略如需优化文件同步性能请参考 Docker Desktop [Synchronized file shares](https://docs.docker.com/desktop/synchronized-file-sharing/) 功能。
---
### 8.2.9 最佳实践
-1
View File
@@ -21,7 +21,6 @@ ghi789... none null local
| **none** | 禁用网络 | 完全隔离的容器 |
| **overlay** | 跨主机网络 | Docker Swarm 集群 |
| **macvlan** | 容器拥有独立 MAC 地址 | 需要直接接入物理网络 |
| **ipvlan** | 容器共享父接口 MAC独享 IP | 同网段大量容器 MAC 数量受限的网络 |
### 9.2.2 Bridge 网络默认
+5 -5
View File
@@ -53,7 +53,7 @@ docker network inspect my-overlay-net
docker service create --name web \
--network my-overlay-net \
--replicas 3 \
nginx # 确保与环境兼容的 Nginx 版本
nginx
# 单机环境下也可以让普通容器加入 attachable overlay 网络
docker run -d --name container1 --network my-overlay-net busybox sleep 1d
@@ -111,14 +111,14 @@ docker run -d \
--dns 8.8.8.8 \
--dns 1.1.1.1 \
--dns-search example.com \
nginx # 确保与环境兼容的 Nginx 版本
nginx
# DNS 选项
docker run -d \
--dns-option ndots:2 \
--dns-option timeout:1 \
--dns-option attempts:3 \
nginx # 确保与环境兼容的 Nginx 版本
nginx
# 查看容器 DNS 配置
docker exec <container_id> cat /etc/resolv.conf
@@ -171,8 +171,8 @@ networks:
docker network create mynet
# 运行服务
docker run -d --name web --network mynet nginx # 确保与环境兼容的 Nginx 版本
docker run -d --name db --network mynet postgres # 确保与环境兼容的 PostgreSQL 版本
docker run -d --name web --network mynet nginx
docker run -d --name db --network mynet postgres
# 在其他容器中通过服务名访问
docker run -it --network mynet busybox sh
+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
@@ -2,7 +2,7 @@
Docker Buildx 是一个 docker CLI 插件其扩展了 docker 命令支持 [Moby BuildKit](10.1_buildkit.md) 提供的功能提供了与 docker build 相同的用户体验并增加了许多新功能
> Buildx 需要 Docker v23.0+该版本起 BuildKit 成为默认构建引擎推荐使用 Docker v28 及以上版本以获得最完整的 Buildx 功能支持
> Buildx 需要 Docker v19.03+ Docker 19.03 及以上版本在较新版本中已更常用且功能更完整
## 本章内容
+2 -2
View File
@@ -26,7 +26,7 @@ Docker Compose 提供了丰富的命令来管理项目和容器。本节将详
**配置验证**
- `docker compose config`验证 docker-compose.yml 格式是否正确
- `docker compose config`验证 compose.yaml ( docker-compose.yml) 格式是否正确
### 11.4.1 命令对象与格式
@@ -46,7 +46,7 @@ docker compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
* `-p, --project-name NAME` 指定项目名称默认将使用所在目录名称作为项目名
* `--verbose` 输出更多调试信息(**已弃用** Docker Compose V2 请改用 `docker --log-level debug compose ...` 或设置环境变量 `COMPOSE_DEBUG=1`)
* `--verbose` 输出更多调试信息
* `-v, --version` 打印版本并退出
+1 -1
View File
@@ -490,7 +490,7 @@ volumes:
```yaml
services:
my_src:
image: mysql:8.4
image: mysql:8.0
volumes:
- mysql_data:/var/lib/mysql
+2 -8
View File
@@ -106,11 +106,6 @@ services:
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
web:
build: .
@@ -120,8 +115,7 @@ services:
ports:
- "3000:3000"
depends_on:
db:
condition: service_healthy
- db
environment:
DATABASE_URL: postgres://postgres:password@db:5432/myapp_development
@@ -134,7 +128,7 @@ volumes:
|--------|------|
| `rm -f tmp/pids/server.pid` | 清理上次异常退出留下的 PID 文件 |
| `volumes: .:/myapp` | 挂载代码目录支持热更新 |
| `depends_on` + `condition` | 等待数据库健康检查通过后再启动 |
| `depends_on: db` | 确保数据库启动 |
| `DATABASE_URL` | Rails 12-factor 风格的数据库配置 |
### 11.7.6 步骤 4生成 Rails 项目
+3 -3
View File
@@ -28,13 +28,13 @@ services:
# 数据库服务
db:
image: mysql:8.4
image: mysql:8.0
container_name: wordpress_db
restart: always
command:
# 用原生密码认证MySQL 8.4 默认禁用旧版 WP 兼容性需要
# 使用原生密码认证旧版 WP 兼容性
- --mysql-native-password=ON
- --default-authentication-plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
environment:
@@ -5,6 +5,11 @@ services:
image: postgres
environment:
POSTGRES_PASSWORD: 'postgres'
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
web:
build: .
@@ -13,3 +18,6 @@ services:
- .:/code
ports:
- "8000:8000"
depends_on:
db:
condition: service_healthy
+2 -2
View File
@@ -2,9 +2,9 @@
services:
db:
image: mysql:8.4
image: mysql:8.0
command:
- --mysql-native-password=ON
- --default_authentication_plugin=mysql_native_password
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
+1 -1
View File
@@ -198,7 +198,7 @@ $ docker run --rm --cpus=1 stress --cpu 4
#### Docker cgroups v2 的支持
Docker 20.10+ 开始支持 cgroups v2如果系统支持提供更好的性能和资源隔离如果需要明确控制或回退到 v1可以通过 Docker 守护进程配置文件 `/etc/docker/daemon.json` 修改 `cgroup-driver` 参数
Docker 19.03+ 默认优先使用 cgroups v2如果系统支持提供更好的性能和资源隔离如果需要明确控制或回退到 v1可以通过 Docker 守护进程配置文件 `/etc/docker/daemon.json` 修改 `cgroup-driver` 参数
```json
{
+1 -1
View File
@@ -41,7 +41,7 @@ flowchart TD
每个 Dockerfile 指令创建一层只有变化的层需要重建
```docker
FROM node:22 # 层1基础镜像
FROM node:20 # 层1基础镜像
COPY package.json ./ # 层2依赖定义
RUN npm install # 层3安装依赖
COPY . . # 层4应用代码
+3 -3
View File
@@ -35,7 +35,7 @@
##### 节点状态
节点的状态通过一组条件Conditions来描述主要条件包括 `Ready`kubelet 健康且可以接收 Pod`MemoryPressure`内存不足`DiskPressure`磁盘不足 `PIDPressure`进程数过多其中 `Ready` 条件最为关键值为 `True` 表示节点健康可调度`False` 表示节点异常`Unknown` 表示节点控制器超过一定时间未收到心跳
节点的状态主要是用来描述处于 `Running` 的节点当前可用的有 `NodeReachable` `NodeReady`以后可能会增加其他状态`NodeReachable` 表示集群可达`NodeReady` 表示 kubelet 返回 Status Ok 并且 HTTP 状态检查健康
#### 节点管理
@@ -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.4
image: mysql:8.0
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
+2 -4
View File
@@ -138,14 +138,12 @@ $ sysctl --system
为了让 kubelet 正确运行我们需要对其进行一些必要的配置
#### 修改 `kubelet.service`可选IPVS 模式
> **注意**kube-proxy IPVS 模式已在 Kubernetes 1.35 中被标记为弃用并在 **Kubernetes 1.36 中正式移除**新部署应使用默认的 iptables 模式或 nftables 模式Kubernetes 1.31+ 可用以下 IPVS 配置仅供 1.35 及更早版本的旧环境参考
#### 修改 `kubelet.service`
`/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容
```bash
# 启用 ipvs 相关内核模块已弃用建议迁移至 nftables
# 启用 ipvs 相关内核模块
[Service]
ExecStartPre=-/sbin/modprobe ip_vs
+3 -6
View File
@@ -169,14 +169,12 @@ $ sysctl --system
为了让 kubelet 正确运行我们需要对其进行一些必要的配置
#### 修改 `kubelet.service`可选IPVS 模式
> **注意**kube-proxy IPVS 模式已在 Kubernetes 1.35 中被标记为弃用并在 **Kubernetes 1.36 中正式移除**新部署应使用默认的 iptables 模式或 nftables 模式Kubernetes 1.31+ 可用以下 IPVS 配置仅供 1.35 及更早版本的旧环境参考
#### 修改 `kubelet.service`
`/etc/systemd/system/kubelet.service.d/10-proxy-ipvs.conf` 写入以下内容
```bash
# 启用 ipvs 相关内核模块已弃用建议迁移至 nftables
# 启用 ipvs 相关内核模块
[Service]
ExecStartPre=-/sbin/modprobe ip_vs
@@ -242,8 +240,7 @@ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
```bash
$ kubeadm join 192.168.199.100:6443 --token cz81zt.orsy9gm9v649e5lf \
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe \
--cri-socket unix:///var/run/cri-dockerd.sock
--discovery-token-ca-cert-hash sha256:5edb316fd0d8ea2792cba15cdf1c899a366f147aa03cba52d4e5c5884ad836fe
```
### 14.2.7 查看服务
+3 -5
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-
@@ -240,10 +240,8 @@ $ kubectl config set-context --current --namespace=my-namespace
# 显示集群信息
$ kubectl cluster-info
# 显示完整的集群状态componentstatuses 1.19 起已弃用建议使用下方替代命令
# 显示完整的集群状态包括所有组件
$ kubectl get componentstatuses
# 推荐替代
$ kubectl get --raw='/readyz?verbose'
```
### 14.8.15 version
+1 -1
View File
@@ -1,6 +1,6 @@
## 15.1 简介
> **版本说明** 本章内容基于 etcd 3.5 系列版本编写官方维护最新两个次版本当前为 3.5 3.6请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本信息。
> **版本说明** 本章内容基于 etcd 3.5 系列版本编写当前最新 v3.5.x请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本信息。
如图 15-1 所示etcd 项目使用该标识
+1 -1
View File
@@ -4,7 +4,7 @@
`etcd` 基于 `Go` 语言实现因此用户可以从[项目主页](https://github.com/etcd-io/etcd)下载源代码自行编译,也可以下载编译好的二进制文件,甚至直接使用制作好的 `Docker` 镜像文件来体验。
> 注意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) 获取最新版本。
> 注意etcd 官方仅维护最新两个次版本当前为 3.5 3.6本章示例基于 etcd `3.5.x` 版本编写etcd 3.6.x 可用于新部署请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本。
### 15.2.1 二进制文件方式下载
+2 -4
View File
@@ -111,11 +111,9 @@ hello
```
支持的选项为
`--sort-by` 指定排序字段CREATE / KEY / MODIFY / VALUE / VERSION
`--sort` 对结果进行排序
`--order` 指定排序顺序ASCEND / DESCEND
`--consistency` 指定一致性级别`l` 线性一致`s` 串行
`--consistent` 将请求发给主节点保证获取内容的一致性
#### del
+3 -3
View File
@@ -2,7 +2,7 @@ version: "3.6"
services:
node1:
image: quay.io/coreos/etcd:v3.5.29
image: quay.io/coreos/etcd:v3.5.17
volumes:
- node1-data:/etcd-data
expose:
@@ -34,7 +34,7 @@ services:
- docker-etcd
node2:
image: quay.io/coreos/etcd:v3.5.29
image: quay.io/coreos/etcd:v3.5.17
volumes:
- node2-data:/etcd-data
networks:
@@ -66,7 +66,7 @@ services:
- docker-etcd
node3:
image: quay.io/coreos/etcd:v3.5.29
image: quay.io/coreos/etcd:v3.5.17
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 核心特性
+2 -2
View File
@@ -40,8 +40,8 @@
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 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)。
- 随着 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 v1containerd 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 -8
View File
@@ -1,19 +1,12 @@
# 第十七章 容器其它生态
> **版本说明核验日期2026-05-16**本章介绍的工具和运行时PodmanBuildahSkopeocontainerdKata ContainersgVisorWasmEdge 都保持活跃的开发建议
> **版本说明**本章介绍的工具和运行时PodmanBuildahSkopeocontainerdKata ContainersgVisorWasmEdge 都保持活跃的开发建议
> - 查阅各项目官方文档获取最新版本
> - 在生产环境使用前验证版本兼容性
> - 关注官方发布说明了解重大变更
本章将介绍 Docker Kubernetes 之外的容器生态技术
同时Docker 自身的生态也在向云构建AI 本地推理和企业级桌面安全扩展当前需要额外关注
* **Docker Model Runner** Docker Desktop / Docker Engine 中管理运行和服务本地 AI 模型支持 OpenAI Ollama 兼容 API并可将 GGUFSafetensors 等模型文件作为 OCI Artifact 管理
* **Docker Build Cloud**通过远程 BuildKit 和共享构建缓存加速本地与 CI 构建适合多平台镜像和团队共享缓存场景
* **Docker Offload**把容器构建和运行卸载到云端适合 VDI受限本机或不支持嵌套虚拟化的开发环境
* **Hardened Docker Desktop / Enhanced Container Isolation (ECI)**通过更强的命名空间隔离敏感挂载保护和系统调用限制降低桌面容器逃逸风险
## 本章内容
* [Fedora CoreOS 简介](17.1_coreos_intro.md)
+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就表明即使内核保持更新运行时层的缺陷仍然可能导致容器隔离被突破
+1 -1
View File
@@ -50,7 +50,7 @@ dockerd \
### 18.3.3 Rootless 模式非特权运行
为了从根本上解决拥有 Docker socket 就是 root的问题Docker 19.03 版本2019 起提供 **Rootless 模式**
为了从根本上解决拥有 Docker socket 就是 root的问题Docker 在近年推出 **Rootless 模式**
Rootless 模式允许在完全局限于非 `root` 用户的环境中运行 Docker 守护进程`dockerd`和容器该模式利用了现代 Linux 内核的 User Namespace 技术和非特权网络命名空间实现
+1 -1
View File
@@ -8,7 +8,7 @@
一个普通的 Linux 内核提供了 300 多个系统调用而一个正常运行的容器化应用例如 Nginx 服务通常只会用到几十个调用这就给攻击者留下了大量的闲置入口点来进行内核层的缓冲区溢出攻击
Docker 默认启用了 Seccomp 并利用预置的 [默认配置文件](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) 将可以利用的系统调用缩减到了不足一半(默认禁用了 44 个危险的统调用,比如修改时区或重启系统)。
Docker 默认启用了 Seccomp 并利用预置的 [默认配置文件](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) 将可以利用的系统调用缩减到了不足一半(默认禁用了 44 个危险的统调用,比如修改时区或重启系统)。
如果你对应用的系统调用特征了如指掌你可以为容器定制专属规则
+2 -2
View File
@@ -434,8 +434,8 @@ jobs:
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Run Trivy vulnerability scan
# 安全提醒2026 3 19 Trivy GitHub Actions 遭受供应链攻击
# 76 个版本标签被劫持务必使用不可变的 commit SHA 引用而非可变标签
# 安全提醒2026 3 Trivy GitHub Actions 遭受供应链攻击
# 75 个版本标签被劫持务必使用不可变的 commit SHA 引用而非可变标签
# 使用前请到 https://github.com/aquasecurity/trivy-action/releases 核实 SHA 对应正确版本。
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
with:
+2 -2
View File
@@ -22,7 +22,7 @@ ELK (ElasticsearchLogstashKibana) 是目前业界最流行的开源日志
```yaml
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:9.4.0
image: docker.elastic.co/elasticsearch/elasticsearch:9.3.3
container_name: elasticsearch
environment:
- "discovery.type=single-node"
@@ -36,7 +36,7 @@ services:
- logging
kibana:
image: docker.elastic.co/kibana/kibana:9.4.0
image: docker.elastic.co/kibana/kibana:9.3.3
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
+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 日志驱动
+7 -7
View File
@@ -25,7 +25,7 @@ Debian 是一个常用的基础镜像。
```bash
$ docker run -it debian bash
root@668e178d8d69:/# cat /etc/issue
Debian GNU/Linux 13
Debian GNU/Linux 12
```
`Debian` 镜像很适合作为基础镜像构建自定义镜像
@@ -43,18 +43,18 @@ Debian GNU/Linux 13
Ubuntu 是目前最流行的 Linux 发行版之一
下面以 `ubuntu:26.04` 为例演示如何使用该镜像安装一些常用软件
下面以 `ubuntu:24.04` 为例演示如何使用该镜像安装一些常用软件
首先使用 `-ti` 参数启动容器登录 `bash`查看 `ubuntu` 的发行版本号
```bash
$ docker run -ti ubuntu:26.04 /bin/bash
$ docker run -ti ubuntu:24.04 /bin/bash
root@7d93de07bf76:/# cat /etc/os-release
PRETTY_NAME="Ubuntu 26.04 LTS"
PRETTY_NAME="Ubuntu 24.04 LTS"
NAME="Ubuntu"
VERSION_ID="26.04"
VERSION="26.04 LTS (Resolute Raccoon)"
VERSION_CODENAME=resolute
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
+1 -1
View File
@@ -50,7 +50,7 @@ latest: Pulling from library/fedora
Digest: sha256:64a02df6aac27d1200c2572fe4b9949f1970d05f74d367ce4af994ba5dc3669e
Status: Downloaded newer image for fedora:latest
[root@196ca341419b /]# cat /etc/redhat-release
Fedora release 43 (Forty Three)
Fedora release 39 (Thirty Nine)
```
### 20.4.3 相关资源
+1 -1
View File
@@ -8,7 +8,7 @@
本章示例中使用的操作系统镜像版本遵循以下原则
- **AlpineDebianUbuntuCentOS** 等操作系统镜像采用大版本或次版本标签 `alpine:3.21``ubuntu:26.04`避免使用 `latest` 标签确保构建的可再现性
- **AlpineDebianUbuntuCentOS** 等操作系统镜像采用大版本或次版本标签 `alpine:3.21``ubuntu:24.04`避免使用 `latest` 标签确保构建的可再现性
- **OS 大版本保留**以便获得最新的安全补丁和修复
- 在生产环境中建议根据实际需求选择合适的版本并定期更新以获得安全修复
+2 -2
View File
@@ -54,9 +54,9 @@ unit_test:
build_image:
stage: build
image: docker:29
image: docker:27
services:
- docker:29-dind
- docker:27-dind
script:
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
+1 -1
View File
@@ -543,7 +543,7 @@ logfile ""
# 客户端输出缓冲限制
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
```
+1 -1
View File
@@ -12,7 +12,7 @@
## DevOps 背景介绍
DevOps 是一种重要的开发和运维文化强调开发团队和运维团队之间的协作和自动化它致力于通过自动化和流程优化加快软件交付速度同时提高系统的稳定性和可靠性Docker 作为容器化技术的领导者已成为现代 DevOps 工作流中不可或缺的工具通过容器化应用开发团队可以确保一次构建处处运行消除开发测试和生产环境的差异大大简化了部署流程
DevOps 是一种重要的开发和运维文化强调开发团队和运维团队之间的协作和自动化它致力于通过自动化和流程优化加快软件交付速度同时提高系统的稳定性和可靠性Docker 作为容器化技术的领导者已成为现代 DevOps 工作流中不可或缺的工具通过容器化应用开发团队可以确保一次构建处处运行消除开发测试和生产环境的差异大大简化了部署流程
## Docker DevOps 中的角色
+2 -2
View File
@@ -14,7 +14,7 @@
#### 使用多阶段构建
现代 Docker 版本中你可以使用[多阶段构建](../07_dockerfile/7.17_multistage_builds.md)来减少所构建镜像的大小该能力最早在 Docker 17.05 引入如今已是编写生产镜像的默认实践之一新项目还应结合 BuildKit 缓存挂载secret 挂载和多平台构建能力一起评估
Docker 17.05 以上版本中你可以使用[多阶段构建](../07_dockerfile/7.17_multistage_builds.md)来减少所构建镜像的大小
#### 避免安装不必要的包
@@ -190,7 +190,7 @@ ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgres && …
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress && …
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH
```
+1 -1
View File
@@ -14,7 +14,7 @@
```bash
$ sudo kill -SIGHUP $(pidof dockerd)
```
此时 dockerd 会在日志中输更多信息供分析
此时 dockerd 会在日志中输更多信息供分析
### 检查内核日志
+4 -4
View File
@@ -421,7 +421,7 @@ Kubernetes 进阶 (Week 24-36)
- [Docker 官方博客](https://www.docker.com/blog/)
- [Kubernetes 官方博客](https://kubernetes.io/blog/)
- [CNCF 博客](https://www.cncf.io/blog/)
- [DZone Cloud Architecture](https://dzone.com/cloud-architecture)
- [DZone](https://dzone.com/containers-cloud)
### 认证指南
@@ -435,7 +435,7 @@ Kubernetes 进阶 (Week 24-36)
- 时间限制90 分钟
- 及格分数73% 41 道题
- 费用$199 USD
- 有效期2
- 有效期3
考试内容比例
```text
@@ -478,7 +478,7 @@ Kubernetes 进阶 (Week 24-36)
# 1. 学习本书第 1-11 基础到中级
# 2. 完成 20+ 个实战项目
# 3. 参考官方学习指南
# 参考 KodeKloud DCA 认证指南https://kodekloud.com/blog/docker-certified-associate-guide/
curl https://docker.training.kodekloud.com/dca-guide
# 4. 模拟考试
- Linux Academy DCA 练习题
@@ -587,7 +587,7 @@ A(要点):
A要点
```text
1. 选择合适的基础镜像
scratch < alpine:3.21 < python:3.14-slim < python:3.14
scratch < alpine:3.17 < python:3.14-slim < python:3.14
2. 多阶段构建
- 构建阶段只保留编译工具
+1 -1
View File
@@ -9,7 +9,7 @@
> 2026 年了对于任何新项目**强烈建议** 使用以下生产级替代方案
> - [Rocky Linux](https://hub.docker.com/_/rockylinux)CentOS 原创始人发起的社区驱动项目,目前主流为 Rocky Linux 9。
> - [AlmaLinux](https://hub.docker.com/_/almalinux):由 CloudLinux 支持的企业级发行版,提供长期支持。
> - [CentOS Stream](https://quay.io/repository/centos/centos)RHEL 的上游开发分支,镜像已迁移至 Quay.io (适合开发测试,不建议用于生产环境)。
> - [CentOS Stream](https://hub.docker.com/r/centos/centos)RHEL 的上游开发分支 (适合开发测试,不建议用于生产环境)。
该仓库位于 [Docker Hub CentOS 官方镜像页](https://hub.docker.com/_/centos),提供了 CentOS 从 5 ~ 8 各个版本的镜像(仅作为历史归档,不再更新)。
+2 -2
View File
@@ -25,13 +25,13 @@ $ docker run --name some-mongo -d --network my-mongo-net mongo
```bash
$ docker run --name some-app -d --network my-mongo-net application-that-uses-mongo
```
或者通过 `mongosh`MongoDB 6.0+ 移除旧版 `mongo` 命令行工具
或者通过 `mongosh`MongoDB 6.0+ 弃用 `mongo`请使用 `mongosh`
```bash
$ docker run -it --rm \
--network my-mongo-net \
mongo \
mongosh "some-mongo:27017/test"
sh -c 'exec mongosh "mongodb://some-mongo:27017/test"'
```
### Dockerfile
+2 -4
View File
@@ -11,7 +11,7 @@
在项目中创建一个 Dockerfile
```docker
FROM node:22
FROM node:20
## replace this with your application's default port
@@ -28,11 +28,9 @@ $ docker run -it --rm --name my-running-app my-nodejs-app
```bash
$ docker run -it --rm \
--name my-running-script \
# -v "$ ":/usr/src/myapp \
--mount type=bind,src="$(pwd)",target=/usr/src/myapp \
-w /usr/src/myapp \
node:22-alpine \
node:20-alpine \
node your-daemon-or-script.js
```