34 Commits

Author SHA1 Message Date
yeasy
d6fff9a3f7 Fix broken AliCloud screenshot link 2026-03-09 21:43:51 -07:00
yeasy
fc276d3b4f Expand Compose introduction and value proposition 2026-03-09 21:43:48 -07:00
yeasy
40ded62baa Clean gitignore 2026-03-09 20:04:22 -07:00
yeasy
89b0dc4425 Add details for cloud images 2026-03-09 20:04:22 -07:00
yeasy
330e084e00 Improve READMEs and add contribution prompts 2026-03-09 20:04:21 -07:00
yeasy
e62b203f1a Expand Tencent Cloud and Alibaba Cloud docs 2026-03-09 20:04:20 -07:00
yeasy
cb6bf74a2e Add pitfall notes to COPY and networking docs 2026-03-09 20:04:19 -07:00
yeasy
a980e34276 Fix cgroups, VOLUME, and tmpfs descriptions 2026-03-09 20:04:19 -07:00
yeasy
3d33e00802 Bump Compose to v5.1.0 and drop deprecated version field 2026-03-09 20:04:18 -07:00
yeasy
1a820c8c8b Bump Flannel to v0.28.1 2026-03-09 20:04:17 -07:00
yeasy
585b364574 Add etcd 3.4 end-of-life warning 2026-03-09 20:04:17 -07:00
yeasy
a0a5de7f11 Upgrade EFK stack and cAdvisor versions 2026-03-09 20:04:16 -07:00
yeasy
83ba6b7b47 Upgrade GitHub Actions and Cosign in security docs 2026-03-09 20:04:16 -07:00
yeasy
53f20dede7 Minor fix 2026-03-09 20:04:15 -07:00
baohua
48c8b50cf7 Fix typography 2026-03-09 20:04:13 -07:00
baohua
70ef2cba58 Fix heading hierarchy 2026-03-05 19:24:01 -08:00
baohua
f5cfa4140a Update containerd architecture 2026-03-05 20:34:40 -08:00
baohua
d174cf327c Update table of contents 2026-03-05 23:48:13 -08:00
baohua
6a9ce44c5a Add learning roadmap 2026-03-05 19:14:37 -08:00
baohua
c09f66da55 Add practical examples 2026-03-05 22:23:06 -08:00
baohua
635e05ad34 Add performance optimization 2026-03-05 21:20:06 -08:00
baohua
6f22d0f5f0 Add image security 2026-03-05 22:19:18 -08:00
baohua
17517e26b7 Add advanced networking 2026-03-05 19:39:42 -08:00
Baohua Yang
9fcaff6673 Fix typo 2026-03-04 17:35:19 -08:00
baohua
a096947382 Optimize content and fix issues 2026-03-03 19:30:21 -08:00
Baohua Yang
be09a95d0d Refine words 2026-03-02 22:16:51 -08:00
Baohua Yang
3af007b176 Use more accurate words 2026-03-02 21:58:39 -08:00
Baohua Yang
551dcfd2cb Refine content 2026-03-02 21:57:32 -08:00
Baohua Yang
0d2654fbf2 Update content 2026-03-02 21:56:46 -08:00
Baohua Yang
3894ba56bc Fix format 2026-03-02 21:55:31 -08:00
Baohua Yang
0dd0d036a2 Update and fix format 2026-03-02 21:54:37 -08:00
Baohua Yang
a9c4189c0c Remove duplicated content 2026-03-01 22:48:51 -08:00
Baohua Yang
56deeaee0f Use docker engine v29 2026-03-01 22:47:56 -08:00
Baohua Yang
0ff67cc893 Add security note 2026-02-28 14:28:38 -08:00
115 changed files with 5138 additions and 1025 deletions

12
.gitignore vendored
View File

@@ -21,11 +21,7 @@ docker-compose.override.yml
__pycache__/
# Check scripts
check_project_rules.py
check_dashes.py
checker.py
find_lists_no_space.py
fix_missing_spaces.py
fix_project_rules.py
fixer.py
format_headings.py
check*.py
find*.py
fix*.py
format*.py

View File

@@ -45,7 +45,7 @@ $ docker run -d -p 8080:80 my-hello-world
### 1.1.5 访问测试
打开浏览器访问 [http://localhost:8080](http://localhost:8080),你应该能看到 “HelloDocker”。
打开浏览器访问 [http://localhost:8080](http://localhost:8080),你应该能看到 “Hello, Docker!”。
### 1.1.6 清理

View File

@@ -102,7 +102,7 @@ $ docker compose up
Docker 容器共享宿主机内核无需为每个应用运行完整的操作系统以一台 64GB 内存的物理服务器为例
- **传统虚拟机方案**每个虚拟机都需要运行完整的操作系统每个额外占用如 2GB 内存产生大量资源开销实际可用于应用的内存可能只有约 18GB
- **Docker 方案**容器直接共享宿主机系统只需付出很少的基础开销OS及引擎约 4GB即可将约 60GB 的内存全部用于实际应用
- **Docker 方案**容器直接共享宿主机系统只需付出很少的基础开销OS 及引擎约 4GB即可将约 60GB 的内存全部用于实际应用
```mermaid
flowchart TD
@@ -200,13 +200,7 @@ flowchart TD
### 1.3.5 与传统虚拟机的对比总结
下表对比了容器技术与传统虚拟机的区别
关于容器与虚拟机的详细特性对比请参阅 [1.2.3 Docker vs 虚拟机](1.2_what.md) 中的对比表总结来说
| 特性 | Docker 容器 | 传统虚拟机 |
|:------|:-----------|:-----------|
| 启动速度 | 秒级 | 分钟级 |
| 磁盘占用 | MB 级别 | GB 级别 |
| 性能 | 接近原生 | 5-20% 损耗 |
| 单机支持量 | 上千个容器 | 几十个虚拟机 |
| 隔离性 | 进程级别 | 完全隔离 |
| 最佳场景 | 微服务CI/CD开发环境 | 多租户高安全需求 |
- **性能差异**虚拟机通常有 5-20% 的性能损耗而容器接近原生性能
- **最佳场景**Docker 容器适合微服务CI/CD开发环境虚拟机适合多租户高安全需求场景

View File

@@ -2,13 +2,15 @@
本章将带领你进入 **Docker** 的世界
> **版本提示**本书内容及示例基于 **Docker Engine v29.x** 及以上版本值得注意的是 Docker Engine v29 官方在全新安装场景下 **默认启用了 `containerd image store` 作为镜像存储后端**取代了传统的经典存储引擎如 overlay2 graph driver这项底层革新极大增强了 Docker 对多架构镜像Multi-platform以及软件供应链安全元数据Attestations, SBOM, Provenance的本地支持原生性
## 本章内容
* [快速上手](1.1_quickstart.md)
* 通过一个简单的 Web 应用例子带你快速体验 Docker 的核心流程构建镜像运行容器
* [什么是 Docker](1.2_what.md)
* 介绍 Docker 的起源发展历程以及其背后的核心技术 (CgroupsNamespacesUnionFS)
* 介绍 Docker 的起源发展历程以及其背后的核心技术 (CgroupsNamespacesUnionFS以及 `containerd` 引擎的演进)
* 了解 Docker 是如何改变软件交付方式的
* [为什么要用 Docker](1.3_why.md)

View File

@@ -6,3 +6,6 @@
- Docker 推动了容器技术的标准化 (OCI) 和生态发展
Docker 的核心价值可以用一句话概括**让应用的开发测试部署保持一致同时极大提高资源利用效率** 笔者认为对于现代软件开发者来说Docker 已经不是 要不要学 的问题而是 **必备技能**无论你是前端后端运维还是全栈开发者掌握 Docker 都能让你的工作更高效
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -123,7 +123,6 @@ RUN apt-get install -y build-essential # 安装编译工具(约 200MB
RUN make && make install # 编译应用
RUN apt-get remove build-essential # 试图删除编译工具
## 结果:镜像仍然包含 200MB 的编译工具!
```
```docker

View File

@@ -56,7 +56,7 @@ flowchart TB
一个完整的 Docker 镜像名称由 Registry 地址用户名/组织名仓库名和标签组成了解其结构有助于我们更准确地定位镜像基本格式如下
```bash
[registry地址/][用户名/]仓库名[:标签]
[registry 地址/][用户名/]仓库名[:标签]
```
示例

View File

@@ -7,3 +7,9 @@
* **仓库** (`Repository`)镜像构建完成后可以很容易的在当前宿主机上运行但是如果需要在其它服务器上使用这个镜像我们就需要一个集中的存储分发镜像的服务Docker Registry 就是这样的服务
理解了这三个概念就理解了 **Docker** 的整个生命周期
## 本章内容
* [Docker 镜像](2.1_image.md)
* [Docker 容器](2.2_container.md)
* [Docker 仓库](2.3_repository.md)

View File

@@ -1,40 +1,18 @@
## 本章小结
本章介绍了 Docker 的三个核心概念镜像容器和仓库
| 概念 | 要点 |
|------|------|
| **镜像是什么** | 只读的应用模板包含运行所需的一切 |
| **分层存储** | 多层叠加共享基础层节省空间 |
| **只读特性** | 构建后不可修改保证一致性 |
| **层的陷阱** | 删除操作只是标记不减小体积 |
理解了镜像接下来让我们学习[容器](2.2_container.md)镜像的运行实例
### 2.4.1 延伸阅读
- [获取镜像](../04_image/4.1_pull.md) Registry 下载镜像
- [使用 Dockerfile 定制镜像](../04_image/4.5_build.md)创建自己的镜像
- [Dockerfile 最佳实践](../appendix/best_practices.md)构建高质量镜像的技巧
- [底层实现 - 联合文件系统](../12_implementation/12.4_ufs.md)深入理解分层存储的技术原理
| 概念 | 要点 |
|------|------|
| **容器是什么** | 镜像的运行实例本质是隔离的进程 |
| **容器 vs 虚拟机** | 共享内核更轻量但隔离性较弱 |
| **存储层** | 可写层随容器删除而消失 |
| **数据持久化** | 使用 Volume Bind Mount |
| **生命周期** | 与主进程 (PID 1) 绑定 |
理解了镜像和容器接下来让我们学习[仓库](2.3_repository.md)存储和分发镜像的服务
### 2.4.2 延伸阅读
- [启动容器](../05_container/5.1_run.md)详细的容器启动选项
- [后台运行](../05_container/5.2_daemon.md)理解容器为什么会 立即退出
- [进入容器](../05_container/5.4_attach_exec.md)如何操作运行中的容器
- [数据管理](../08_data/README.md)Volume 和数据持久化详解
| 概念 | 要点 |
|------|------|
| **Registry** | 存储和分发镜像的服务 |
| **仓库 (Repository)** | 同一软件的镜像集合 |
| **标签 (Tag)** | 版本标识默认为 latest |
@@ -43,9 +21,20 @@
现在你已经了解了 Docker 的三个核心概念[镜像](2.1_image.md)[容器](2.2_container.md)和仓库接下来让我们开始[安装 Docker](../03_install/README.md)动手实践
### 2.4.3 延伸阅读
### 延伸阅读
- [获取镜像](../04_image/4.1_pull.md) Registry 下载镜像
- [使用 Dockerfile 定制镜像](../04_image/4.5_build.md)创建自己的镜像
- [Dockerfile 最佳实践](../appendix/best_practices.md)构建高质量镜像的技巧
- [底层实现 - 联合文件系统](../12_implementation/12.4_ufs.md)深入理解分层存储的技术原理
- [启动容器](../05_container/5.1_run.md)详细的容器启动选项
- [后台运行](../05_container/5.2_daemon.md)理解容器为什么会立即退出
- [进入容器](../05_container/5.4_attach_exec.md)如何操作运行中的容器
- [数据管理](../08_data/README.md)Volume 和数据持久化详解
- [Docker Hub](../06_repository/6.1_dockerhub.md)Docker Hub 的详细使用
- [私有仓库](../06_repository/6.2_registry.md)搭建私有 Registry
- [私有仓库高级配置](../06_repository/6.3_registry_auth.md)认证TLS 配置
- [镜像加速器](../03_install/3.9_mirror.md)配置镜像加速
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -122,7 +122,12 @@ $ sudo systemctl start docker
### 3.1.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
> **安全警告`docker` 用户组等同于 `root` 权限**
>
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐但这也意味着该用户可以轻易获取主机的最高 root 权限例如通过挂载根目录运行容器
> 如果你在一个多用户共享的生产系统上配置切勿随意将普通用户加入此组此时更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
建立 `docker`

View File

@@ -113,7 +113,12 @@ $ sudo systemctl start docker
### 3.2.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
> **安全警告`docker` 用户组等同于 `root` 权限**
>
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐但这也意味着该用户可以轻易获取主机的最高 root 权限例如通过挂载根目录运行容器
> 如果你在一个多用户共享的生产系统上配置切勿随意将普通用户加入此组此时更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
建立 `docker`

View File

@@ -121,7 +121,12 @@ $ sudo systemctl start docker
### 3.3.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
> **安全警告`docker` 用户组等同于 `root` 权限**
>
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐但这也意味着该用户可以轻易获取主机的最高 root 权限例如通过挂载根目录运行容器
> 如果你在一个多用户共享的生产系统上配置切勿随意将普通用户加入此组此时更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
建立 `docker`

View File

@@ -126,7 +126,12 @@ $ sudo systemctl start docker
### 3.4.6 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
> **安全警告`docker` 用户组等同于 `root` 权限**
>
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐但这也意味着该用户可以轻易获取主机的最高 root 权限例如通过挂载根目录运行容器
> 如果你在一个多用户共享的生产系统上配置切勿随意将普通用户加入此组此时更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
建立 `docker`

View File

@@ -140,7 +140,12 @@ $ sudo systemctl start docker
### 3.5.5 建立 docker 用户组
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
默认情况下`docker` 命令会使用 [Unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) 与 Docker 引擎通讯。而只有 `root` 用户和 `docker` 组的用户才可以访问 Docker 引擎的 Unix socket。出于安全考虑一般 Linux 系统上不会直接使用 `root` 用户。因此,更好做法是将需要使用 `docker` 的用户加入 `docker` 用户组。
> **安全警告`docker` 用户组等同于 `root` 权限**
>
> 将用户加入 `docker` 组免去了每次执行 `docker` 命令时输入 `sudo` 的繁琐但这也意味着该用户可以轻易获取主机的最高 root 权限例如通过挂载根目录运行容器
> 如果你在一个多用户共享的生产系统上配置切勿随意将普通用户加入此组此时更安全的替代方案是使用官方提供的 **[Rootless 模式 (Rootless mode)](https://docs.docker.com/engine/security/rootless/)**,它允许在没有任何 root 权限的情况下运行 Docker 守护进程和容器。
建立 `docker`

View File

@@ -1,16 +1,12 @@
## 3.6 Linux 离线安装
\[TOC]
生产环境中一般都是没有公网资源的本文介绍如何在生产服务器上离线部署 `Docker`
括号内的字母表示该操作需要在哪些服务器上执行
![Docker-offile-install-top](../_images/image-20200412202617411.png)
### 3.6.1 概述
### 3.6.2 CentOS/Rocky/AlmaLinux 离线安装 Docker
### 3.6.1 CentOS/Rocky/AlmaLinux 离线安装 Docker
在无法连接外网的安全环境中离线安装是唯一的选择本节介绍如何在 RHEL 系发行版中进行离线安装
@@ -18,7 +14,7 @@
#### YUM 本地文件安装 (推荐)
推荐这种方式是因为在生产环境一般会选定某个指定的文档软件版本使用
推荐这种方式是因为在生产环境一般会选定某个指定的文档软件版本使用
##### 查询可用的软件版本

View File

@@ -2,7 +2,7 @@
### 3.7.1 系统要求
[Docker Desktop for Mac](https://docs.docker.com/docker-for-mac/) 要求系统最低为 macOS Sonora 14.0 或更高版本,建议升级到最新版本的 macOS。
[Docker Desktop for Mac](https://docs.docker.com/docker-for-mac/) 要求系统最低为 macOS Sonoma 14.0 或更高版本,建议升级到最新版本的 macOS。
### 3.7.2 安装
@@ -47,7 +47,7 @@ $ brew install --cask docker
```bash
$ docker --version
Docker version 26.1.1, build 4cf5afa
Docker version 27.0.3, build 7d4bcd8
```
如果 `docker version``docker info` 都正常的话可以尝试运行一个 [Nginx 服务器](https://hub.docker.com/_/nginx/)

View File

@@ -17,7 +17,7 @@
下载好之后双击 `Docker Desktop Installer.exe` 开始安装
**使用** [**winget**](https://docs.microsoft.com/zh-cn/windows/package-manager/) **安装**
**使用**[**winget**](https://docs.microsoft.com/zh-cn/windows/package-manager/)**安装**
```powershell
$ winget install Docker.DockerDesktop

Binary file not shown.

View File

@@ -11,7 +11,7 @@ Docker 支持在多种平台上安装和使用,选择合适的安装方式是
| **Raspberry Pi** | 官方安装脚本 | 支持 ARM 架构 |
| **离线环境** | 二进制包安装 | 适用于无法联网的服务器 |
### 3.11.1 安装后验证
### 安装后验证
安装完成后运行以下命令验证 Docker 是否正常工作
@@ -20,8 +20,11 @@ $ docker version
$ docker run --rm hello-world
```
### 3.11.2 延伸阅读
### 延伸阅读
- [镜像加速器](3.9_mirror.md)解决国内拉取镜像慢的问题
- [开启实验特性](3.10_experimental.md)使用最新功能
- [Docker Hub](../06_repository/6.1_dockerhub.md)官方镜像仓库
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -171,9 +171,6 @@ root@e7009c6ce357:/# exit
```bash
$ sudo systemctl restart docker # Linux
## 或在 Docker Desktop 中重启
## 或在 Docker Desktop 中重启
```
详见[镜像加速器](../03_install/3.9_mirror.md)章节

View File

@@ -204,11 +204,10 @@ ubuntu latest ca2b0f26964c # 同一个镜像
$ docker rmi ubuntu:24.04
Untagged: ubuntu:24.04
## 只是移除标签,镜像仍存在(因为还有 ubuntu:latest 指向它)
```
当同一个镜像有多个标签时`docker rmi` 只是删除指定的标签不会删除镜像本身
```
#### 原因三被其他镜像依赖 (中间层)
```bash

View File

@@ -120,9 +120,7 @@ docker run --name web2 -d -p 81:80 nginx:v2
至此我们第一次完成了定制镜像使用的是 `docker commit` 命令手动操作给旧的镜像添加了新的一层形成新的镜像对镜像多层存储应该有了更直观的感觉
### 4.4.1 概述
### 4.4.2 慎用 `docker commit`
### 4.4.1 慎用 `docker commit`
使用 `docker commit` 命令虽然可以比较直观的帮助理解镜像分层存储的概念但是实际环境中并不会这样使用

View File

@@ -6,7 +6,7 @@ Dockerfile 是一个文本文件,其内包含了一条条的 **指令 (Instruc
### 4.5.1 使用 docker init 快速创建 (推荐)
Docker 提供了 `docker init` 命令可以根据项目类型自动生成 Dockerfiledockerignore compose.yaml 文件
Docker 提供了 `docker init` 命令可以根据项目类型自动生成 Dockerfile.dockerignore compose.yaml 文件
```bash
$ docker init

View File

@@ -15,3 +15,8 @@ Docker 运行容器前需要本地存在对应的镜像,如果本地不存在
* [使用 Dockerfile 定制镜像](4.5_build.md)
* [其它制作镜像的方式](4.6_other.md)
* [镜像的实现原理](4.7_internal.md)
> **版本提示镜像存储后端的变迁**
>
> Docker Engine v29 及后续版本中Docker 全新安装默认启用了 **containerd image store**替代了传统的 classic store这一底层架构级别的变迁意味着 Docker 解锁了对 OCI Image Index Attestations 例如原生的 provenance 来源证明与 SBOM 软件物料清单的全量本地支持
> 读者在执行类似 `docker buildx build --provenance=mode=min --sbom=true` 甚至使用后续审查工具 `docker buildx imagetools inspect`其元数据能够与镜像数据一并完好地管理于本地存储系统中为供应链安全验证补齐了最后一块拼图

View File

@@ -1,21 +1,13 @@
## 本章小结
本章介绍了 Docker 镜像的获取列出删除以及构建方式
| 操作 | 命令 |
|------|------|
| 拉取镜像 | `docker pull 镜像名:标签` |
| 拉取所有标签 | `docker pull -a 镜像名` |
| 指定平台 | `docker pull --platform linux/amd64 镜像名` |
| 用摘要拉取 | `docker pull 镜像名@sha256:...` |
### 4.8.1 延伸阅读
- [列出镜像](4.2_list.md)查看本地镜像
- [删除镜像](4.3_rm.md)清理本地镜像
- [镜像加速器](../03_install/3.9_mirror.md)加速镜像下载
- [Docker Hub](../06_repository/6.1_dockerhub.md)官方镜像仓库
| 操作 | 命令 |
|------|------|
| 列出所有镜像 | `docker images` |
| 按仓库名过滤 | `docker images nginx` |
| 列出虚悬镜像 | `docker images -f dangling=true` |
@@ -23,24 +15,22 @@
| 显示摘要 | `docker images --digests` |
| 自定义格式 | `docker images --format "..."` |
| 查看空间占用 | `docker system df` |
### 4.8.2 延伸阅读
- [获取镜像](4.1_pull.md) Registry 拉取镜像
- [删除镜像](4.3_rm.md)清理本地镜像
- [镜像](../02_basic_concept/2.1_image.md)理解镜像概念
| 操作 | 命令 |
|------|------|
| 删除指定镜像 | `docker rmi 镜像名:标签` |
| 强制删除 | `docker rmi -f 镜像名` |
| 删除虚悬镜像 | `docker image prune` |
| 删除未使用镜像 | `docker image prune -a` |
| 批量删除 | `docker rmi $(docker images -q -f ...)` |
| 查看空间占用 | `docker system df` |
### 4.8.3 延伸阅读
### 延伸阅读
- [获取镜像](4.1_pull.md) Registry 拉取镜像
- [列出镜像](4.2_list.md)查看和过滤镜像
- [删除镜像](4.3_rm.md)清理本地镜像
- [镜像加速器](../03_install/3.9_mirror.md)加速镜像下载
- [Docker Hub](../06_repository/6.1_dockerhub.md)官方镜像仓库
- [镜像](../02_basic_concept/2.1_image.md)理解镜像概念
- [删除容器](../05_container/5.6_rm.md)清理容器
- [数据卷](../08_data/8.1_volume.md)清理数据卷
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -1,55 +1,33 @@
## 本章小结
本章介绍了 Docker 容器的启动停止进入和删除等核心操作
| 操作 | 命令 | 说明 |
|------|------|------|
| 新建并运行 | `docker run` | 最常用的启动方式 |
| 交互式启动 | `docker run -it` | 用于调试或临时操作 |
| 后台运行 | `docker run -d` | 用于服务类应用 |
| 启动已停止的容器 | `docker start` | 重用已有容器 |
| 优雅停止 | `docker stop` | SIGTERM超时后 SIGKILL |
| 强制停止 | `docker kill` | 直接 SIGKILL |
| 重启 | `docker restart` | 停止后立即启动 |
| 停止全部 | `docker stop $(docker ps -q)` | 停止所有运行中容器 |
| 进入容器调试 | `docker exec -it 容器名 bash` | 推荐方式 |
| 执行单条命令 | `docker exec 容器名 命令` | 不进入交互模式 |
| 查看主进程输出 | `docker attach 容器名` | 慎用退出可能停止容器 |
| 删除已停止容器 | `docker rm 容器名` | 需先停止 |
| 强制删除运行中容器 | `docker rm -f 容器名` | 直接删除 |
| 删除容器及匿名卷 | `docker rm -v 容器名` | 同时清理匿名卷 |
| 清理所有已停止容器 | `docker container prune` | 批量清理 |
### 5.7.1 延伸阅读
### 延伸阅读
- [后台运行](5.2_daemon.md)理解 `-d` 参数和容器生命周期
- [进入容器](5.4_attach_exec.md)操作运行中的容器
- [网络配置](../09_network/README.md)理解端口映射的原理
- [数据管理](../08_data/README.md)数据持久化方案
| 操作 | 命令 | 说明 |
|------|------|------|
| 优雅停止 | `docker stop` | SIGTERM超时后 SIGKILL |
| 强制停止 | `docker kill` | 直接 SIGKILL |
| 重新启动 | `docker start` | 启动已停止的容器 |
| 重启 | `docker restart` | 停止后立即启动 |
| 停止全部 | `docker stop $(docker ps -q)` | 停止所有运行中容器 |
### 5.7.2 延伸阅读
- [启动容器](../05_container/5.1_run.md)容器启动详解
- [删除容器](5.6_rm.md)清理容器
- [容器日志](5.2_daemon.md)排查停止原因
| 需求 | 推荐命令 |
|------|---------|
| 进入容器调试 | `docker exec -it 容器名 bash` |
| 执行单条命令 | `docker exec 容器名 命令` |
| 查看主进程输出 | `docker attach 容器名` (慎用)|
### 5.7.3 延伸阅读
- [后台运行](5.2_daemon.md)理解容器主进程
- [查看容器](5.1_run.md)列出和过滤容器
- [容器日志](5.2_daemon.md)查看容器输出
| 操作 | 命令 |
|------|------|
| 删除已停止容器 | `docker rm 容器名` |
| 强制删除运行中容器 | `docker rm -f 容器名` |
| 删除容器及匿名卷 | `docker rm -v 容器名` |
| 清理所有已停止容器 | `docker container prune` |
| 删除所有容器 | `docker rm -f $(docker ps -aq)` |
### 5.7.4 延伸阅读
- [终止容器](5.3_stop.md)优雅停止容器
- [删除镜像](../04_image/4.3_rm.md)清理镜像
- [数据卷](../08_data/8.1_volume.md)数据卷管理
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -45,7 +45,8 @@ $ docker pull nginx:alpine
```bash
$ docker login
## 输入用户名和密码
## 默认情况下,不带其它参数进行 docker login 会自动走 Device Code Web Flow (浏览器认证)
## 若在非交互 CI 环境中,推荐结合 --username 与 --password-stdin 参数使用
...
```
@@ -76,10 +77,18 @@ $ docker push username/myapp:v1
| **免费账户** (已登录) | 6 小时 200 次请求 |
| **Pro/Team 账户** | 无限制 |
> **提示**如果在 CI/CD 环境中遇到 `toomanyrequests` 错误建议
> 1. CI 中配置 `docker login`
> 2. 使用国内镜像加速器
> 3. 搭建私有仓库代理
#### 滥用限流
除了上述针对特定账号拉取镜像数量的 Pull Rate Limit 之外Docker Hub 对所有用户包含已认证及付费用户还实施了 **滥用保护限流 (Abuse Rate Limiting)**它是根据网络出口 IP (IPv4 IPv6 /64 子网) 计算整体请求频率阈值动态触发通常为每分钟数千级别请求
**两类的差异与排查方法**
- **Pull Rate Limit**针对拉取量达到上限报错返回 `429 Too Many Requests`并且 HTTP 返回体/CLI 错误提示中会带有明确的 `toomanyrequests: You have reached your pull rate limit` 提示常附有账户升级链接
- **Abuse Rate Limit**防范接口频率打击报错仅返回简化的 `429 Too Many Requests`这一限流不分付费与否常发生在多终端共享出口 IP的企业局域网或者第三方云 CI 服务 GitHub Actions 即使你已正常配置 `docker login` 也依旧可能触发
> **提示**如果在 CI/CD 等环境遇到 429 错误建议
> 1. 先甄别具体是哪类限流普通的 pull rate limit 只要在 CI 中配置 `docker login` (并使用有效账号) 就能解除匿名限制
> 2. 如果是 Abuse 频控导致应考虑搭建私有仓库作为拉取缓存代理 (Registry pull-through cache)避免频繁直接请求官方 Hub
> 3. 使用国内镜像加速器
---
@@ -94,13 +103,13 @@ $ docker push username/myapp:v1
#### 2. 使用 Access Token
不要在脚本或 CI/CD 中直接使用登录密码
> ** 警告**绝不要在脚本或 CI/CD 系统中直接使用 `-p` 参数传递密码或 Token (类似 `docker login -p xxx`)这会导致凭证直接暴露在系统的命令历史进程列表和终端输出中
1. Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token
2. 使用 Token 作为密码登录
1. Docker Hub -> Account Settings -> Security -> Access Tokens 创建 Token (PAT)
2. Token 通过标准输入 (stdin) 安全传递给 Docker:
```bash
$ docker login -u username -p dckr_pat_xxxxxxx
$ echo "dckr_pat_xxxxxxx" | docker login --username username --password-stdin
```
#### 3. 关注镜像漏洞

Binary file not shown.

Binary file not shown.

View File

@@ -5,3 +5,10 @@
一个容易混淆的概念是注册服务器 (`Registry`)实际上注册服务器是管理仓库的具体服务器每个服务器上可以有多个仓库而每个仓库下面有多个镜像从这方面来说仓库可以被认为是一个具体的项目或目录例如对于仓库地址 `docker.io/ubuntu` 来说`docker.io` 是注册服务器地址`ubuntu` 是仓库名
大部分时候并不需要严格区分这两者的概念
## 本章内容
* [Docker Hub](6.1_dockerhub.md)
* [私有仓库](6.2_registry.md)
* [私有仓库高级配置](6.3_registry_auth.md)
* [Nexus 3](6.4_nexus3_registry.md)

View File

@@ -1,15 +1,18 @@
## 本章小结
本章介绍了 Docker Hub 的使用私有仓库的搭建以及 Nexus 3 等企业级方案
| 功能 | 说明 |
|------|------|
| **官方镜像** | 优先使用的基础镜像 |
| **拉取限制** | 匿名 100/6h登录 200/6h |
| **拉取限制** | 匿名 100 /6h登录 200 /6h |
| **安全** | 推荐开启 2FA 并使用 Access Token |
| **自动化** | 支持 Webhooks 和自动构建 |
### 6.5.1 概述
### 6.5.2 延伸阅读
### 延伸阅读
- [私有仓库](6.2_registry.md)搭建自己的 Registry
- [镜像加速器](../03_install/3.9_mirror.md)加速下载
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -1,7 +1,36 @@
## 7.16 参考文档
* `Dockerfile` 官方文档https://docs.docker.com/engine/reference/builder/
### 官方文档
* `Dockerfile` 最佳实践文档https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
* `Dockerfile` 官方参考手册https://docs.docker.com/engine/reference/builder/
* `Docker` 官方镜像 `Dockerfile`https://github.com/docker-library/docs
* `Dockerfile` 最佳实践指南https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
* `Docker` 官方镜像 `Dockerfile` https://github.com/docker-library/docs
### 常用指令总结
Dockerfile 中的常用指令包括
- **FROM**: 指定基础镜像必须是第一条指令
- **RUN**: 在镜像中执行命令用于安装软件包等
- **WORKDIR**: 设置工作目录
- **COPY/ADD**: 复制文件到镜像中
- **EXPOSE**: 声明容器监听的端口
- **ENV**: 设置环境变量
- **ENTRYPOINT**: 容器启动时的入口点
- **CMD**: 容器默认执行的命令
### 最佳实践建议
1. 使用具体的基础镜像版本标签而非 latest
2. 最小化镜像层数合并 RUN 指令
3. 使用 .dockerignore 文件排除不必要的文件
4. 安装必要的软件包后清理缓存
5. 使用多阶段构建减小最终镜像体积
6. 避免以 root 身份运行容器应用
### 相关资源
- Docker 官方镜像库https://hub.docker.com/
- Docker 镜像构建最佳实践https://docs.docker.com/build/building/best-practices/

View File

@@ -118,7 +118,7 @@ go/helloworld 2 f7cf3465432c 22 seconds ago 6.47MB
go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
```
## 7.17 使用多阶段构建
### 7.17.3 使用多阶段构建
为解决以上问题Docker v17.05 开始支持多阶段构建 (`multistage builds`)使用多阶段构建我们就可以很容易解决前面提到的问题并且只需要编写一个 `Dockerfile`
@@ -167,7 +167,7 @@ go/helloworld 1 f55d3e16affc 2 minutes ago 295MB
很明显使用多阶段构建的镜像体积小同时也完美解决了上边提到的问题
### 7.17.1 只构建某一阶段的镜像
### 7.17.4 只构建某一阶段的镜像
我们可以使用 `as` 来为某一阶段命名例如
@@ -181,7 +181,7 @@ FROM golang:alpine as builder
$ docker build --target builder -t username/imagename:tag .
```
### 7.17.2 构建时从其他镜像复制文件
### 7.17.5 构建时从其他镜像复制文件
上面例子中我们使用 `COPY --from=0 /go/src/github.com/go/helloworld/app .` 从上一阶段的镜像中复制文件我们也可以复制任意镜像中的文件

View File

@@ -268,3 +268,7 @@ COPY . .
```
---
> **🔥 踩坑实录**
>
> 某公司在优化 Node.js 应用的 Docker 镜像时发现构建出来的镜像体积超过了 2GB远远超过生产部署的需求排查发现Dockerfile 中使用了 `COPY . .` 把整个构建上下文复制进镜像导致 `node_modules/``.git/` 目录和大量测试数据全部被打包进镜像最初他们没有创建 `.dockerignore` 文件默认会复制所有文件解决方案是添加一个 `.dockerignore` 文件排除这些不必要的目录使镜像缩小到了 200MB这个教训深刻地说明了`.dockerignore` `.gitignore` 一样重要应该在项目初始化时就创建而不是等到出现问题时才想起来建议的标准做法是先复制 `package.json` `package-lock.json` 安装依赖再复制应用代码同时在 `.dockerignore` 中明确列出 `node_modules``.git`test 目录等

View File

@@ -103,7 +103,7 @@ VOLUME /data
RUN echo "hello" > /data/test.txt
```
**原因**VOLUME 指令之后Docker 将该目录视为外部挂载点不再记录对它的修改
**原因**在构建过程中VOLUME 指令会为该目录创建一个临时的匿名卷后续 RUN 指令对该目录的写入实际发生在这个临时卷中而非镜像层当该 RUN 指令结束后临时卷被丢弃因此写入的内容不会保存到最终镜像中注意这与容器运行时创建的匿名卷是不同的运行时创建的卷会在容器生命周期内持续存在
#### 正确做法

View File

@@ -2,7 +2,7 @@
## 什么是 Dockerfile
Dockerfile 是一个文本文件包含了一条条的 **指令 (Instruction)**每一条指令构建一层therefore 每一条指令的内容就是描述该层应当如何构建
Dockerfile 是一个文本文件包含了一条条的 **指令 (Instruction)**每一条指令构建一层因此每一条指令的内容就是描述该层应当如何构建
[第四章](../04_image/README.md)我们通过 `docker commit` 学习了镜像的构成但是手动 `commit` 只能作为临时修补并不适合作为生产环境镜像的构建方式
@@ -21,6 +21,7 @@ Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像
本章将详细讲解 Dockerfile 中的各个指令
* [RUN 执行命令](7.1_run.md)
* [COPY 复制文件](7.2_copy.md)
* [ADD 更高级的复制文件](7.3_add.md)
* [CMD 容器启动命令](7.4_cmd.md)
@@ -35,7 +36,15 @@ Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像
* [ONBUILD 为他人作嫁衣裳](7.13_onbuild.md)
* [LABEL 为镜像添加元数据](7.14_label.md)
* [SHELL 指令](7.15_shell.md)
* [RUN 执行命令](7.1_run.md)
### 高级特性
本章还将介绍 Dockerfile 的高级特性
* [多阶段构建](7.17_multistage_builds.md)
* [多阶段构建实战Laravel 应用](7.18_multistage_builds_laravel.md)
### 参考与最佳实践
此外我们还将介绍 Dockerfile 的最佳实践和常见问题

View File

@@ -1,208 +1,33 @@
## 本章小结
| 要点 | 说明 |
|------|------|
| **作用** | 设置后续指令的工作目录 |
| **语法** | `WORKDIR /path` |
| **自动创建** | 目录不存在会自动创建 |
| **持久性** | 影响后续所有指令直到下次 WORKDIR |
| **不要用** | `RUN cd /path` (无效)|
本章详细介绍了 Dockerfile 的所有核心指令以下是各指令要点的速查表
### 7.19.1 延伸阅读
| 指令 | 作用 | 关键要点 |
|------|------|---------|
| **FROM** | 指定基础镜像 | 必须是第一条指令 |
| **RUN** | 在新层执行命令 | 合并命令清理缓存以减小体积 |
| **COPY** | 复制文件 | 优先使用支持 `--from` |
| **ADD** | 更高级的复制 | 自动解压 tar不推荐用于下载 |
| **CMD** | 容器启动默认命令 | 可被 `docker run` 参数覆盖 |
| **ENTRYPOINT** | 容器入口点 | 固定启动命令CMD 作为默认参数 |
| **ENV** | 设置环境变量 | 构建时 + 运行时均生效 |
| **ARG** | 构建参数 | 仅构建时生效FROM 后需重新声明 |
| **VOLUME** | 定义匿名卷 | VOLUME 之后的修改会丢失 |
| **EXPOSE** | 声明端口 | 仅文档作用不自动映射 |
| **WORKDIR** | 指定工作目录 | 替代 `RUN cd`目录不存在会自动创建 |
| **USER** | 指定运行用户 | 用户必须已存在推荐 gosu |
| **HEALTHCHECK** | 健康检查 | 支持 starting/healthy/unhealthy 状态 |
| **ONBUILD** | 延迟执行指令 | 只继承一次不可级联 |
| **LABEL** | 添加元数据 | 推荐 OCI 标准标签替代 MAINTAINER |
| **SHELL** | 更改默认 shell | 推荐 `["/bin/bash", "-o", "pipefail", "-c"]` |
- [COPY 复制文件](7.2_copy.md)文件复制
- [RUN 执行命令](../04_image/4.5_build.md)执行构建命令
- [最佳实践](../appendix/best_practices.md)Dockerfile 编写指南
### 延伸阅读
| 要点 | 说明 |
|------|------|
| **作用** | 切换后续指令的执行用户 |
| **语法** | `USER username` `USER UID:GID` |
| **前提** | 用户必须已存在 |
| **运行时覆盖** | `docker run -u` |
| **切换工具** | 使用 gosu不用 su/sudo |
### 7.19.2 延伸阅读
- [安全](../18_security/README.md)容器安全实践
- [ENTRYPOINT](7.5_entrypoint.md)入口脚本中的用户切换
- [最佳实践](../appendix/best_practices.md)Dockerfile 安全
| 要点 | 说明 |
|------|------|
| **作用** | 检测容器应用是否真实可用 |
| **命令** | `HEALTHCHECK [选项] CMD command` |
| **状态** | starting, healthy, unhealthy |
| **Compose** | 支持 `condition: service_healthy` 依赖 |
| **注意** | 避免副作用节省资源 |
### 7.19.3 延伸阅读
- [CMD 容器启动命令](7.4_cmd.md)启动主进程
- [Compose 模板文件](../11_compose/11.5_compose_file.md)Compose 中的健康检查
- [Docker 调试](../appendix/debug.md)容器排障
| 要点 | 说明 |
|------|------|
| **作用** | 定义在子镜像构建时执行的指令 |
| **语法** | `ONBUILD INSTRUCTION` |
| **适用** | 基础架构镜像 (Node, Python, Go )|
| **限制** | 只继承一次不可级联 |
| **规范** | 建议使用 `-onbuild` 标签后缀 |
### 7.19.4 延伸阅读
- [COPY 指令](7.2_copy.md)文件复制
- [Dockerfile 最佳实践](../appendix/best_practices.md)基础镜像设计
| 要点 | 说明 |
|------|------|
| **作用** | 添加 key-value 元数据 |
| **语法** | `LABEL k=v k=v ...` |
| **规范** | 推荐使用 OCI 标准标签 |
| **弃用** | 不要再使用 `MAINTAINER` |
| **查看** | `docker inspect` |
### 7.19.5 延伸阅读
- [OCI 标签规范](https://github.com/opencontainers/image-spec/blob/main/annotations.md)
- [Dockerfile 最佳实践](../appendix/best_practices.md)
| 要点 | 说明 |
|------|------|
| **作用** | 更改 RUN/CMD/ENTRYPOINT 的默认 shell |
| **Linux 默认** | `["/bin/sh", "-c"]` |
| **Windows 默认** | `["cmd", "/S", "/C"]` |
| **推荐用法** | `SHELL ["/bin/bash", "-o", "pipefail", "-c"]` |
| **影响范围** | 后续所有使用 shell 格式的指令 |
### 7.19.6 延伸阅读
- [RUN 指令](../04_image/4.5_build.md)执行命令
- [Dockerfile 最佳实践](../appendix/best_practices.md)错误处理与调试
| 要点 | 说明 |
|------|------|
| **作用** | 在新层执行命令 |
| **原则** | 合并命令清理缓存 |
| **格式** | Shell (常用) vs Exec |
| **陷阱** | `cd` 不持久环境变量不持久 |
| **进阶** | 使用 Cache Mount 加速构建 |
### 7.19.7 延伸阅读
- [CMD 容器启动命令](7.4_cmd.md)容器启动时的命令
- [WORKDIR 指定工作目录](7.10_workdir.md)改变目录
- [Dockerfile 最佳实践](../appendix/best_practices.md)
| 操作 | 示例 |
|------|------|
| 复制文件 | `COPY app.js /app/` |
| 复制多个文件 | `COPY *.json /app/` |
| 复制目录内容 | `COPY src/ /app/src/` |
| 修改所有者 | `COPY --chown=node:node . /app/` |
| 从构建阶段复制 | `COPY --from=builder /app/dist ./` |
### 7.19.8 延伸阅读
- [ADD 指令](7.3_add.md)复制和解压
- [WORKDIR 指令](7.10_workdir.md)设置工作目录
- [使用 Dockerfile 定制镜像](../04_image/4.5_build.md)Dockerfile 入门
- [多阶段构建](7.17_multistage_builds.md)优化镜像大小
- [最佳实践](../appendix/best_practices.md)Dockerfile 编写指南
- [Dockerfile 最佳实践](../appendix/best_practices.md)编写指南
- [安全](../18_security/README.md)容器安全实践
- [Compose 模板文件](../11_compose/11.5_compose_file.md)Compose 中的配置
---
| 场景 | 推荐指令 |
|------|---------|
| 复制普通文件 | `COPY` |
| 复制目录 | `COPY` |
| 自动解压 tar | `ADD` |
| URL 下载 | `RUN curl` |
| 保持 tar 不解压 | `COPY` |
### 7.19.9 延伸阅读
- [COPY 复制文件](7.2_copy.md)基本复制操作
- [多阶段构建](7.17_multistage_builds.md)减少镜像体积
- [最佳实践](../appendix/best_practices.md)Dockerfile 编写指南
| 要点 | 说明 |
|------|------|
| **作用** | 指定容器启动时的默认命令 |
| **推荐格式** | exec 格式 `CMD [“程序”, “参数”]` |
| **覆盖方式** | `docker run image 新命令` |
| ** ENTRYPOINT** | CMD 作为 ENTRYPOINT 的默认参数 |
| **核心原则** | 应用必须在前台运行 |
### 7.19.10 延伸阅读
- [ENTRYPOINT 入口点](7.5_entrypoint.md)固定的启动命令
- [后台运行](../05_container/5.2_daemon.md)容器前台/后台概念
- [最佳实践](../appendix/best_practices.md)Dockerfile 编写指南
| ENTRYPOINT | CMD | 适用场景 |
|------------|-----|---------|
| | | 镜像作为固定命令使用 |
| | | 简单的默认命令 |
| | | **推荐**固定命令 + 可配置参数 |
### 7.19.11 延伸阅读
- [CMD 容器启动命令](7.4_cmd.md)默认命令
- [最佳实践](../appendix/best_practices.md)启动命令设计
- [后台运行](../05_container/5.2_daemon.md)前台/后台概念
| 要点 | 说明 |
|------|------|
| **语法** | `ENV KEY=value` |
| **作用范围** | 构建时 + 运行时 |
| **覆盖方式** | `docker run -e KEY=value` |
| ** ARG** | ARG 仅构建时ENV 持久化到运行时 |
| **安全** | 不要存储敏感信息 |
### 7.19.12 延伸阅读
- [ARG 构建参数](7.7_arg.md)构建时变量
- [Compose 环境变量](../11_compose/11.5_compose_file.md)Compose 中的环境变量
- [最佳实践](../appendix/best_practices.md)Dockerfile 编写指南
| 要点 | 说明 |
|------|------|
| **作用** | 定义构建时变量 |
| **语法** | `ARG NAME=value` |
| **覆盖** | `docker build --build-arg NAME=value` |
| **作用域** | FROM 之后需要重新声明 |
| **vs ENV** | ARG 仅构建时ENV 构建+运行时 |
| **安全** | 不要存储敏感信息 |
### 7.19.13 延伸阅读
- [ENV 设置环境变量](7.6_env.md)运行时环境变量
- [FROM 指令](../04_image/4.5_build.md)基础镜像指定
- [多阶段构建](7.17_multistage_builds.md)复杂构建场景
| 要点 | 说明 |
|------|------|
| **作用** | 创建挂载点标记为外部卷 |
| **语法** | `VOLUME /path` |
| **默认行为** | 自动创建匿名卷 |
| **覆盖方式** | `docker run -v name:/path` |
| **注意** | VOLUME 之后的修改会丢失 |
### 7.19.14 延伸阅读
- [数据卷](../08_data/8.1_volume.md)卷的管理和使用
- [挂载主机目录](../08_data/8.2_bind-mounts.md)Bind Mount
- [Compose 数据管理](../11_compose/11.5_compose_file.md)Compose 中的卷配置
| 要点 | 说明 |
|------|------|
| **作用** | 声明容器提供服务的端口 (文档)|
| **不会** | 自动映射端口或开放外部访问 |
| **配合** | `docker run -P` 自动映射 |
| **外部访问** | 需要 `-p 宿主机端口:容器端口` |
| **语法** | `EXPOSE 80` `EXPOSE 80/tcp` |
### 7.19.15 延伸阅读
- [网络配置](../09_network/README.md)Docker 网络详解
- [端口映射](../09_network/9.5_port_mapping.md)-p 参数详解
- [Compose 端口](../11_compose/11.5_compose_file.md)Compose 中的端口配置
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -138,8 +138,11 @@ $ docker run -d \
| 特性 | --mount | -v |
|------|---------|-----|
| 语法 | 键值对更清晰 | 冒号分隔更简洁 |
| 自动创建卷 | source 不存在会报错 | 自动创建 |
| 推荐程度 | 推荐 (更明确)| 常用 (更简洁)|
| **数据卷 (Volume)** 挂载行为 | 卷不存在会自动创建 `-v` 结果一致 | 卷不存在会自动创建 |
| **绑定挂载 (Bind Mount)** 行为 | **宿主机路径不存在会报错**不会自动创建 | 宿主机路径不存在会 **自动创建为目录** |
| 推荐程度 | 推荐 (更明确安全避免误创建)| 常用 (更简洁)|
> **提示**官方更推荐使用 `--mount`除了语法格式可读性更好之外最重要的行为差异发生在 **绑定挂载 (Bind Mount)** 如果挂载的宿主机源路径尚未存在`-v` 会擅自将其自动创建为一个空目录 `--mount` 则会严格检查并直接报错这能有效避免因路径拼写错误而在宿主机上留下垃圾目录以及导致的容器访问空目录问题而对于本节的 **数据卷 (Volume)** 挂载而言两者在目标指定的卷不存在时皆会自动创建卷产生的结果是 **完全一致**
#### 只读挂载

View File

@@ -74,9 +74,11 @@ $ docker run -d \
| 特性 | --mount | -v |
|------|---------|-----|
| 语法 | 键值对更清晰 | 冒号分隔更简洁 |
| 路径不存在时 | 报错 | 自动创建目录 |
| 路径不存在时 | 直接报错 (Fail Fast) | 静默自动创建 **目录** |
| 推荐程度 | 推荐 | 常用 |
> ** 陷阱**如果不小心挂载了一个不存在的宿主机路径使用 `-v` 会在宿主机上静默创建一个 **空目录**即使你本来想挂载的是一个文件这常常会导致权限错误或应用无法正常读取这也正是为什么 Docker 官方更推荐使用 `--mount` 的原因它会遵循Fail Fast原则直接报错避免弄巧成拙
---
### 8.2.4 使用场景

View File

@@ -10,16 +10,20 @@
### 8.3.2 基本用法
```bash
$ docker run --tmpfs /run:rw,noexec,nosuid,size=64m nginx
```
也可以使用 `--mount` 语法
使用 `--mount` 语法推荐
```bash
$ docker run --mount type=tmpfs,destination=/run,tmpfs-size=67108864 nginx
$ docker run --mount type=tmpfs,destination=/run,tmpfs-size=67108864,tmpfs-mode=1770 nginx
```
也可以使用 `--tmpfs` 简写语法
```bash
$ docker run --tmpfs /run:size=64m nginx
```
> **注意**`--tmpfs` 支持的选项有限主要为 `size` `mode`如果需要更精细的控制 `noexec``nosuid`推荐使用 `--mount` 语法并通过 `tmpfs-mode` 参数设置权限
### 8.3.3 注意事项
- 容器停止后`tmpfs` 数据会丢失

View File

@@ -6,7 +6,8 @@
8-1 Docker 数据挂载类型示意图
这一章介绍如何在 Docker 内部以及容器之间管理数据在容器中管理数据主要有种方式
这一章介绍如何在 Docker 内部以及容器之间管理数据在容器中管理数据主要有以下几种方式
* [数据卷](8.1_volume.md)
* [挂载主机目录](8.2_bind-mounts.md)
* [tmpfs 挂载](8.3_tmpfs.md)

View File

@@ -1,18 +1,12 @@
## 本章小结
| 要点 | 说明 |
|------|------|
| **作用** | 将宿主机目录挂载到容器 |
| **语法** | `-v /宿主机:/容器` `--mount type=bind,...` |
| **只读** | 添加 `readonly` `:ro` |
| **适用场景** | 开发环境配置文件日志 |
| **vs Volume** | Bind 更灵活Volume 更适合生产 |
本章介绍了 Docker 的三种数据管理方式数据卷 (Volume)绑定挂载 (Bind Mount) tmpfs 挂载
### 8.4.1 延伸阅读
- [数据卷](8.1_volume.md)Docker 管理的持久化存储
- [tmpfs 挂载](8.3_tmpfs.md)内存临时存储
- [Compose 数据管理](../11_compose/11.5_compose_file.md)Compose 中的挂载配置
| 方式 | 特点 | 适用场景 |
|------|------|---------|
| **数据卷 (Volume)** | Docker 管理生命周期独立于容器 | 数据库应用数据推荐生产环境 |
| **绑定挂载 (Bind Mount)** | 挂载宿主机目录更灵活 | 开发环境配置文件日志 |
| **tmpfs 挂载** | 仅存储在内存中容器停止即消失 | 临时敏感数据高速缓存 |
| 操作 | 命令 |
|------|------|
@@ -23,8 +17,13 @@
| 清理未用 | `docker volume prune` |
| 挂载数据卷 | `-v name:/path` `--mount source=name,target=/path` |
### 8.4.2 延伸阅读
### 延伸阅读
- [数据卷](8.1_volume.md)Docker 管理的持久化存储
- [绑定挂载](8.2_bind-mounts.md)挂载宿主机目录
- [tmpfs 挂载](8.3_tmpfs.md)内存中的临时存储
- [存储驱动](../12_implementation/12.4_ufs.md)Docker 存储的底层原理
- [Compose 数据管理](../11_compose/11.5_compose_file.md)Compose 中的挂载配置
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -4,16 +4,16 @@ Docker 1.10.0 以后,内建了一个 DNS 服务器,使得容器可以直接
但是使用 Docker DNS 有个前提条件就是它只能在 **自定义网络** 中使用也就是说如果使用的是默认的 `bridge` 网络是无法使用 DNS 所以我们就需要自定义网络
### 9.2.1 容器的 DNS 机制
### 9.1.1 容器的 DNS 机制
Docker 容器的 DNS 配置有两种情况
1. **默认 Bridge 网络**继承宿主机的 DNS 配置 (`/etc/resolv.conf`)
2. **自定义网络** (推荐)使用 Docker 嵌入式 DNS 服务器 (Embedded DNS)支持通过 **容器名** 进行服务发现
2. **自定义网络**(推荐)使用 Docker 嵌入式 DNS 服务器 (Embedded DNS)支持通过 **容器名** 进行服务发现
---
### 9.2.2 嵌入式 DNS
### 9.1.2 嵌入式 DNS
这是 Docker 网络最强大的功能之一在自定义网络中容器可以通过 名字 找到彼此而不需要知道对方的 IP (因为 IP 可能会变)
@@ -38,7 +38,7 @@ Docker 守护进程在 `127.0.0.11` 运行了一个 DNS 服务器。容器内的
---
### 9.2.3 配置 DNS 参数
### 9.1.3 配置 DNS 参数
如果你需要手动配置容器的 DNS (例如使用内网 DNS 服务器)可以在 `docker run` 中使用以下参数
@@ -69,7 +69,7 @@ $ docker run -h myweb nginx
---
### 9.2.4 全局 DNS 配置
### 9.1.4 全局 DNS 配置
如果希望所有容器都使用特定的 DNS 服务器 (而不是继承宿主机)可以修改 `/etc/docker/daemon.json`
@@ -86,7 +86,7 @@ $ docker run -h myweb nginx
---
### 9.2.5 常见问题
### 9.1.5 常见问题
以下是使用容器 DNS 时常见的问题及解决方法

View File

@@ -2,7 +2,7 @@
在生产环境中推荐使用用户自定义网络代替默认的 bridge 网络自定义网络提供了更好的隔离性和服务发现能力
### 9.4.1 为什么要用自定义网络
### 9.3.1 为什么要用自定义网络
默认 bridge 网络存在以下局限而自定义网络可以很好地解决这些问题
@@ -12,7 +12,7 @@
| 所有容器在同一网络 | 更好的隔离性 |
| 需要 --link (已废弃)| 原生支持服务发现 |
### 9.4.2 创建自定义网络
### 9.3.2 创建自定义网络
使用 `docker network create` 命令可以创建自定义网络
@@ -26,7 +26,7 @@ $ docker network create mynet
$ docker network inspect mynet
```
### 9.4.3 使用自定义网络
### 9.3.3 使用自定义网络
启动容器时通过 `--network` 参数指定连接的网络
@@ -43,7 +43,7 @@ PING db (172.18.0.3): 56 data bytes
64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.083 ms
```
### 9.4.4 容器名 DNS 解析
### 9.3.4 容器名 DNS 解析
自定义网络自动提供 DNS 服务Docker 守护进程在 `127.0.0.11` 运行了一个嵌入式 DNS 服务器容器内的 DNS 请求会被转发到这里
@@ -58,7 +58,7 @@ flowchart LR
end
```
### 9.4.5 常用网络命令
### 9.3.5 常用网络命令
以下是 Docker 网络管理中常用的命令
@@ -91,3 +91,9 @@ $ docker network rm mynet
$ docker network prune
```
---
> **🔥 踩坑实录**
>
> 一个新手开发者通过 `docker-compose` 部署了两个容器化服务服务 A 和服务 B他在服务 A 的代码中尝试用 `localhost:3000` 访问服务 B结果始终连接超时这个错误非常隐蔽在本地单机开发时看不出问题因为他可能在同一个进程中测试排查时他错误地认为是防火墙或网络配置问题实际原因是每个容器都有独立的网络命名空间`localhost` 在容器内部只指向容器自己不是宿主机也不是其他容器正确的做法是使用 docker-compose 自动创建的服务名作为主机名`http://service-b:3000``docker-compose` 会自动在网络中注册服务名的 DNS这样容器间通信才能正确解析改动仅需一行代码问题随之消失

View File

@@ -2,7 +2,7 @@
容器之间的网络通信是 Docker 网络的核心功能之一本节介绍容器互联的几种方式
### 9.5.1 同一网络内的容器
### 9.4.1 同一网络内的容器
同一自定义网络内的容器可以直接通过容器名通信这是推荐的容器互联方式
@@ -21,7 +21,7 @@ $ docker run -d --name app --network app-net myapp
...
```
### 9.5.2 连接到多个网络
### 9.4.2 连接到多个网络
一个容器可以同时连接到多个网络这对于需要跨网络通信的中间件容器特别有用
@@ -39,7 +39,7 @@ $ docker network connect backend multi-net-container
$ docker inspect multi-net-container --format '{{json .NetworkSettings.Networks}}'
```
### 9.5.3 --link 已废弃
### 9.4.3 --link 已废弃
`--link` Docker 早期用于容器互联的方式**已经被废弃**不建议在新项目中使用请使用自定义网络替代

View File

@@ -2,7 +2,7 @@
容器运行在自己的隔离网络环境中 (通常是 Bridge 模式)为了让外部网络访问容器内的服务我们需要将容器的端口映射到宿主机的端口
### 9.6.1 为什么要映射端口
### 9.5.1 为什么要映射端口
容器的网络访问规则如下
@@ -21,7 +21,7 @@ flowchart TD
---
### 9.6.2 端口映射方式
### 9.5.2 端口映射方式
Docker 提供了多种方式来指定端口映射
@@ -66,7 +66,7 @@ abc123456 0.0.0.0:49153->80/tcp
---
### 9.6.3 查看端口映射
### 9.5.3 查看端口映射
可以使用以下命令查看容器的端口映射
@@ -92,7 +92,7 @@ abc123456 nginx 0.0.0.0:8080->80/tcp web
---
### 9.6.4 最佳实践与安全
### 9.5.4 最佳实践与安全
在配置端口映射时需要注意以下安全事项
@@ -127,7 +127,7 @@ $ docker run -d -p 53:53/udp dns-server
---
### 9.6.5 实现原理
### 9.5.5 实现原理
Docker 使用 `docker-proxy` 进程 (用户态) `iptables` DNAT 规则 (内核态) 来实现端口转发

View File

@@ -2,7 +2,7 @@
Docker 网络提供了天然的隔离能力不同网络之间的容器默认无法通信这是 Docker 网络安全的重要基础
### 9.7.1 网络隔离原理
### 9.6.1 网络隔离原理
不同网络之间默认隔离容器只能与同一网络中的容器直接通信
@@ -26,7 +26,7 @@ $ docker exec web ping db
ping: db: Name or service not known
```
### 9.7.2 安全优势
### 9.6.2 安全优势
这种隔离机制带来以下安全优势
@@ -37,7 +37,7 @@ ping: db: Name or service not known
| **多租户** | 不同租户的容器在不同网络中完全隔离 |
| **最小权限** | 容器只能访问必要的网络资源 |
### 9.7.3 跨网络通信
### 9.6.3 跨网络通信
如果确实需要某个容器跨网络通信可以将其同时连接到多个网络
@@ -52,7 +52,7 @@ $ docker network connect backend api
这种方式让你可以精确控制哪些容器可以跨网络通信遵循最小权限原则
### 9.7.4 典型网络架构
### 9.6.4 典型网络架构
一个典型的多层应用网络架构如下

View File

@@ -0,0 +1,709 @@
## 9.7 容器网络高级特性
深入探讨容器网络的核心机制Overlay 网络CNI 插件生态容器 DNS 解析网络策略等高级特性为生产级别的网络架构打下坚实基础
### 9.7.1 Overlay 网络原理与配置
Overlay 网络在现有网络基础上建立虚拟网络允许容器跨宿主机通信它是 Kubernetes Swarm 模式的基础
#### Overlay 网络工作原理
Overlay 网络通过隧道封装技术通常是 VXLAN将容器网络流量封装在宿主机物理网络的 UDP 数据包中传输
```
容器 A (192.168.0.2)
veth 对
br-net (网桥)
Docker 引擎 (VXLAN 封装)
物理网络 (172.16.0.0/24)
Docker 引擎 (VXLAN 解封装)
br-net (网桥)
veth 对
容器 B (192.168.0.3,不同宿主机)
```
#### 创建和使用 Overlay 网络
**Docker Swarm 模式下的 Overlay 网络**
```bash
# 初始化 Swarm创建集群
docker swarm init
# 创建 overlay 网络
docker network create --driver overlay \
--subnet 192.168.0.0/24 \
--opt com.docker.network.driver.mtu=1450 \
my-overlay-net
# 验证网络创建
docker network ls
docker network inspect my-overlay-net
# 在 Swarm 服务中使用 overlay 网络
docker service create --name web \
--network my-overlay-net \
--replicas 3 \
nginx:latest
# 验证服务跨节点通信
docker service ps web
```
**单机 Overlay 网络模拟Linux 容器**
```bash
# 创建自定义 overlay 网络
docker network create --driver overlay custom-overlay
# 创建两个容器
docker run -d --name container1 --network custom-overlay nginx:latest
docker run -d --name container2 --network custom-overlay nginx:latest
# 测试跨容器通信
docker exec container1 ping container2
docker exec container1 curl http://container2
# 检查网络配置
docker network inspect custom-overlay
```
#### Overlay 网络性能优化
```bash
# 调整 MTUMaximum Transmission Unit避免分片
# VXLAN 开销 50 字节,物理 MTU 1500建议设置为 1450
docker network create --driver overlay \
--opt com.docker.network.driver.mtu=1450 \
optimized-overlay
# 启用 IP 地址管理IPAM自定义
docker network create --driver overlay \
--subnet 10.0.9.0/24 \
--aux-address "my-router=10.0.9.2" \
my-custom-overlay
# 在 Compose 中使用 overlay 网络
version: '3.9'
services:
web:
image: nginx
networks:
- backend
db:
image: postgres
networks:
- backend
networks:
backend:
driver: overlay
driver_opts:
com.docker.network.driver.mtu: 1450
```
### 9.7.2 CNI 插件生态概览
容器网络接口CNI是容器编排平台尤其是 Kubernetes的标准化网络接口不同的 CNI 插件提供不同的网络能力
#### 主流 CNI 插件对比
**Calico - 基于 BGP 的网络**
Calico 使用 BGP 协议进行路由支持网络策略和 eBPF 加速
```yaml
# Kubernetes 中安装 Calico
apiVersion: v1
kind: ConfigMap
metadata:
name: calico-config
namespace: kube-system
data:
cni_network_config: |
{
"name": "k8s-pod-network",
"cniVersion": "0.4.0",
"plugins": [
{
"type": "calico",
"datastore_type": "kubernetes",
"mtu": 1450,
"ipam": {
"type": "calico-ipam"
}
},
{
"type": "portmap",
"snat": true,
"capabilities": {"portMappings": true}
}
]
}
```
**Flannel - 简单可靠的 Overlay**
Flannel 提供简单的 overlay 网络实现适合小到中等规模的集群
```bash
# 安装 Flannel
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 配置 Flannel 后端VXLAN、UDP、AWS VPC 等)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: kube-flannel-cfg
namespace: kube-flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}
EOF
```
**Cilium - eBPF 驱动的先进网络**
Cilium 使用 eBPF 在内核级别实现网络策略和可观测性性能优异
```bash
# 安装 Cilium
helm repo add cilium https://helm.cilium.io
helm install cilium cilium/cilium \
--namespace kube-system \
--set image.tag=v1.14.0 \
--set operator.replicas=1
# 启用 Hubble可观测性
helm upgrade cilium cilium/cilium \
--namespace kube-system \
--reuse-values \
--set hubble.enabled=true \
--set hubble.ui.enabled=true
```
**Weave - 跨主机网络通信**
Weave 提供简单的跨主机通信支持加密和多播
```bash
# Docker 中使用 Weave 网络
docker run -d --name weave \
--net=host \
--cap-add=NET_ADMIN \
--cap-add=SYS_PTRACE \
ghcr.io/weaveworks/weave:latest
# 连接到 Weave 网络
docker run -d --network weave --name web nginx:latest
```
**CNI 插件对比表**
| 特性 | Calico | Flannel | Cilium | Weave |
|------|--------|---------|--------|-------|
| 路由方式 | BGP | VXLAN/UDP | eBPF | VxLAN |
| 网络策略 | | | (L3-L7) | |
| 性能 | | | | |
| 可观测性 | | | | |
| 学习曲线 | | | | |
| 生产就绪 | | | | |
### 9.7.3 容器 DNS 解析机制
Docker 内置 DNS 服务器 DNS 解析涉及多个层面的配置
#### DNS 解析流程
```
容器应用 (dig www.example.com)
容器内 /etc/resolv.conf (127.0.0.11:53)
Docker 内嵌 DNS 服务器 (127.0.0.11)
用户自定义 DNS 或宿主机 /etc/resolv.conf
外部 DNS 服务器 (8.8.8.8 等)
DNS 响应 → 容器缓存 → 应用
```
#### 配置容器 DNS
**在运行时指定 DNS**
```bash
# 单个容器
docker run -d \
--dns 8.8.8.8 \
--dns 1.1.1.1 \
--dns-search example.com \
nginx:latest
# DNS 选项
docker run -d \
--dns-option ndots:2 \
--dns-option timeout:1 \
--dns-option attempts:3 \
nginx:latest
# 查看容器 DNS 配置
docker exec <container_id> cat /etc/resolv.conf
```
**Docker Compose DNS 配置**
```yaml
version: '3.9'
services:
web:
image: nginx
dns:
- 8.8.8.8
- 1.1.1.1
dns_search:
- example.com
- local
db:
image: postgres
networks:
- backend
hostname: postgres-db
networks:
backend:
driver: bridge
# 容器内 /etc/resolv.conf 将被自动配置
# search example.com local
# nameserver 8.8.8.8
# nameserver 1.1.1.1
```
**Docker 守护进程级别配置**
```json
{
"dns": ["8.8.8.8", "1.1.1.1"],
"dns-search": ["example.com"],
"insecure-registries": [],
"registry-mirrors": ["https://mirror.example.com"]
}
```
#### 自定义服务发现Service Discovery
**使用 Docker 内建 DNS 的服务发现**
```bash
# 创建自定义网络
docker network create mynet
# 运行服务
docker run -d --name web --network mynet nginx:latest
docker run -d --name db --network mynet postgres:latest
# 在其他容器中通过服务名访问
docker run -it --network mynet busybox sh
# ping web # 自动解析到 web 容器 IP
# ping db # 自动解析到 db 容器 IP
```
**Compose 服务名自动发现**
```yaml
version: '3.9'
services:
frontend:
image: nginx
depends_on:
- backend
environment:
BACKEND_URL: http://backend:8080
backend:
image: myapp
depends_on:
- database
database:
image: postgres
environment:
POSTGRES_DB: mydb
# frontend 容器可以直接访问 http://backend:8080
# backend 容器可以直接访问 postgres://database:5432
```
#### DNS 性能优化
```bash
# 检查 DNS 延迟
time docker exec <container> nslookup www.example.com
# 优化 DNS 解析
docker run -d \
--dns 127.0.0.1 \ # 使用本地缓存 DNS (Dnsmasq)
nginx:latest
# 在 Kubernetes 中优化
kubectl patch deployment -n kube-system coredns --patch '{
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "coredns",
"resources": {
"limits": {
"memory": "512Mi",
"cpu": "500m"
}
}
}
]
}
}
}
}'
```
### 9.7.4 网络策略NetworkPolicy实践
网络策略定义了容器间的流量控制规则是微服务架构中的安全基础
#### 基本网络策略
**默认拒绝所有入站流量的策略**
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
# 不指定 ingress 规则,表示拒绝所有入站流量
```
**允许特定来源的入站流量**
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
spec:
podSelector:
matchLabels:
tier: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
tier: frontend
ports:
- protocol: TCP
port: 8080
```
**允许出站流量到数据库**
```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-db
spec:
podSelector:
matchLabels:
tier: backend
policyTypes:
- Egress
egress:
# 允许到数据库的流量
- to:
- podSelector:
matchLabels:
tier: database
ports:
- protocol: TCP
port: 5432
# 允许 DNS 查询
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
# 允许到外部 API 的流量
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 169.254.169.254/32 # 阻止元数据服务
ports:
- protocol: TCP
port: 443
```
#### 微服务网络策略示例
```yaml
---
# 拒绝所有默认
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# Frontend 容器策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
- Egress
ingress:
# 允许来自 Ingress Controller 的流量
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
- podSelector:
matchLabels:
app: ingress-controller
ports:
- protocol: TCP
port: 3000
egress:
# 允许到 API 的流量
- to:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 8080
# 允许 DNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
---
# API 容器策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-api
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
# 允许到数据库的流量
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
# 允许 DNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
---
# 数据库容器策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-postgres
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 5432
```
#### 使用 Calico/Cilium 的高级网络策略
**L7 应用层策略 Cilium 支持**
```yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "api-gateway-policy"
spec:
description: "L7 policy for API gateway"
endpointSelector:
matchLabels:
app: api
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
# 允许 GET /api/users
- method: "GET"
path: "/api/users/.*"
# 允许 POST /api/users 仅从管理员来源
- method: "POST"
path: "/api/users"
sourceIPs:
- "10.0.0.0/8"
```
### 9.7.5 跨主机容器通信方案对比
#### 方案对比表
| 方案 | 隔离性 | 性能 | 复杂度 | 适用场景 |
|------|--------|------|--------|---------|
| 主机网络 | | | | 高性能单主机 |
| Bridge + Host Port | | | | 小规模集群 |
| Overlay (VXLAN) | | | | 跨域通信 |
| BGP (Calico) | | | | 大规模集群 |
| eBPF (Cilium) | | | | 高性能大集群 |
#### 选择建议
```bash
# 1. 开发环境:使用 Bridge 网络
docker network create my-app
docker-compose up # 默认使用 bridge
# 2. 小规模生产(< 50 节点):使用 Flannel
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 3. 中等规模50-500 节点):使用 Calico
kubeadm init --pod-network-cidr=192.168.0.0/16
kubectl apply -f https://docs.projectcalico.org/v3.24/manifests/tigera-operator.yaml
# 4. 大规模(> 500 节点)或需要 L7 策略:使用 Cilium
helm install cilium cilium/cilium --namespace kube-system
# 5. 需要多云/跨域:使用 Weave
```
### 9.7.6 网络故障排查
**常见网络问题诊断**
```bash
# 1. 容器无法访问外部网络
docker exec <container> ping 8.8.8.8
docker exec <container> cat /etc/resolv.conf
docker logs <container> | grep -i network
# 2. 容器间无法通信
docker network inspect <network>
docker exec <container1> ping <container2>
# 3. 端口映射失效
docker port <container>
netstat -tlnp | grep <port>
# 4. DNS 解析失败
docker exec <container> nslookup example.com
docker exec <container> cat /etc/hosts
# 5. 网络延迟
docker run --rm --network host iperf3:latest -c <target>
docker exec <container> mtr -r example.com
# 使用 tcpdump 抓包分析
docker run --rm --cap-add NET_ADMIN --network host \
corfr/tcpdump -i eth0 -n "port 80"
```

View File

@@ -34,8 +34,9 @@ graph TD
## 本章内容
* [配置 DNS](9.1_dns.md)
* [外部访问容器](9.5_port_mapping.md)
* [网络类型](9.2_network_types.md)
* [自定义网络](9.3_custom_network.md)
* [容器互联](9.4_container_linking.md)
* [外部访问容器](9.5_port_mapping.md)
* [网络隔离](9.6_network_isolation.md)
* [高级网络配置](9.7_advanced_networking.md)

View File

@@ -12,7 +12,7 @@
| **网络隔离** | 不同网络默认隔离增强安全性 |
| **--link** | 已废弃使用自定义网络替代 |
### 9.8.1 延伸阅读
### 延伸阅读
- [配置 DNS](9.1_dns.md)自定义 DNS 设置
- [网络类型](9.2_network_types.md)BridgeHostNone 等网络模式
@@ -22,3 +22,6 @@
- [网络隔离](9.6_network_isolation.md)网络安全与隔离策略
- [EXPOSE 指令](../07_dockerfile/7.9_expose.md) Dockerfile 中声明端口
- [Compose 网络](../11_compose/11.5_compose_file.md)Compose 中的网络配置
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -38,6 +38,15 @@ $ docker buildx build --sbom=true -t myimage .
该命令会在构建结果中包含 SPDX CycloneDX 格式的 SBOM 数据
> ** 注意与失败模式**
> 要使 SBOM (或其它 attestation 元数据) 成功附着并可见对底层的存储格式有前置要求默认的 classic image store 不支持 manifest list/index 这种存放 attestation 的结构
>
> 如果只简单运行上述命令你可能会面临 **命令成功执行但本地镜像中看不到 SBOM** 的体会落差
>
> **正确的解决路径有两条**
> 1. Docker 守护进程中启用 `containerd image store` 特性现代 Docker Desktop 默认推荐
> 2. 或者使用 `docker-container` driver 的构建器并直接 **加上 `--push` 参数** 将产物推送到远端支持 OCI 的镜像仓库仓库会正确保存这些元数据
### 10.2.2 官方文档
* https://docs.docker.com/engine/reference/commandline/buildx/

View File

@@ -11,3 +11,6 @@ Docker Buildx 是一个 docker CLI 插件,其扩展了 docker 命令,支持
* [使用 BuildKit 构建镜像](10.1_buildkit.md)
* [使用 Buildx 构建镜像](10.2_buildx.md)
* [构建多种系统架构支持的 Docker 镜像](10.3_multi-arch-images.md)
> **供应链安全与存储后端前瞻**现代软件供应链中镜像来源证明Provenance BuildKit 中默认以 `mode=min` 添加和软件物料清单SBOM可通过 `--sbom=true` 显式开启已经成为极其重要的构建产出这些 Attestations 数据会作为 manifest 附着在 **镜像索引 (Image Index)**
> 正是基于此诉求 Docker Engine v29 开始默认启用的 `containerd image store` 提供对 Image Index 的完美本地支持能力解决了传统经典存储后端Classic Store无法有效处理带 Attestations 镜像索引的瓶颈这使得你可以利用 `docker buildx imagetools inspect` 等手段甚至做到无需拉取完整镜像内容即可在 Registry 或本地高效校验镜像的安全元数据

View File

@@ -17,3 +17,6 @@ Docker Buildx 是 Docker 构建系统的重要进化,提供了高效、安全
- [Dockerfile 指令详解](../07_dockerfile/README.md)Dockerfile 编写基础
- [多阶段构建](../07_dockerfile/7.17_multistage_builds.md)优化镜像体积
- [Dockerfile 最佳实践](../appendix/best_practices.md)编写高效 Dockerfile
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -12,6 +12,10 @@
### 11.1.1 概述
Docker Compose 让用户能够以声明式方式定义和管理多容器应用它的核心价值在于用一个 YAML 文件取代一连串手动的 `docker run` 命令使得复杂应用的启动停止和重建变得一键可达
对于开发团队而言Compose 解决了三个关键问题环境一致性"在我机器上能跑"的问题服务依赖管理确保数据库在应用之前启动以及开发-测试-生产的配置差异管理通过 `compose.override.yaml` 实现多环境适配
### 11.1.2 模板文件规范
Compose 模板文件采用 YAML 格式扩展名为 `.yml` `.yaml`

View File

@@ -18,12 +18,12 @@ Linux 系统请使用以下介绍的方法安装。
> **提示**版本更新较快请访问上述链接获取最新版本号替换下方命令中的版本号
例如 Linux 64 位系统上直接下载对应的二进制包 ( v5.0.2 为例)
例如 Linux 64 位系统上直接下载对应的二进制包 ( v5.1.0 为例)
```bash
$ DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
$ mkdir -p $DOCKER_CONFIG/cli-plugins
$ curl -SL https://github.com/docker/compose/releases/download/v5.0.2/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
$ curl -SL https://github.com/docker/compose/releases/download/v5.1.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
```
之后执行
@@ -36,13 +36,13 @@ $ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
```bash
$ docker compose version
Docker Compose version v5.0.2
Docker Compose version v5.1.0
```
### 11.2.3 bash 补全命令
```bash
$ curl -L https://raw.githubusercontent.com/docker/compose/v5.0.2/contrib/completion/bash/docker-compose | sudo tee /etc/bash_completion.d/docker-compose > /dev/null
$ curl -L https://raw.githubusercontent.com/docker/compose/v5.1.0/contrib/completion/bash/docker-compose | sudo tee /etc/bash_completion.d/docker-compose > /dev/null
```
### 11.2.4 卸载

View File

@@ -399,8 +399,8 @@ mysql:
- my_other_secret
secrets:
my_secret:
file: ./my_secret.txt
db_root_password:
file: ./db_root_password.txt
my_other_secret:
external: true
```

View File

@@ -1,3 +1,38 @@
## 11.9 实战 LNMP
本项目的维护者 [khs1994](https://github.com/khs1994) 的开源项目 [khs1994-docker/lnmp](https://github.com/khs1994-docker/lnmp) 使用 Docker Compose 搭建了一套 LNMP 环境,各位开发者可以参考该项目在 Docker 或 Kubernetes 中运行 LNMP。
### 什么是 LNMP
LNMP 是一个经典的 Web 应用栈由以下四个开源软件组合而成
- **L**Linux操作系统
- **N**NginxWeb 服务器
- **M**MySQL数据库服务器
- **P**PHP脚本语言
这个组合被广泛用于构建高性能的 Web 应用
### 使用 Docker Compose 部署 LNMP
本项目的维护者 [khs1994](https://github.com/khs1994) 的开源项目 [khs1994-docker/lnmp](https://github.com/khs1994-docker/lnmp) 使用 Docker Compose 搭建了一套完整的 LNMP 环境。
### 参考项目
该项目中包含的服务
- **Nginx**Web 服务器用于处理 HTTP 请求
- **MySQL/MariaDB**关系型数据库服务
- **PHP-FPM**PHP 处理器 Nginx 通过 Fast CGI 协议通信
- **Redis**可选的内存缓存服务用于会话或缓存
### 学习资源
各位开发者可以参考该项目在以下场景中运行 LNMP
- Docker 容器化部署
- Kubernetes 集群编排
- 开发环境快速搭建
- 生产环境配置参考
项目地址https://github.com/khs1994-docker/lnmp
通过该项目你可以学习到如何使用 Docker Compose 定义多个相互关联的服务以及如何在容器化环境中管理应用的生命周期

View File

@@ -2,6 +2,10 @@
`Docker Compose` Docker 官方编排 (Orchestration) 项目之一负责快速的部署分布式应用
> **重要提示Compose V1 已停止支持**
>
> 早期基于 Python 编写的 Compose V1命令为 `docker-compose`已于 2023 年中正式停止支持现已全面升级为基于 Go 编写的 Compose V2作为 Docker CLI 的官方插件提供命令为 `docker compose`中间为空格本书强烈推荐且后续章节均以 V2 为核心标准进行讲解
本章将介绍 `Compose` 项目情况以及安装和使用
* [简介](11.1_introduction.md)

View File

@@ -13,9 +13,12 @@ Docker Compose 是管理多容器应用的利器,通过 YAML 文件声明式
| **查看日志** | `docker compose logs` 查看服务日志 |
| **模板文件** | 支持 `services``networks``volumes` 等顶级配置 |
### 11.10.1 延伸阅读
### 延伸阅读
- [Compose 模板文件](11.5_compose_file.md)详细模板语法参考
- [Compose 命令说明](11.4_commands.md)完整命令列表
- [网络配置](../09_network/README.md)Docker 网络基础
- [数据管理](../08_data/README.md)数据卷管理
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -2,9 +2,9 @@
命名空间是 Linux 内核一个强大的特性每个容器都有自己单独的命名空间运行在其中的应用都像是在独立的操作系统中运行一样命名空间保证了容器之间彼此互不影响
## 12.2 什么是 Namespace
### 12.2.1 什么是 Namespace
> **Namespace Linux 内核提供的资源隔离机制它让容器内的进程仿佛运行在独立的操作系统中** Namespace 是容器技术的核心基础之一它回答了一个关键问题**如何让一个进程 以为 自己独占整个系统**
> **Namespace Linux 内核提供的资源隔离机制它让容器内的进程仿佛运行在独立的操作系统中**Namespace 是容器技术的核心基础之一它回答了一个关键问题**如何让一个进程 以为 自己独占整个系统**
```mermaid
flowchart LR
@@ -26,7 +26,7 @@ flowchart LR
H4 -. "(实际是宿主机的 1234" .- C1
```
### 12.2.1 Namespace 的类型
### 12.2.2 Namespace 的类型
Linux 内核提供了以下几种 NamespaceDocker 容器使用了全部
@@ -42,7 +42,7 @@ Linux 内核提供了以下几种 NamespaceDocker 容器使用了全部:
---
### 12.2.2 PID Namespace
### 12.2.3 PID Namespace
PID Namespace 负责进程 ID 的隔离使得容器内的进程彼此不可见
@@ -75,7 +75,7 @@ PID USER COMMAND
---
### 12.2.3 NET Namespace
### 12.2.4 NET Namespace
NET Namespace 负责网络栈的隔离包括网卡路由表和 iptables 规则等
@@ -110,7 +110,7 @@ flowchart LR
---
### 12.2.4 MNT Namespace
### 12.2.5 MNT Namespace
MNT Namespace 负责文件系统挂载点的隔离确保容器看到独立的文件系统视图
@@ -143,7 +143,7 @@ MNT Namespace 负责文件系统挂载点的隔离,确保容器看到独立的
---
### 12.2.5 UTS Namespace
### 12.2.6 UTS Namespace
UTS Namespace 主要用于隔离主机名和域名
@@ -169,7 +169,7 @@ UTS = “UNIX Time-sharing System”是历史遗留的名称。
---
### 12.2.6 IPC Namespace
### 12.2.7 IPC Namespace
IPC Namespace 用于隔离进程间通信资源 System V IPC POSIX 消息队列
@@ -190,7 +190,7 @@ IPC Namespace 用于隔离进程间通信资源,如 System V IPC 和 POSIX 消
---
### 12.2.7 USER Namespace
### 12.2.8 USER Namespace
USER Namespace 允许将容器内的用户 ID 映射到宿主机的不同用户 ID
@@ -226,7 +226,7 @@ flowchart LR
---
### 12.2.8 动手实验体验 Namespace
### 12.2.9 动手实验体验 Namespace
使用 `unshare` 命令可以在不使用 Docker 的情况下体验 Namespace
@@ -285,7 +285,7 @@ $ ip addr
---
### 12.2.9 Namespace 的局限性
### 12.2.10 Namespace 的局限性
Namespace 提供了隔离但不是安全边界

View File

@@ -35,10 +35,11 @@ flowchart LR
| 时间 | 事件 |
|------|------|
| 2006 | Google 工程师提出 cgroups 概念 |
| 2008 | Linux 2.6.24 正式支持 cgroups v1 |
| 2006 | Google 工程师提出 "process containers" 概念 |
| 2007 | 为避免与 Linux 容器概念混淆更名为 "control groups" (cgroups) |
| 2008 | Linux 2.6.242008年1月正式合并 cgroups v1 |
| 2016 | Linux 4.5 引入 cgroups v2 |
| 现在 | Docker 默认使用 cgroups v2 (如系统支持)|
| 现在 | Docker 在宿主机支持 cgroups v2 时会自动使用 v2否则回退到 v1 |
---
@@ -265,7 +266,7 @@ $ docker run -d --name cadvisor \
-v /var/run:/var/run:ro \
-v /sys:/sys:ro \
-v /var/lib/docker:/var/lib/docker:ro \
gcr.io/cadvisor/cadvisor
ghcr.io/google/cadvisor
```
---

View File

@@ -92,32 +92,33 @@ flowchart LR
### 12.4.4 Docker 支持的存储驱动
Docker 可使用多种联合文件系统实现
Docker 的存储驱动经历了从早期各式各样的机制 aufs, devicemapper到被广泛使用的现代经典 graph driver (`overlay2`)再到当下Engine v29 及以后**默认启用的 containerd 镜像存储引擎containerd image store** 的演进
| 存储驱动 | 说明 | 推荐程度 |
| 存储后端 / 驱动 | 核心特性说明 | 推荐程度 |
|---------|------|---------|
| **overlay2**| 现代 Linux 默认驱动性能优秀 | **推荐** |
| **containerd image store**| (v29+ 新一代默认引擎) 基于 containerd snapshotters原生支持 OCI image index多架构镜像与 Attestations 构建溯源元数据存储 | **强烈推荐 (现代默认)** |
| **overlay2**| (经典 Graph Driver) 传统架构下的现代 Linux 默认驱动性能优秀但在处理复杂溯源元数据索引时受限 | **推荐 (主要后备)** |
| **aufs** | 早期默认兼容性好 | 遗留系统 |
| **btrfs** | 使用 Btrfs 子卷 | 特定场景 |
| **zfs** | 使用 ZFS 数据集 | 特定场景 |
| **devicemapper** | 块设备级存储 | 遗留系统 |
| **btrfs**/**zfs** | 使用原生稳定文件系统快照能力 | 特定场景 |
| **devicemapper** | 块设备级存储 | 遗留系统 (已被逐步弃用) |
| **vfs** | 不使用 CoW每层完整复制 | 仅测试 |
#### 各发行版推荐
#### Classic Graph Drivers Snapshotters 的核心差异
| Linux 发行版 | 推荐存储驱动 |
|-------------|-------------|
| Ubuntu 16.04+ | overlay2 |
| Debian Stretch+ | overlay2 |
| CentOS 7+ | overlay2 |
| RHEL 8+ | overlay2 |
| Fedora | overlay2 |
传统模型 `overlay2`将镜像拉取解包的过程由 Docker graph drivers 处理而新的 `containerd image store` 则将这一职责彻底下放给了 `containerd` 自身的 `snapshotters`底层在 Linux 发行版通常依然利用操作系统的 overlayfs这种架构改变带来了
1. 本地免拉取查看多平台镜像 index manifest attestations (SBOMProvenance)
2. 避免了以前绕过 CRI 获取本地镜像的问题带来更好的原生 Kubernetes 生态兼容性
#### 查看当前存储驱动
#### 查看当前存储驱动与后端
```bash
## 查看默认存储驱动 (Storage Driver)
$ docker info | grep "Storage Driver"
Storage Driver: overlay2
## 在 Engine v29+ 中,可以通过如下输出验证是否开启了 containerd 镜像后端:
$ docker info | grep "containerd image store"
containerd image store: true
```
---

View File

@@ -1,3 +1,50 @@
## 12.5 容器格式
最初Docker 采用了 `LXC` 中的容器格式 0.7 版本以后开始去除 LXC转而使用自行开发的 [libcontainer](https://github.com/docker/libcontainer),从 1.11 开始,则进一步演进为使用 [runC](https://github.com/opencontainers/runc) 和 [containerd](https://github.com/containerd/containerd)。
### Docker 容器格式的演进
最初Docker 采用了 `LXC` 中的容器格式 0.7 版本以后开始去除 LXC 的依赖转而使用自行开发的 [libcontainer](https://github.com/docker/libcontainer)。从 1.11 开始,则进一步演进为使用 [runC](https://github.com/opencontainers/runc) 和 [containerd](https://github.com/containerd/containerd)。
### 关键组件说明
#### LXCLinux 容器
Docker 早期版本0.1-0.7直接使用 LXC 作为容器运行时利用 Linux Namespaces Cgroups 实现容器隔离
#### libcontainer
- Docker 自行开发的容器库
- 提供了容器的通用接口
- 不依赖于特定的 Linux 容器实现
- 更灵活和可控
#### runC
- OCIOpen Container Initiative标准实现
- 轻量级的容器运行时
- 独立的二进制文件可单独使用
- 基于 libcontainer 发展而来
#### containerd
- Docker 开源的容器运行时
- 提供了容器的完整生命周期管理
- 支持 runC 和其他 OCI 兼容的运行时
- Kubernetes 等编排系统中广泛使用
### 容器规范标准
Docker 积极参与 Open Container Initiative (OCI) 的制定推动了以下规范的发展
- **Image Spec**容器镜像格式规范
- **Runtime Spec**容器运行时接口规范
- **Distribution Spec**容器镜像分发规范
### 架构演变的优势
LXC libcontainer runC/containerd 的演变提供了以下优势
1. 减少外部依赖
2. 提高运行效率
3. 遵循行业标准OCI
4. 增强可移植性和互操作性
5. 支持多种容器运行时选择

View File

@@ -12,6 +12,8 @@ Docker 底层的核心技术包括 Linux 上的命名空间 (Namespaces)、控
随着 Linux 系统对于命名空间功能的完善实现程序员已经可以实现上面的所有需求让某些进程在彼此隔离的命名空间中运行大家虽然都共用一个内核和某些运行时环境 (例如一些系统命令和系统库)但是彼此却看不到都以为系统中只有自己的存在这种机制就是容器 (Container)利用命名空间来做权限的隔离控制利用 cgroups 来做资源分配
## 本章内容
* [基本架构](12.1_arch.md)
* [命名空间](12.2_namespace.md)
* [控制组](12.3_cgroups.md)

View File

@@ -1,5 +1,13 @@
## 本章小结
本章深入介绍了 Docker 的底层实现包括命名空间控制组和联合文件系统三大核心技术
| 技术 | 作用 | 要点 |
|------|------|------|
| **Namespace** | 资源隔离 | PIDNETMNTUTSIPCUSER 六种命名空间 |
| **Cgroups** | 资源限制 | 限制 CPU内存磁盘 I/O进程数 |
| **Union FS** | 分层存储 | overlay2 为推荐驱动支持 Copy-on-Write |
| Namespace | 隔离内容 | 一句话说明 |
|-----------|---------|-----------|
| PID | 进程 ID | 容器有自己的进程树 |
@@ -9,13 +17,6 @@
| IPC | 进程间通信 | 容器间 IPC 隔离 |
| USER | 用户 ID | 容器 root 宿主机 root |
### 12.7.1 延伸阅读
- [控制组 (Cgroups)](12.3_cgroups.md)资源限制机制
- [联合文件系统](12.4_ufs.md)分层存储的实现
- [安全](../18_security/README.md)容器安全实践
- [Linux Namespace 官方文档](https://man7.org/linux/man-pages/man7/namespaces.7.html)
| 资源 | 限制参数 | 示例 |
|------|---------|------|
| **内存** | `-m` | `-m 512m` |
@@ -24,21 +25,15 @@
| **磁盘 I/O** | `--device-write-bps` | `--device-write-bps /dev/sda:10mb` |
| **进程数** | `--pids-limit` | `--pids-limit=100` |
### 12.7.2 延伸阅读
- [命名空间](12.2_namespace.md)资源隔离
- [安全](../18_security/README.md)容器安全概述
- [Docker Stats](../05_container/README.md)监控容器资源
| 概念 | 说明 |
|------|------|
| **UnionFS** | 将多层目录联合挂载为一个文件系统 |
| **Copy-on-Write** | 写时复制修改时才复制到可写层 |
| **overlay2** | Docker 默认推荐的存储驱动 |
| **分层好处** | 镜像复用快速构建快速启动 |
### 12.7.3 延伸阅读
### 延伸阅读
- [命名空间](12.2_namespace.md)资源隔离机制详解
- [控制组 (Cgroups)](12.3_cgroups.md)资源限制机制
- [联合文件系统](12.4_ufs.md)分层存储的实现
- [安全](../18_security/README.md)容器安全实践
- [镜像](../02_basic_concept/2.1_image.md)理解镜像分层
- [容器](../02_basic_concept/2.2_container.md)容器存储层
- [构建镜像](../04_image/4.5_build.md)Dockerfile 层的创建
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -1,10 +1,10 @@
## 13.2 基本概念
如图 12-2 所示Kubernetes 由控制平面与工作节点构成
如图 13-2 所示Kubernetes 由控制平面与工作节点构成
![Kubernetes 基本概念示意图](./_images/kubernetes_design.jpg)
12-2 Kubernetes 基本概念示意图
13-2 Kubernetes 基本概念示意图
* 节点 (`Node`)一个节点是一个运行 Kubernetes 中的主机
* 容器组 (`Pod`)一个 Pod 对应于由若干容器组成的一个容器组同个组内的容器共享一个存储卷 (volume)
@@ -39,41 +39,56 @@
#### 节点管理
节点并非 Kubernetes 创建而是由云平台创建或者就是物理机器虚拟机 Kubernetes 节点仅仅是一条记录节点创建之后Kubernetes 会检查其是否可用 Kubernetes 节点用如下结构保存
节点并非 Kubernetes 创建而是由云平台创建或者就是物理机器虚拟机 Kubernetes 节点仅仅是一条记录节点创建之后Kubernetes 会检查其是否可用可以通过 `kubectl` 查看节点信息
```json
{
"id": "10.1.2.3",
"kind": "Minion",
"apiVersion": "v1beta1",
"resources": {
"capacity": {
"cpu": 1000,
"memory": 1073741824
},
},
"labels": {
"name": "my-first-k8s-node",
},
}
```bash
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
control-plane Ready control-plane 10d v1.30.2
worker-1 Ready <none> 10d v1.30.2
worker-2 Ready <none> 10d v1.30.2
```
Kubernetes 校验节点可用依赖于 ID在当前的版本中有两个接口可以用来管理节点节点控制和 Kube 管理
每个节点的详细信息以如下结构保存
#### 节点控制
```yaml
apiVersion: v1
kind: Node
metadata:
name: worker-1
labels:
kubernetes.io/os: linux
status:
capacity:
cpu: "4"
memory: 8Gi
conditions:
- type: Ready
status: "True"
```
Kubernetes 主节点中节点控制器是用来管理节点的组件主要包含
#### 节点控制器
* 集群范围内节点同步
Kubernetes 控制平面中节点控制器 (Node Controller) 负责管理节点的生命周期主要包含
* 集群范围内节点状态同步
* 单节点生命周期管理
节点控制有一个同步轮询主要监听所有云平台的虚拟实例会根据节点状态创建和删除可以通过 `--node_sync_period` 标志来控制该轮询如果一个实例已经创建节点控制将会为其创建一个结构同样的如果一个节点被删除节点控制也会删除该结构 Kubernetes 启动时可用通过 `--machines` 标记来显示指定节点同样可以使用 `kubectl` 一条一条的添加节点两者是相同的通过设置 `--sync_nodes=false` 标记来禁止集群之间的节点同步你也可以使用 api/kubectl 命令行来增删节点
节点控制器会持续监控节点的健康状态当节点变为不可达时控制器会等待一个超时期限然后将该节点上的 Pod 标记为失败并触发重新调度可以使用 `kubectl` 管理节点例如标记节点为不可调度或排空节点上的工作负载
```bash
## 标记节点为不可调度
$ kubectl cordon worker-1
## 排空节点上的 Pod
$ kubectl drain worker-1 --ignore-daemonsets
```
### 13.2.2 容器组
Kubernetes 使用的最小单位是容器组容器组是创建调度管理的最小单位一个容器组使用相同的 Docker 容器并共享卷 (挂载点)一个容器组是一个特定应用的打包集合包含一个或多个容器
Kubernetes 使用的最小调度单位是容器组 (Pod)是创建调度管理的最小单位一个 Pod 包含一个或多个紧密协作的容器它们共享网络命名空间和存储卷
和运行的容器类似一个容器组被认为只有很短的运行周期容器组被调度到一组节点运行直到容器的生命周期结束或者其被删除如果节点死掉运行在其上的容器组将会被删除而不是重新调度(也许在将来的版本中会添加容器组的移动)
Pod 通常不会被直接创建而是通过 Deployment 等控制器来管理当节点发生故障时控制器会在其他可用节点上重新创建 Pod
#### 容器组设计的初衷
@@ -93,7 +108,7 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中有两个接
#### 容器组的使用
容器组可以通过组合来构建复杂的应用其本来的意义包含
容器组可以通过组合来构建复杂的应用典型的使用模式包含
* 内容管理文件和数据加载以及本地缓存管理等
* 日志和检查点备份压缩快照等
@@ -101,108 +116,154 @@ Kubernetes 校验节点可用依赖于 ID。在当前的版本中有两个接
* 代理网桥
* 控制器管理配置以及更新
#### 替代方案
#### 为什么不在一个容器里运行多个程序
为什么不在一个单一的容器里运行多个程序
* 1. 透明化为了使容器组中的容器保持一致的基础设施和服务比如进程管理和资源监控这样设计是为了用户的便利性
* 2. 解耦软件之间的依赖每个容器都可能重新构建和发布Kubernetes 必须支持热发布和热更新 (将来)
* 3. 方便使用用户不必运行独立的程序管理也不用担心每个应用程序的退出状态
* 4. 高效考虑到基础设施有更多的职责容器必须要轻量化
1. **透明化**为了使容器组中的容器保持一致的基础设施和服务比如进程管理和资源监控
2. **解耦依赖**每个容器都可能独立地重新构建和发布
3. **方便使用**用户不必运行独立的程序管理也不用担心每个应用程序的退出状态
4. **高效**考虑到基础设施有更多的职责容器必须要轻量化
#### 容器组的生命状态
包括若干状态值`pending``running``succeeded``failed`
包括若干状态值`Pending``Running``Succeeded``Failed`
##### pending
| 状态 | 说明 |
|------|------|
| **Pending** | Pod 已被集群接受但有一个或多个容器还没有运行起来可能在拉取镜像|
| **Running** | Pod 已被调度到节点并且所有容器都已启动至少有一个容器处于运行状态|
| **Succeeded** | Pod 中的所有容器都正常退出且不会被重启|
| **Failed** | Pod 中的所有容器都已终止且至少有一个容器以失败状态退出|
容器组已经被节点接受但有一个或多个容器还没有运行起来这将包含某些节点正在下载镜像的时间这种情形会依赖于网络情况
#### 容器组生命周期与重启策略
##### running
Pod 的重启策略 (`restartPolicy`) 决定了容器退出后的行为
容器组已经被调度到节点并且所有的容器都已经启动至少有一个容器处于运行状态 (或者处于重启状态)
| 重启策略 | 容器正常退出 | 容器异常退出 |
|---------|------------|------------|
| **Always** (默认) | 重启容器 | 重启容器 |
| **OnFailure** | 不重启 | 重启容器 |
| **Never** | 不重启 | 不重启 |
##### succeeded
当节点故障或不可达时节点控制器会将该节点上所有 Pod 的状态标记为 `Failed`如果这些 Pod Deployment 等控制器管理控制器会自动在其他节点上重新创建
所有的容器都正常退出
### 13.2.3 Deployment ReplicaSet
##### failed
Deployment 是管理无状态应用的推荐方式它通过 ReplicaSet 来确保指定数量的 Pod 副本始终在运行
容器组中所有容器都意外中断了
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
```
#### 容器组生命周期
Deployment 的核心能力包括
通常来说如果容器组被创建了就不会自动销毁除非被某种行为触发而触发此种情况可能是人为或者复制控制器所为唯一例外的是容器组由 succeeded 状态成功退出或者在一定时间内重试多次依然失败
* **副本管理**确保始终有指定数量的 Pod 在运行
* **滚动更新**逐步替换旧版本 Pod实现零停机部署
* **回滚**如果新版本出现问题可以快速回滚到之前的版本
如果某个节点死掉或者不能连接那么节点控制器将会标记其上的容器组的状态为 `failed`
举例如下
* 容器组状态 `running` 1 容器容器正常退出
* 记录完成事件
* 如果重启策略为
* 始终重启容器容器组保持 `running`
* 失败时容器组变为 `succeeded`
* 从不容器组变为 `succeeded`
* 容器组状态 `running` 1 容器容器异常退出
* 记录失败事件
* 如果重启策略为
* 始终重启容器容器组保持 `running`
* 失败时重启容器容器组保持 `running`
* 从不容器组变为 `failed`
* 容器组状态 `running` 2 容器 1 容器异常退出
* 记录失败事件
* 如果重启策略为
* 始终重启容器容器组保持 `running`
* 失败时重启容器容器组保持 `running`
* 从不容器组保持 `running`
* 当有 2 容器退出
* 记录失败事件
* 如果重启策略为
* 始终重启容器容器组保持 `running`
* 失败时重启容器容器组保持 `running`
* 从不容器组变为 `failed`
* 容器组状态 `running`容器内存不足
* 标记容器错误中断
* 记录内存不足事件
* 如果重启策略为
* 始终重启容器容器组保持 `running`
* 失败时重启容器容器组保持 `running`
* 从不记录错误事件容器组变为 `failed`
* 容器组状态 `running`一块磁盘死掉
* 杀死所有容器
* 记录事件
* 容器组变为 `failed`
* 如果容器组运行在一个控制器下容器组将会在其他地方重新创建
* 容器组状态 `running`对应的节点段溢出
* 节点控制器等到超时
* 节点控制器标记容器组 `failed`
* 如果容器组运行在一个控制器下容器组将会在其他地方重新创建
### 13.2.3 Replication Controllers
> Replication Controller (RC) 是早期的控制器类型现代 Kubernetes 更推荐使用 ReplicaSet/Deployment
> 早期 Kubernetes 使用 Replication Controller (RC) 来管理副本现已被 ReplicaSet/Deployment 取代
### 13.2.4 服务
> 服务 (Service) 定义一组 Pod 的逻辑集合和访问它们的策略
服务 (Service) 定义一组 Pod 的逻辑集合和访问策略由于 Pod IP 地址是动态分配的Service 提供了一个稳定的访问入口
```yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
type: ClusterIP
```
常见的 Service 类型
| 类型 | 说明 |
|------|------|
| **ClusterIP** | 默认类型仅集群内部可访问 |
| **NodePort** | 在每个节点上开放固定端口集群外部可通过 `节点IP:端口` 访问 |
| **LoadBalancer** | 通过云平台的负载均衡器暴露服务 |
### 13.2.5
> (Volume) 包含可被 Pod 中容器访问的数据的目录
(Volume) Pod 容器提供持久化存储Kubernetes 支持多种卷类型
| 卷类型 | 说明 |
|-------|------|
| **emptyDir** | 临时存储Pod 删除后数据丢失 |
| **hostPath** | 挂载节点上的文件或目录 |
| **PersistentVolumeClaim** | 使用持久卷声明与底层存储解耦 |
| **configMap / secret** | 将配置或敏感数据挂载为文件 |
生产环境中推荐使用 PersistentVolume (PV) PersistentVolumeClaim (PVC) 来管理存储实现存储资源与使用者的解耦
### 13.2.6 标签
> 标签 (Label) 是附加到对象 ( Pods) 上的键值对用于组织和选择对象子集
标签 (Label) 是附加到 Kubernetes 对象上的键值对用于组织和选择对象子集标签是 Kubernetes 中实现松耦合的关键机制
### 13.2.7 接口权限
```bash
## 为 Pod 添加标签
$ kubectl label pod my-pod env=production
> 接口权限通过认证授权和准入控制来保护 Kubernetes API 的访问
## 通过标签选择器查询
$ kubectl get pods -l env=production
```
### 13.2.8 web 界面
ServiceDeployment 等资源都通过标签选择器 (`selector`) 来关联目标 Pod
> Kubernetes Dashboard 是一个基于 Web 的用户界面用于管理集群
### 13.2.7 API 访问控制
### 13.2.9 命令行操作
Kubernetes API 的访问通过三个阶段进行控制
> kubectl Kubernetes 的命令行工具用于与集群进行交互
1. **认证 (Authentication)**验证请求者的身份如证书TokenOIDC
2. **授权 (Authorization)**判断请求者是否有权限执行操作通常使用 RBAC
3. **准入控制 (Admission Control)**在请求被持久化之前对其进行校验或修改
### 13.2.8 Dashboard
Kubernetes Dashboard 是一个基于 Web 的用户界面用于部署容器化应用监控集群资源和排查问题Dashboard 的部署方法详见[部署 Dashboard](../14_kubernetes_setup/14.7_dashboard.md) 章节
### 13.2.9 命令行工具 kubectl
`kubectl` Kubernetes 的命令行工具用于与集群进行交互常用命令如下
```bash
## 查看集群中的资源
$ kubectl get pods,deployments,services,nodes
## 创建资源
$ kubectl apply -f deployment.yaml
## 查看 Pod 日志
$ kubectl logs my-pod
## 进入 Pod 执行命令
$ kubectl exec -it my-pod -- /bin/sh
## 查看资源详情
$ kubectl describe pod my-pod
```
更多 kubectl 操作详见[kubectl 命令行](../14_kubernetes_setup/14.8_kubectl.md)章节

View File

@@ -13,11 +13,11 @@
### 13.3.2 运行原理
如图 12-3 所示该图完整展示了 Kubernetes 的运行原理
如图 13-3 所示该图完整展示了 Kubernetes 的运行原理
![Kubernetes 架构](./_images/k8s_architecture.png)
12-3 Kubernetes 运行原理图
13-3 Kubernetes 运行原理图
可见Kubernetes 首先是一套分布式系统由多个节点组成节点分为两类一类是属于管理平面的主节点/控制节点 (Master Node)一类是属于运行平面的工作节点 (Worker Node)
@@ -52,4 +52,4 @@
![Proxy 代理对服务的请求](./_images/kube-proxy.png)
12-4 kube-proxy 请求转发示意图
13-4 kube-proxy 请求转发示意图

View File

@@ -6,10 +6,10 @@
Kubernetes 的最小调度单位是 `Pod`一个 `Pod` 由一组紧密协作的容器构成它们共享网络命名空间IP 以及部分存储资源也可以根据需要对 Pod 进行端口映射
本章将分为 5 节介绍 `Kubernetes`包括
本章将分为 5 节介绍 `Kubernetes`
* 项目简介
* 快速入门
* 基本概念
* 实践例子
* 架构分析等高级话题
* [简介](13.1_intro.md)
* [基本概念](13.2_concepts.md)
* [架构设计](13.3_design.md)
* [高级特性](13.4_advanced.md)
* [实战练习](13.5_practice.md)

View File

@@ -17,3 +17,6 @@ Kubernetes 是当前最主流的容器编排平台,其声明式管理模型和
- [部署 Kubernetes](../14_kubernetes_setup/README.md)搭建 Kubernetes 集群
- [Etcd](../15_etcd/README.md)Kubernetes 使用的分布式存储
- [底层实现](../12_implementation/README.md)容器技术原理
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -1,4 +1,4 @@
## 14.1 使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)
## 14.1 使用 kubeadm 部署 Kubernetes
`kubeadm` 提供了 `kubeadm init` 以及 `kubeadm join` 这两个命令作为快速创建 `Kubernetes` 集群的最佳实践
@@ -292,7 +292,6 @@ kubelet 默认要求禁用 swap否则可能导致初始化失败或节点无
$ sudo swapoff -a
## 如需永久禁用,可在 /etc/fstab 中注释 swap 对应行
```
```bash
@@ -446,7 +445,7 @@ $ kubectl get node -o yaml | grep CIDR
```
```bash
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.26.1/Documentation/kube-flannel.yml
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.1/Documentation/kube-flannel.yml
```
### 14.1.10 master 节点默认不能运行 pod

View File

@@ -2,9 +2,13 @@
`kubeadm` 提供了 `kubeadm init` 以及 `kubeadm join` 这两个命令作为快速创建 `Kubernetes` 集群的最佳实践
> **重要说明** Kubernetes 1.24 内置 `dockershim` 已被移除Kubernetes 默认不再直接使用 Docker Engine 作为容器运行时 (CRI)因此**更推荐参考** 同目录下的[使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)](14.1_kubeadm.md)
> **强烈提示Docker Kubernetes 环境的时代分界**
>
> 本文档主要用于历史环境/学习目的如果你确实需要在较新版本中继续使用 Docker Engine通常需要额外部署 `cri-dockerd` 并在 `kubeadm init/join` 中指定 `--cri-socket`
> Kubernetes v1.24 内置的 `dockershim` 组件已被正式移除这意味着 **Kubernetes 不再将 Docker Engine 作为默认内置的容器运行时**虽然 Docker 仍然是你本地构建管理镜像的绝佳工具但它已不再是 kubelet 的默认运行时选项
>
> 因此**强烈推荐** 读者直接参考同目录下的[使用 kubeadm 部署 Kubernetes (CRI 使用 containerd)](14.1_kubeadm.md)作为主要的部署路线
>
> 本文档保留主要用于历史环境维护或特殊需求场景如果你必须在较新的 Kubernetes 集群中继续使用 Docker Engine 作为底层运行时你必须理解 CRI 层机制额外部署并配置第三方兼容层 `cri-dockerd`同时在部署时手动补充 `--cri-socket` 等参数约束
### 14.2.1 安装 Docker
@@ -74,7 +78,6 @@ kubelet 默认要求禁用 swap否则可能导致初始化失败或节点无
$ sudo swapoff -a
## 如需永久禁用,可在 /etc/fstab 中注释 swap 对应行
```
```bash
@@ -212,7 +215,7 @@ $ kubectl get node -o yaml | grep CIDR
```
```bash
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.26.1/Documentation/kube-flannel.yml
$ kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.28.1/Documentation/kube-flannel.yml
```
### 14.2.9 master 节点默认不能运行 pod

View File

@@ -1,3 +1,67 @@
## 14.6 一步步部署 Kubernetes 集群
可以参考 [opsnull/follow-me-install-kubernetes-cluster](https://github.com/opsnull/follow-me-install-kubernetes-cluster) 项目一步步部署 Kubernetes 集群。
### 概述
部署 Kubernetes 集群涉及多个组件的安装和配置包括 Master 节点和 Worker 节点本章介绍如何使用 systemd 管理这些服务的生命周期
### Kubernetes 主要组件
#### Master 节点组件
- **kube-apiserver**API 服务器Kubernetes 集群的中心
- **kube-controller-manager**控制器管理器
- **kube-scheduler**调度器负责 Pod 调度
- **etcd**分布式键值存储存储集群数据
#### Worker 节点组件
- **kubelet**节点代理管理容器生命周期
- **kube-proxy**网络代理处理服务网络
- **Container Runtime**容器运行时Dockercontainerd
### 使用 systemd 管理 Kubernetes 服务
#### 服务单元文件
为了让 systemd 管理 Kubernetes 服务需要创建相应的 `.service` 文件例如
```
/etc/systemd/system/kubelet.service
/etc/systemd/system/kube-proxy.service
/etc/systemd/system/kube-apiserver.service
```
#### 常用命令
```bash
# 启动服务
sudo systemctl start kubelet
# 停止服务
sudo systemctl stop kubelet
# 重启服务
sudo systemctl restart kubelet
# 查看服务状态
sudo systemctl status kubelet
# 设置开机自启
sudo systemctl enable kubelet
```
### 参考资源
详细的部署步骤和配置说明可以参考以下项目
- [opsnull/follow-me-install-kubernetes-cluster](https://github.com/opsnull/follow-me-install-kubernetes-cluster):一个完整的 Kubernetes 集群部署指南项目
该项目提供了详细的步骤说明涵盖 Master 节点Worker 节点的安装配置以及如何使用 systemd 管理这些组件的生命周期
### 推荐学习路径
1. 理解 Kubernetes 架构和各组件的作用
2. 准备所需的系统环境Linux 主机网络配置等
3. 按步骤安装各个 Kubernetes 组件
4. 配置 systemd 服务单元文件
5. 验证集群健康状态

View File

@@ -8,74 +8,74 @@ kubectl [flags]
kubectl [command]
```
## 14.8 get
### 14.8.1 get
显示一个或多个资源
## 14.8 describe
### 14.8.2 describe
显示资源详情
## 14.8 create
### 14.8.3 create
从文件或标准输入创建资源
## 14.8 update
### 14.8.4 update
从文件或标准输入更新资源
## 14.8 delete
### 14.8.5 delete
通过文件名标准输入资源名或者 label selector 删除资源
## 14.8 logs
### 14.8.6 logs
输出 pod 中一个容器的日志
## 14.8 rollout
### 14.8.7 rollout
Deployment 等资源执行滚动更新/回滚
## 14.8 exec
### 14.8.8 exec
在容器内部执行命令
## 14.8 port-forward
### 14.8.9 port-forward
将本地端口转发到 Pod
## 14.8 proxy
### 14.8.10 proxy
Kubernetes API server 启动代理服务器
## 14.8 run
### 14.8.11 run
在集群中使用指定镜像启动容器
## 14.8 expose
### 14.8.12 expose
replication controller service pod 暴露为新的 Kubernetes service
## 14.8 label
### 14.8.13 label
更新资源的 label
## 14.8 config
### 14.8.14 config
修改 Kubernetes 配置文件
## 14.8 cluster-info
### 14.8.15 cluster-info
显示集群信息
## 14.8 api-versions
### 14.8.16 api-versions
/版本 的格式输出服务端支持的 API 版本
## 14.8 version
### 14.8.17 version
输出服务端和客户端的版本信息
## 14.8 help
### 14.8.18 help
显示各个命令的帮助信息

View File

@@ -2,10 +2,13 @@
目前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
你可以使用以下几种方式部署 Kubernetes接下来的小节会对各种方式进行详细介绍
* kubeadm
* docker-desktop
* k3s
接下来的小节会对以上几种方式进行详细介绍
* [使用 kubeadm 部署 (CRI 使用 containerd)](14.1_kubeadm.md)
* [使用 kubeadm 部署 (使用 Docker)](14.2_kubeadm-docker.md)
* [ Docker Desktop 使用](14.3_docker-desktop.md)
* [Kind - Kubernetes IN Docker](14.4_kind.md)
* [K3s - 轻量级 Kubernetes](14.5_k3s.md)
* [一步步部署 Kubernetes 集群](14.6_systemd.md)
* [部署 Dashboard](14.7_dashboard.md)
* [Kubernetes 命令行 kubectl](14.8_kubectl.md)

View File

@@ -15,3 +15,6 @@
- [容器编排基础](../13_kubernetes_concepts/README.md)Kubernetes 核心概念
- [Dashboard](14.7_dashboard.md)部署可视化管理界面
- [kubectl](14.8_kubectl.md)命令行工具使用指南
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -4,7 +4,7 @@
`etcd` 基于 `Go` 语言实现因此用户可以从[项目主页](https://github.com/etcd-io/etcd)下载源代码自行编译,也可以下载编译好的二进制文件,甚至直接使用制作好的 `Docker` 镜像文件来体验。
>注意本章节内容基于 etcd `3.4.x` 版本
>注意本章节内容基于 etcd `3.4.x` 版本编写etcd 3.4 的官方支持将于 **2026 5 15 日结束**新部署建议使用 etcd `3.5` `3.6` 版本请访问 [etcd 官方发布页](https://github.com/etcd-io/etcd/releases) 获取最新版本。
### 15.2.1 二进制文件方式下载

View File

@@ -1,3 +1,10 @@
# 第十五章 Etcd 项目
`etcd` `CoreOS` 团队发起的一个管理配置信息和服务发现 (`Service Discovery`) 的项目在这一章里面我们将基于 `etcd 3.x` 版本介绍该项目的目标安装和使用以及实现的技术
## 本章内容
* [简介](15.1_intro.md)
* [安装](15.2_install.md)
* [集群](15.3_cluster.md)
* [使用 etcdctl](15.4_etcdctl.md)

View File

@@ -15,3 +15,6 @@ etcd 是 Kubernetes 的核心存储组件,为分布式系统提供可靠的键
- [容器编排基础](../13_kubernetes_concepts/README.md)Kubernetes 如何使用 etcd
- [部署 Kubernetes](../14_kubernetes_setup/README.md)在集群中部署 etcd
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -15,3 +15,199 @@
![腾讯云容器服务界面](https://mc.qcloudimg.com/static/img/0581dbeb97c869bbe6e62025dbc592d7/image.png)
13-6 腾讯云容器服务示意图
### 腾讯云容器服务 (TKE) 简介
腾讯云容器服务 (TKE, Tencent Kubernetes Engine) 是一款容器编排平台基于原生 Kubernetes 提供支持自动扩展负载均衡多可用区高可用等企业级功能TKE 帮助开发者快速部署和管理容器化应用消除集群运维的复杂度
### 基本使用步骤
#### 1. 创建集群
登录腾讯云控制台进入容器服务模块
- 选择 "创建集群"配置集群名称地域和网络
- 选择节点配置云服务器规格和数量
- 设置 Kubernetes 版本和安全组
- 完成创建后获得集群 kubeconfig 文件
```bash
# 下载 kubeconfig 文件后,配置本地环境
export KUBECONFIG=/path/to/kubeconfig.yaml
kubectl cluster-info
```
#### 2. 部署容器应用
创建 Deployment 部署应用
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
```
应用配置文件
```bash
kubectl apply -f deployment.yaml
kubectl get pods
kubectl get svc
```
#### 3. 管理镜像
通过腾讯云容器镜像服务 (TCR) 存储和管理私有镜像
```bash
# 登录腾讯云镜像仓库
docker login ccr.ccs.tencentyun.com -u <username>
# 标记本地镜像
docker tag my-app:latest ccr.ccs.tencentyun.com/namespace/my-app:latest
# 推送镜像到腾讯云
docker push ccr.ccs.tencentyun.com/namespace/my-app:latest
```
### 腾讯云 Docker 镜像加速器配置
为了加快镜像拉取速度腾讯云提供了镜像加速服务配置方法如下
#### Linux 系统配置
编辑 `/etc/docker/daemon.json` 文件如果不存在则创建
```bash
# 创建或编辑配置文件
sudo mkdir -p /etc/docker
sudo nano /etc/docker/daemon.json
```
添加以下内容
```json
{
"registry-mirrors": [
"https://mirror.ccs.tencentyun.com"
],
"insecure-registries": []
}
```
重启 Docker 服务
```bash
sudo systemctl daemon-reload
sudo systemctl restart docker
```
验证配置
```bash
# 查看镜像源是否生效
docker info | grep -A 5 "Registry Mirrors"
```
#### Windows/Mac 配置
对于 Docker Desktop在设置界面中
1. 打开 Docker Desktop 设置
2. 导航到 "Docker Engine"
3. JSON 配置中添加上述 `registry-mirrors` 字段
4. 点击 "Apply & Restart"
### 腾讯云容器镜像服务 (TCR)
腾讯云容器镜像服务 (TCR) 提供企业级容器镜像存储和分发能力
- **私有镜像仓库**支持命名空间隔离完整的访问权限控制
- **镜像扫描**自动扫描镜像漏洞提供安全建议
- **镜像加速**支持跨地域镜像分发和加速
- **Webhook 通知**镜像推送时自动触发 CI/CD 流程
- **镜像版本管理**标签管理镜像清理策略生命周期管理
#### 快速开始
1. 在腾讯云控制台创建个人版或企业版 TCR 实例
2. 创建命名空间和镜像仓库
3. 配置 Docker 登录凭证
4. 本地构建镜像并推送到 TCR
5. TKE 集群部署时引用 TCR 镜像地址
#### 完整推送/拉取示例
```bash
# 登录到腾讯云 TCR使用 API 密钥)
docker login ccr.ccs.tencentyun.com \
--username <腾讯云账号ID> \
--password <API_KEY>
# 拉取公开镜像
docker pull ccr.ccs.tencentyun.com/library/nginx:latest
# 构建本地镜像
docker build -t my-app:v1.0 .
# 标记镜像为 TCR 地址
docker tag my-app:v1.0 \
ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
# 推送镜像到 TCR
docker push ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
# 在 Dockerfile 中使用 TCR 镜像
FROM ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
RUN echo "使用腾讯云镜像作为基础镜像"
```
#### TKE 集群中使用 TCR 镜像
配置镜像拉取凭证后 Deployment 中直接引用 TCR 镜像
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
imagePullSecrets:
- name: tcr-secret # 需提前创建该 Secret
containers:
- name: my-app
image: ccr.ccs.tencentyun.com/my-namespace/my-app:v1.0
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
```

View File

@@ -12,6 +12,260 @@
[阿里云容器服务 Kubernetes ACK](https://www.aliyun.com/product/kubernetes?source=5176.11533457\&userCode=8lx5zmtu\&type=copy) 提供了高性能、可伸缩的容器应用管理服务,支持在一组云服务器上通过 Docker 容器来进行应用生命周期管理。容器服务极大简化了用户对容器管理集群的搭建工作,无缝整合了阿里云虚拟化、存储、网络和安全能力。容器服务提供了多种应用发布方式和流水线般的持续交付能力,原生支持微服务架构,助力用户无缝上云和跨云管理。
![阿里云容器服务界面](https://img.alicdn.com/tps/TB10yjtPpXXXXacXXXXXXXXXXXX-1531-1140.png)
<!-- 注意阿里云容器服务截图链接已失效请参考阿里云官方文档获取最新界面截图 -->
<!-- 原链接: https://img.alicdn.com/tps/TB10yjtPpXXXXacXXXXXXXXXXXX-1531-1140.png -->
13-4 阿里云容器服务示意图
13-4 阿里云容器服务示意图请访问 [阿里云容器服务 ACK 官方文档](https://help.aliyun.com/product/85222.html) 查看最新界面)
### 阿里云容器服务 ACK 简介
阿里云容器服务 Kubernetes (ACK, Container Service for Kubernetes) 是一款托管式 Kubernetes 服务基于开源 Kubernetes 构建提供企业级的容器编排和管理能力ACK 集成了阿里云存储网络和安全能力支持多种应用部署模式和持续交付流程
### 基本使用步骤
#### 1. 创建集群
登录阿里云控制台进入容器服务 > Kubernetes 集群
- 点击 "创建集群"选择集群配置
- 配置集群名称地域可用区和节点类型
- 选择节点规格和数量支持弹性伸缩
- 配置网络参数和安全设置
- 完成创建下载 kubeconfig 文件
```bash
# 配置本地 kubectl
export KUBECONFIG=/path/to/kubeconfig.yaml
kubectl get nodes
```
#### 2. 部署容器应用
通过 Deployment 部署应用示例
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: registry.cn-hangzhou.aliyuncs.com/myapp/web:v1
ports:
- containerPort: 8080
resources:
limits:
memory: "512Mi"
cpu: "500m"
```
部署应用
```bash
kubectl apply -f deployment.yaml
kubectl get pods -o wide
kubectl logs <pod-name>
```
#### 3. 暴露服务
创建 Service 暴露应用
```yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: web
```
应用
```bash
kubectl apply -f service.yaml
kubectl get svc web-service
```
### 阿里云 Docker 镜像加速器配置
为了加快从阿里云镜像源拉取官方镜像的速度可以配置镜像加速器阿里云为容器服务 ACK 用户提供了免费的镜像加速服务
#### 获取加速器地址
登录阿里云容器镜像服务控制台 "镜像工具" > "镜像加速器" 中可获取个人的加速器地址类似于 `https://xxxxxx.mirror.aliyuncs.com`
#### Linux 系统配置
编辑或创建 `/etc/docker/daemon.json` 文件
```bash
sudo mkdir -p /etc/docker
sudo nano /etc/docker/daemon.json
```
添加或修改以下内容替换为你的加速器地址
```json
{
"registry-mirrors": [
"https://xxxxxx.mirror.aliyuncs.com"
]
}
```
重新加载并重启 Docker
```bash
sudo systemctl daemon-reload
sudo systemctl restart docker
```
验证配置生效
```bash
docker info | grep -A 5 "Registry Mirrors"
```
#### Windows/Mac 配置
Docker Desktop Settings
1. 进入 "Docker Engine" 标签
2. 编辑 JSON 配置添加 `registry-mirrors` 字段
3. 点击 "Apply & Restart"
#### 测试加速效果
```bash
# 从加速器拉取镜像(速度应该明显提升)
docker pull nginx:latest
time docker pull alpine:latest
```
### 阿里云容器镜像服务 (ACR)
阿里云容器镜像服务 (ACR, Container Registry) 是企业级的容器镜像存储和分发平台
- **私有镜像仓库**支持多个命名空间细粒度权限控制
- **镜像构建**云端编译和构建支持自动化 CI/CD
- **镜像扫描**自动检测镜像中的漏洞和恶意代码
- **跨地域复制**支持镜像在多个地域的同步和加速
- **集成 ACK** ACK 无缝集成自动身份认证
- **镜像版本管理**标签管理镜像过期清理保留策略
#### 完整推送/拉取示例
```bash
# 登录阿里云镜像仓库(使用 Docker 登录)
# 使用阿里云账户 ID 和 RAM 访问密钥或密码
docker login registry.cn-hangzhou.aliyuncs.com \
--username=<阿里云账户ID>
# 拉取阿里云公开镜像
docker pull registry.cn-hangzhou.aliyuncs.com/library/nginx:latest
# 构建本地镜像
docker build -t my-app:v1.0 .
# 标记镜像为阿里云仓库地址
docker tag my-app:v1.0 \
registry.cn-hangzhou.aliyuncs.com/myapp/my-app:v1.0
# 推送镜像到阿里云 ACR
docker push registry.cn-hangzhou.aliyuncs.com/myapp/my-app:v1.0
# 在 Dockerfile 中使用 ACR 镜像
FROM registry.cn-hangzhou.aliyuncs.com/myapp/my-app:v1.0
COPY . /app
RUN echo "已成功使用阿里云镜像"
```
#### ACK 集群中使用 ACR 镜像
ACK 集群中需要先配置镜像拉取凭证Secret然后在 Deployment 中引用
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
# 如果是私有镜像,需配置镜像拉取凭证
imagePullSecrets:
- name: acr-secret
containers:
- name: web
image: registry.cn-hangzhou.aliyuncs.com/myapp/web:v2.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
affinity:
# 配置 Pod 反亲和性,分散到不同节点
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
```
#### 创建镜像拉取凭证
ACK 集群中创建 Secret用于拉取私有镜像
```bash
# 创建镜像拉取 Secret
kubectl create secret docker-registry acr-secret \
--docker-server=registry.cn-hangzhou.aliyuncs.com \
--docker-username=<阿里云账户ID> \
--docker-password=<RAM访问密钥或密码> \
--docker-email=<邮箱地址>
# 查看创建的 Secret
kubectl get secret acr-secret
kubectl describe secret acr-secret
```
#### ACR 优势
- ACK 集群中与镜像仓库无缝集成简化身份认证
- 支持 Helm Chart 存储和版本管理方便应用交付
- 提供完整的图形化镜像仓库管理界面
- 完整的审计日志和操作追踪功能
- 支持镜像自动扫描和漏洞报告

View File

@@ -3,3 +3,11 @@
Docker 目前已经得到了众多公有云平台的支持并成为除虚拟机之外的核心云业务
除了 AWSGoogleAzure 国内的各大公有云厂商基本上都同时支持了虚拟机服务和基于 Kubernetes 的容器云业务有的还推出了其他服务例如[容器镜像服务](https://cloud.tencent.com/act/cps/redirect?redirect=11588&cps_key=3a5255852d5db99dcd5da4c72f05df61)让用户在云上享有安全高效的镜像托管、分发等服务。
## 本章内容
* [简介](16.1_intro.md)
* [腾讯云](16.2_tencentCloud.md)
* [阿里云](16.3_alicloud.md)
* [亚马逊云](16.4_aws.md)
* [多云部署策略](16.5_multicloud.md)

View File

@@ -11,3 +11,6 @@
* 利用公有云和 Docker 的特性更加方便的迁移和扩展应用
同时容器将作为与虚拟机类似的业务直接提供给用户使用极大的丰富了应用开发和部署的场景
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -21,8 +21,3 @@ FCOS 使用 rpm-ostree 系统进行事务性升级。无需像 yum 升级那样
#### 容器工具
对于诸如构建复制和其他管理容器的任务FCOS 用一组容器工具代替了 **Docker CLI****podman CLI** 工具支持许多容器运行时功能例如运行启动停止列出和删除容器和镜像**skopeo CLI** 工具可以复制认证和签名镜像您还可以使用 **crictl CLI** 工具来处理 CRI-O 容器引擎中的容器和镜像
### 17.1.2 参考文档
* [官方文档](https://docs.fedoraproject.org/en-US/fedora-coreos/)
* [openshift 官方文档](https://docs.openshift.com/container-platform/4.3/architecture/architecture-rhcos.html)

View File

@@ -47,7 +47,3 @@ $ ssh core@虚拟机IP
$ docker --version
```
### 17.2.6 参考链接
* [官方文档](https://docs.fedoraproject.org/en-US/fedora-coreos/bare-metal/)

Binary file not shown.

View File

@@ -2,10 +2,28 @@
本章将介绍 Docker Kubernetes 之外的容器生态技术
- **Fedora CoreOS**专为容器化工作负载设计的操作系统
- **Podman**兼容 Docker CLI 的下一代无守护进程容器引擎
- **Buildah**无需守护进程的 OCI 容器镜像构建工具
- **Skopeo**远程检查和管理容器镜像的利器
- **containerd**作为现代容器生态基石的核心容器运行时
- **安全容器运行时**通过提供更强隔离性来保证安全的技术方案 Kata ContainersgVisor
- **WebAssembly**一种极具潜力的轻量级跨平台二进制指令格式
## 本章内容
* [Fedora CoreOS 简介](17.1_coreos_intro.md)
* 专为容器化工作负载设计的操作系统
* [Fedora CoreOS 安装与配置](17.2_coreos_install.md)
* CoreOS 的安装方式与基本配置
* [Podman](17.3_podman.md)
* 兼容 Docker CLI 的下一代无守护进程容器引擎
* [Buildah](17.4_buildah.md)
* 无需守护进程的 OCI 容器镜像构建工具
* [Skopeo](17.5_skopeo.md)
* 远程检查和管理容器镜像的利器
* [containerd](17.6_containerd.md)
* 作为现代容器生态基石的核心容器运行时
* [安全容器运行时](17.7_secure_runtime.md)
* 通过提供更强隔离性来保证安全的技术方案 Kata ContainersgVisor
* [WebAssembly](17.8_wasm.md)
* 一种极具潜力的轻量级跨平台二进制指令格式

View File

@@ -28,3 +28,6 @@ Docker 并非容器生态的唯一选择,了解其他工具有助于根据场
- [底层实现](../12_implementation/README.md)容器技术的内核基础
- [安全](../18_security/README.md)容器安全实践
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -1,6 +1,6 @@
## 18.1 内核命名空间
命名空间 (Namespace) Linux 容器隔离的基础它确保了容器内的进程无法直接干扰主机或其他容器虽然在本书第 12 章中我们已经从底层实现的角度介绍了 Namespace但在本节中我们将重点探讨其**安全意义**及相关配置
命名空间 (Namespace) Linux 容器隔离的基础它确保了容器内的进程无法直接干扰主机或其他容器虽然在本书第 12 章中我们已经从底层实现的角度介绍了 Namespace但在本节中我们将重点探讨其 **安全意义** 及相关配置
### 18.1.1 隔离的安全本质
@@ -22,7 +22,7 @@ Docker 守护进程在启动容器时,会在后台为容器创建一套独立
通过命名空间Docker 也能限制进程从外部环境获取信息
例如由于进程环境被隔离进程在内部其实是无法感知到外部宿主机的存在的它既不能获取其他容器的进程列表也无法通过网络与其他系统进行交互除非经过配置
### 18.1.1 用户命名空间 与提权防护
### 18.1.3 用户命名空间与提权防护
在所有的 Namespace **User Namespace** 对安全的影响尤为关键

View File

@@ -1,6 +1,6 @@
## 18.2 控制组
控制组 (Cgroups) Linux 容器机制的另外一个关键组件如果说命名空间 (Namespace) 决定了容器能**看到**什么那么控制组就决定了容器能**使用**多少资源
控制组 (Cgroups) Linux 容器机制的另外一个关键组件如果说命名空间 (Namespace) 决定了容器能 **看到** 什么那么控制组就决定了容器能 **使用** 多少资源
在安全领域中资源的不可用性本身就是一种安全威胁控制组负责实现资源的审计和限制这对于抵御资源耗尽型攻击如拒绝服务攻击 DoS至关重要
@@ -17,7 +17,7 @@
### 18.2.2 核心资源限制实战
为了确保多租户平台如公有或私有的 PaaS 平台的稳定性或者在生产环境防止服务级联故障我们要养成在启动容器时**显式声明资源上限**的习惯
为了确保多租户平台如公有或私有的 PaaS 平台的稳定性或者在生产环境防止服务级联故障我们要养成在启动容器时 **显式声明资源上限** 的习惯
#### 1. 内存限制

View File

@@ -83,4 +83,4 @@ $ docker version
### 18.3.4 结语
保障 Docker 服务端的安全主要是做减法关闭不必要的网络监听点严管 Socket 访问权限而一旦基础系统条件允许**毫不犹豫地在生产环境启用 Rootless 模式**将是一项划算的安全加固选择
保障 Docker 服务端的安全主要是做减法关闭不必要的网络监听点严管 Socket 访问权限而一旦基础系统条件允许**毫不犹豫地在生产环境启用 Rootless 模式** 将是一项划算的安全加固选择

View File

@@ -6,7 +6,7 @@
### 18.4.1 容器内置的 Capability 白名单
在默认情况下即便一个容器是在以 `root` 用户运行Docker 也只为其内核授予了所有可用能力中的**一小部分白名单能力**
在默认情况下即便一个容器是在以 `root` 用户运行Docker 也只为其内核授予了所有可用能力中的 **一小部分白名单能力**
常见的 Linux Capabilities 包含
- `CAP_CHOWN`: 修改文件所有者
@@ -14,7 +14,7 @@
- `CAP_NET_ADMIN`: 网络管理的最高权限例如调整路由配置设置防火墙规则等
- `CAP_SYS_ADMIN`: 被誉为Linux 内核的特权网管允许各种高危操作挂载磁盘访问敏感设备等
为了在**最小特权原则**的指导下加强安全Docker 默认**移除了**大量可能导致容器大范围破坏宿主机的能力例如
为了在 **最小特权原则** 的指导下加强安全Docker 默认 **移除了** 大量可能导致容器大范围破坏宿主机的能力例如
* 完全禁止了任何通过 `CAP_SYS_ADMIN` 进行的核心挂载或设备操作
* 禁止修改内核模块
* 禁止直接访问硬件套接字
@@ -27,7 +27,7 @@
#### 实战场景一构建极限安全的 Web 靶机
假设你正在提供一个公共的 Web 容器你不希望里面的任何恶意脚本修改进程权限或者创建设备节点你可以通过命令先移除**所有**默认能力然后再按需授权该守护进程一个仅仅能绑端口的能力
假设你正在提供一个公共的 Web 容器你不希望里面的任何恶意脚本修改进程权限或者创建设备节点你可以通过命令先移除 **所有** 默认能力然后再按需授权该守护进程一个仅仅能绑端口的能力
```bash
$ docker run -d \
@@ -56,7 +56,7 @@ $ docker run -it --rm \
我们只授予了所需的网络管理控制NET_ADMIN和侦听底层套接字的权限NET_RAW而免去了赋予整个容器终极杀器 `--privileged` 参数
> [!WARNING]
> 大量开发人员遇到了权限遭到拒绝的错误时往往习惯性图省事添加 `--privileged` 这个核选项但这将把**宿主机上一切特权和所有访问设备完全投射给容器内的根用户**其危险性等价于根本没有做隔离请务必查明进程出错的实际原因精准施加必要的隔离 `CAP_*` 能力
> 大量开发人员遇到了权限遭到拒绝的错误时往往习惯性图省事添加 `--privileged` 这个核选项但这将把 **宿主机上一切特权和所有访问设备完全投射给容器内的根用户**其危险性等价于根本没有做隔离请务必查明进程出错的实际原因精准施加必要的隔离 `CAP_*` 能力
### 18.4.3 总结

View File

@@ -85,4 +85,4 @@ Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 1, CRITICAL: 0)
### 18.5.4 容器核心层基石结语
到这里Docker 为保障宿主和容器界限安全的几个护城河**资源剥离限制** (`Cgroups`) **进程/网络/身份蒙蔽** (`Namespace`)**特权能力回收** (`Capabilities`) 再到**内核强制策略拦截管制** (`Seccomp`/`AppArmor`) 已悉数交代完毕虽然绝没有100% 免疫网络穿刺的防线只要开发者牢记 **权限最小化原则** 容器的堡垒就可以做到令攻击者望洋兴叹
到这里Docker 为保障宿主和容器界限安全的几个护城河 **资源剥离限制**(`Cgroups`) **进程/网络/身份蒙蔽**(`Namespace`) **特权能力回收**(`Capabilities`) 再到 **内核强制策略拦截管制**(`Seccomp`/`AppArmor`) 已悉数交代完毕虽然绝没有100% 免疫网络穿刺的防线只要开发者牢记 **权限最小化原则** 容器的堡垒就可以做到令攻击者望洋兴叹

View File

@@ -0,0 +1,556 @@
## 18.6 容器镜像安全扫描与供应链安全
DevOps 流程中容器镜像安全已经成为不容忽视的关键环节从开发构建存储到部署镜像的整个生命周期都需要安全防护本节深入讨论镜像漏洞扫描软件物料清单SBOM镜像签名验证等供应链安全实践
### 18.6.1 容器镜像漏洞扫描工具对比
#### Trivy - 轻量级通用扫描器
Trivy 是由 Aqua Security 开发的开源漏洞扫描器以其轻量级快速准确而闻名已成为业界标准
**优点**
- 零依赖单个二进制文件
- 扫描速度快秒级
- 支持镜像文件系统Git 仓库多种扫描源
- 数据库每日自动更新
- 支持多种输出格式JSON表格SBOM
**安装与基本使用**
```bash
# 安装 Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
# 扫描本地镜像
trivy image nginx:latest
# 生成 JSON 格式报告
trivy image -f json -o report.json nginx:latest
# 扫描文件系统
trivy fs /path/to/project
# 扫描 Git 仓库
trivy repo https://github.com/aquasecurity/trivy
```
** CI/CD 中集成**
```bash
# 设置严重程度过滤
trivy image --severity HIGH,CRITICAL \
--exit-code 1 \
myregistry.com/myapp:v1.0.0
```
#### Grype - 支持多种软件包的扫描器
Grype Anchore 开发支持更广泛的软件包管理器和语言
**优点**
- 支持 JavaPythonGoRubyJavaScript 等多种语言的依赖检测
- SyftSBOM 生成器配合效果好
- 可自定义漏洞数据库源
- 支持离线扫描模式
**安装与使用**
```bash
# 安装 Grype
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
# 扫描镜像
grype docker:nginx:latest
# 与 Syft 配合生成 SBOM
syft docker:nginx:latest -o json > sbom.json
grype sbom:sbom.json
# 扫描特定目录
grype dir:/path/to/app
```
#### Snyk - 完整的安全平台
Snyk 提供了商业级的安全扫描服务特别适合企业环境
**特点**
- 支持开源漏洞和许可证扫描
- 与多个 Git 平台深度集成GitHubGitLabBitbucket
- 提供修复建议和自动化修复 PR
- 支持 Kubernetes 部署后安全监控
**基本使用**
```bash
# 安装 Snyk CLI
npm install -g snyk
# 认证
snyk auth
# 扫描镜像
snyk container test docker-archive://image.tar
# 监控仓库
snyk monitor --docker
```
**工具对比表**
| 特性 | Trivy | Grype | Snyk |
|------|-------|-------|------|
| 零依赖 | | | |
| 离线模式 | | | |
| 许可证扫描 | | | |
| 自动修复 | | | |
| 开源免费 | | | 部分 |
| IDE 集成 | | | |
### 18.6.2 SBOM软件物料清单生成与管理
SBOMSoftware Bill of Materials是一份详细列表记录了软件中使用的所有组件依赖库及其版本信息SBOM 在供应链安全中至关重要特别是在发现新的安全漏洞时能快速定位受影响的应用
#### Syft - SBOM 生成工具
Syft Anchore 推出的专业 SBOM 生成工具
**安装**
```bash
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
```
**生成 SBOM**
```bash
# 从镜像生成 SBOM多种格式
syft docker:nginx:latest -o json > sbom.json
syft docker:nginx:latest -o spdx > sbom.spdx
syft docker:nginx:latest -o cyclonedx > sbom.xml
# 从本地文件系统生成
syft dir:/path/to/app -o json > sbom.json
# 从 OCI 镜像档案生成
syft oci-archive:image.tar -o json > sbom.json
```
#### CycloneDX SPDX 格式
两种主流的 SBOM 格式
**CycloneDX 格式示例**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" version="1">
<components>
<component type="library">
<name>openssl</name>
<version>1.1.1k</version>
<purl>pkg:deb/debian/openssl@1.1.1k-1+deb11u5</purl>
</component>
<component type="library">
<name>curl</name>
<version>7.74.0-1.3+deb11u1</version>
<purl>pkg:deb/debian/curl@7.74.0-1.3+deb11u1</purl>
</component>
</components>
</bom>
```
**SPDX 格式示例**
```json
{
"SPDXID": "SPDXRef-DOCUMENT",
"spdxVersion": "SPDX-2.2",
"creationInfo": {
"created": "2024-03-01T12:00:00Z",
"creators": ["Tool: syft"]
},
"packages": [
{
"SPDXID": "SPDXRef-Package-openssl",
"name": "openssl",
"versionInfo": "1.1.1k",
"downloadLocation": "NOASSERTION"
}
]
}
```
#### SBOM 的应用场景
**漏洞关联**
当新的 CVE 被发现时可快速查询受影响的应用
```bash
# 使用 Grype 针对 SBOM 进行漏洞扫描
grype sbom:sbom.json --add-cpes-if-none
```
**合规性报告**
SBOM 保存为构建产物用于审计和合规性检查
**依赖升级决策**
通过分析 SBOM 中的依赖版本制定安全升级计划
### 18.6.3 镜像签名与验证Cosign/Notary
镜像签名确保镜像的来源可信且未被篡改两种主流方案是 Cosign Notary
#### Cosign - 现代签名解决方案
Cosign Sigstore 项目的核心工具支持无密钥签名适合现代 CI/CD 流程
**安装**
```bash
wget https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign-linux-amd64
sudo mv cosign-linux-amd64 /usr/local/bin/cosign
```
**生成密钥对传统方式**
```bash
cosign generate-key-pair
# 生成 cosign.key 和 cosign.pub
```
**签名镜像**
```bash
# 使用私钥签名(推送到仓库前)
cosign sign --key cosign.key myregistry.com/myapp:v1.0.0
# 系统会提示输入私钥密码
```
**验证签名**
```bash
# 使用公钥验证
cosign verify --key cosign.pub myregistry.com/myapp:v1.0.0
# 输出结果示例
# Verification successful!
# {
# "critical": {
# "identity": {...},
# "image": {...},
# "type": "cosign container image signature"
# },
# "optional": {...}
# }
```
**Keyless 签名推荐用于 CI/CD**
```bash
# 在 GitHub Actions 等 CI 中无需存储密钥
cosign sign --yes myregistry.com/myapp:v1.0.0
# 验证时自动使用 OIDC 令牌验证身份
cosign verify myregistry.com/myapp:v1.0.0 \
--certificate-identity https://github.com/myorg/myrepo/.github/workflows/build.yml@refs/heads/main \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
```
#### Docker Content TrustDCT Notary
Docker Content Trust 使用 Notary 实现镜像签名 Docker 官方的签名解决方案
**启用 DCT**
```bash
# 在环境中启用 DCT
export DOCKER_CONTENT_TRUST=1
# 此后所有 docker push/pull 都需要签名
docker push myregistry.com/myapp:v1.0.0
# 如果镜像未签名,操作会被拒绝
# 禁用 DCT仅用于特定操作
docker push --disable-content-trust myregistry.com/myapp:v1.0.0
```
**签名密钥管理**
```bash
# 首次推送时会提示创建 Delegation Key
# 密钥存储在 ~/.docker/trust/private/root_keys/ 和 ~/.docker/trust/private/tuf_keys/
# 查看签名信息
docker inspect --format='{{.RepoDigests}}' myregistry.com/myapp:v1.0.0
```
### 18.6.4 供应链安全最佳实践
#### 1. 基础镜像安全
```dockerfile
# ❌ 不推荐:使用 latest 标签
FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl
# ✓ 推荐:固定基础镜像版本和摘要
FROM ubuntu:22.04@sha256:a6d2b38300ce017add71440577d5b0a90460d0e6e0e14...(完整 64 位哈希)
RUN apt-get update && apt-get install -y curl=7.68.0-1ubuntu1
```
#### 2. 构建时扫描
Dockerfile 中集成安全扫描
```dockerfile
FROM golang:1.20-alpine AS builder
WORKDIR /app
COPY . .
# 使用 Trivy 扫描源代码
RUN apk add --no-cache curl && \
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin && \
trivy fs . --exit-code 1 --severity HIGH,CRITICAL
RUN go build -o app .
FROM alpine:3.17@sha256:abcd1234...(请替换为实际完整的 64 位摘要哈希)
COPY --from=builder /app/app /app
```
#### 3. 运行时镜像扫描策略
```bash
# 镜像构建完成后立即扫描
trivy image --severity HIGH,CRITICAL \
--exit-code 1 \
--timeout 30m \
$IMAGE_NAME:$IMAGE_TAG
# 定期扫描已部署的镜像
trivy image --scanners vuln,misconfig registry:5000/myapp:latest
```
#### 4. 镜像仓库安全配置
**Harbor私有镜像仓库的安全扫描**
```yaml
# harbor.yml 配置示例
trivy:
enabled: true
# 启用镜像扫描
image_source: "Official"
# 默认扫描配置
scan_on_push: true # 推送时自动扫描
scan_all: true # 扫描仓库中的所有镜像
```
#### 5. 政策执行Admission Controller
Kubernetes 环境中使用 Admission Webhook 强制镜像签名和扫描
```yaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: image-security-policy
webhooks:
- name: image-security.example.com
clientConfig:
service:
name: image-security-webhook
namespace: security
path: "/validate"
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
admissionReviewVersions: ["v1"]
sideEffects: None
```
### 18.6.5 CI/CD 中集成安全扫描
#### GitHub Actions 工作流示例
```yaml
name: Build and Scan Image
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-scan:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: .
push: false
load: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Run Trivy vulnerability scan
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'HIGH,CRITICAL'
- name: Upload Trivy results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
format: cyclonedx-json
output-file: sbom-cyclonedx.json
- name: Upload SBOM
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom-cyclonedx.json
- name: Sign image with Cosign
if: github.event_name == 'push'
run: |
cosign sign --yes ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Login to Registry and Push
if: github.event_name == 'push'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
```
#### GitLab CI 工作流示例
```yaml
stages:
- build
- scan
- sign
- push
variables:
REGISTRY: registry.gitlab.com
IMAGE_NAME: $REGISTRY/$CI_PROJECT_PATH
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t $IMAGE_NAME:$CI_COMMIT_SHA .
- docker save $IMAGE_NAME:$CI_COMMIT_SHA > image.tar
scan:trivy:
stage: scan
image: aquasec/trivy:latest
script:
- trivy image --severity HIGH,CRITICAL --exit-code 1 docker-archive://image.tar
allow_failure: false
scan:grype:
stage: scan
image: anchore/grype:latest
script:
- grype docker-archive://image.tar
generate:sbom:
stage: scan
image: anchore/syft:latest
script:
- syft docker-archive://image.tar -o cyclonedx > sbom.xml
artifacts:
reports:
sbom: sbom.xml
sign:
stage: sign
image: gcr.io/projectsigstore/cosign:latest
script:
- cosign sign --key $COSIGN_KEY $IMAGE_NAME:$CI_COMMIT_SHA
only:
- main
push:
stage: push
image: docker:latest
services:
- docker:dind
script:
- docker load < image.tar
- docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD $REGISTRY
- docker push $IMAGE_NAME:$CI_COMMIT_SHA
only:
- main
```
### 18.6.6 常见问题与最佳实践
**Q: 扫描报告中有过时的 CVE如何处理**
A: 某些 CVE 可能已经被修复但数据库未更新可以
- 手动验证安全补丁是否已应用
- 使用工具的忽略列表功能 Trivy `.trivyignore`
- 定期更新扫描工具和漏洞数据库
**Q: 如何平衡镜像大小和安全性**
A:
- 使用多阶段构建减少最终镜像大小
- 使用精简基础镜像AlpineDistroless
- 定期更新依赖而不是一味求小
- 优先安全性体积次之
**Q: 如何管理和轮换签名密钥**
A:
- 在密钥管理系统 HashiCorp Vault中存储密钥
- 定期轮换密钥建议每 90
- 使用 Keyless 签名消除密钥管理复杂性
- 保留密钥轮换的审计日志

View File

@@ -24,273 +24,27 @@ flowchart LR
end
```
---
## 本章内容
## 核心安全机制
本章涵盖 Docker 安全的多个层面从内核隔离机制到运行时防护和供应链安全
### 1. 命名空间
* [内核命名空间](18.1_kernel_ns.md)
* 命名空间的安全意义User Namespace 与提权防护
提供进程网络文件系统等资源的隔离
* [控制组](18.2_control_group.md)
* 通过 Cgroups 限制容器资源使用防止资源耗尽攻击
| Namespace | 隔离内容 | 安全作用 |
|-----------|---------|---------|
| PID | 进程 | 容器看不到其他进程 |
| NET | 网络 | 独立网络栈 |
| MNT | 文件系统 | 独立的根目录 |
| USER | 用户 | 容器 root 宿主机 root |
| IPC | 进程通信 | 隔离共享内存 |
| UTS | 主机名 | 独立主机名 |
* [服务端防护](18.3_daemon_sec.md)
* Docker 守护进程的安全配置与网络访问控制
详见[命名空间](../12_implementation/12.2_namespace.md)章节
* [内核能力机制](18.4_kernel_capability.md)
* Linux Capabilities 的细粒度权限控制
### 2. 控制组
* [其它安全特性](18.5_other_feature.md)
* 镜像安全漏洞扫描签名验证运行时安全 root 运行只读文件系统SeccompAppArmorDockerfile 安全实践软件供应链安全SBOMSLSA
限制容器的资源使用防止资源耗尽攻击
```bash
## 限制内存(超出会被 OOM Kill
$ docker run -m 512m myapp
## 限制 CPU
$ docker run --cpus=1.5 myapp
## 限制磁盘 I/O
$ docker run --device-write-bps /dev/sda:10mb myapp
```
### 3. 能力机制
Linux root 权限拆分为多个细粒度的能力Docker 默认禁用危险能力
| 能力 | 说明 | 默认状态 |
|------|------|---------|
| `CAP_NET_ADMIN` | 网络管理 | 禁用 |
| `CAP_SYS_ADMIN` | 系统管理 | 禁用 |
| `CAP_SYS_PTRACE` | 进程追踪 | 禁用 |
| `CAP_CHOWN` | 更改文件所有者 | 启用 |
| `CAP_NET_BIND_SERVICE` | 绑定低端口 | 启用 |
```bash
## 删除所有能力,只添加需要的
$ docker run --cap-drop=all --cap-add=NET_BIND_SERVICE myapp
## 查看容器的能力
$ docker exec myapp cat /proc/1/status | grep Cap
```
---
## 镜像安全
### 使用可信镜像
```bash
## ✅ 使用官方镜像
$ docker pull nginx
## ✅ 使用经过验证的镜像
$ docker pull bitnami/nginx
## ⚠️ 谨慎使用未知来源镜像
$ docker pull randomuser/suspicious-image
```
### 漏洞扫描
扫描镜像中的已知安全漏洞
```bash
## Docker Scout官方工具
$ docker scout cves nginx:latest
$ docker scout recommendations nginx:latest
## Trivy开源工具
$ trivy image nginx:latest
## Snyk商业工具
$ snyk container test nginx:latest
```
### 镜像签名验证
当前更推荐使用 Sigstore / Notation 体系进行镜像签名`Docker Content Trust (DCT)` 已进入退场阶段不建议作为新项目主方案
> 注意Cosign 默认会把签名写回镜像所在仓库请使用你有推送权限的镜像地址
```bash
## 准备示例镜像
$ export IMAGE=<你的仓库地址>/myimage:latest
$ docker pull nginx:1.27
$ docker tag nginx:1.27 $IMAGE
$ docker push $IMAGE
## 生成签名密钥(会生成 cosign.key / cosign.pub
$ cosign generate-key-pair
## Cosign: 签名与验证
$ cosign sign --key cosign.key $IMAGE
$ cosign verify --key cosign.pub $IMAGE
```
---
## 运行时安全
### 1. root 用户运行
> 笔者强调这是最重要的安全实践之一
```dockerfile
FROM node:22-alpine
## 创建非 root 用户
RUN addgroup -g 1001 appgroup && \
adduser -u 1001 -G appgroup -D appuser
## 设置工作目录权限
WORKDIR /app
COPY --chown=appuser:appgroup . .
## 切换用户
USER appuser
CMD ["node", "server.js"]
```
或在运行时指定
```bash
$ docker run -u 1001:1001 myapp
```
### 2. 只读文件系统
```bash
## 根文件系统只读
$ docker run --read-only myapp
## 需要写入的目录使用 tmpfs
$ docker run --read-only --tmpfs /tmp --tmpfs /var/run myapp
```
### 3. 禁用特权模式
```bash
## ❌ 绝对不要在生产环境使用
$ docker run --privileged myapp
## ✅ 只添加必要的能力
$ docker run --cap-add=SYS_TIME myapp
```
### 4. 限制资源
```bash
$ docker run \
-m 512m \ # 内存限制
--cpus=1 \ # CPU 限制
--pids-limit=100 \ # 进程数限制
--ulimit nofile=1024:1024 \ # 文件描述符限制
myapp
```
### 5. 网络隔离
```bash
## 禁用网络(适用于不需要网络的任务)
$ docker run --network=none myapp
## 使用自定义网络隔离
$ docker network create --internal isolated_net
$ docker run --network=isolated_net myapp
```
---
## Dockerfile 安全实践
### 1. 使用精简基础镜像
```dockerfile
## ✅ 好:使用精简镜像
FROM node:22-alpine # ~50MB
FROM gcr.io/distroless/nodejs # ~20MB
## ❌ 差:使用完整镜像
FROM node:22 # ~1GB
FROM ubuntu:24.04 # ~78MB
```
### 2. 多阶段构建
```dockerfile
## 构建阶段
FROM node:22 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
## 生产阶段(不包含开发依赖和源码)
FROM node:22-alpine
COPY --from=builder /app/dist /app
USER node
CMD ["node", "/app/server.js"]
```
### 3. 不存储敏感信息
```dockerfile
## ❌ 错误:敏感信息写入镜像
ENV DB_PASSWORD=secret123
COPY .env /app/
## ✅ 正确:运行时传入
## docker run -e DB_PASSWORD=xxx 或使用 Docker Secrets
...
```
### 4. 固定依赖版本
```dockerfile
## ✅ 固定版本
FROM node:22.12.0-alpine3.21
RUN apk add --no-cache curl=8.5.0-r0
## ❌ 使用 latest
FROM node:latest
RUN apk add curl
```
---
* [镜像安全](18.6_image_security.md)
* 容器镜像的安全扫描漏洞检测与签名验证
## 安全扫描清单
@@ -306,89 +60,3 @@ RUN apk add curl
| 最小能力 | 检查 `--cap-drop=all` |
| 网络隔离 | 检查网络配置 |
| 敏感信息 | 确认无硬编码密码 |
---
## 高级安全方案
### Seccomp 系统调用过滤
限制容器可以使用的系统调用
```bash
$ docker run --security-opt seccomp=/path/to/profile.json myapp
```
### AppArmor / SELinux
使用强制访问控制
```bash
$ docker run --security-opt apparmor=docker-default myapp
```
### 安全容器 (gVisor / Kata)
需要更强隔离时
```bash
## 使用 gVisor 运行时
$ docker run --runtime=runsc myapp
```
---
## 软件供应链安全
随着软件供应链攻击日益频繁仅保障运行时安全已不足够
### 1. SBOM (软件物料清单)
SBOM 类似于食品的配料表列出了容器镜像中包含的所有软件包及其版本
- **生成 SBOM**使用 `docker buildx build --sbom` `docker scout sbom`
- **管理 SBOM**确保持续监控 SBOM 中的组件是否存在新披露的漏洞
### 2. 镜像签名 (Sigstore / Notary v2)
确保镜像在构建后未被篡改且确实来自可信的发布者
- **Cosign**Sigstore 项目的一部分用于签署和验证容器镜像
```bash
## 使用有写权限的仓库地址
$ export IMAGE=<你的仓库地址>/myimage:tag
$ docker pull nginx:1.27
$ docker tag nginx:1.27 $IMAGE
$ docker push $IMAGE
## 生成签名密钥(会生成 cosign.key / cosign.pub
$ cosign generate-key-pair
## 签署与验证镜像
$ cosign sign --key cosign.key $IMAGE
$ cosign verify --key cosign.pub $IMAGE
```
### 3. SLSA (Supply-chain Levels for Software Artifacts)
遵循 SLSA 框架确保构建过程的完整性例如使用 GitHub Actions 等受控环境进行构建而非在开发者本地机器上构建发布
---
## 本章小结
| 安全措施 | 重要程度 | 实现方式 |
|---------|---------|---------|
| root 运行 | | `USER` 指令 |
| 漏洞扫描 | | `docker scout`, `trivy` |
| 资源限制 | | `-m`, `--cpus` |
| 只读文件系统 | | `--read-only` |
| 最小能力 | | `--cap-drop=all` |
| 镜像签名 | | `cosign` / Notation |
## 延伸阅读
- [命名空间](../12_implementation/12.2_namespace.md)隔离机制详解
- [控制组](../12_implementation/12.3_cgroups.md)资源限制详解
- [最佳实践](../appendix/best_practices.md)Dockerfile 安全配置

View File

@@ -5,3 +5,6 @@ Docker 的安全性依赖于多层隔离机制的协同工作,同时需要用
总体来看Docker 容器还是十分安全的特别是在容器内不使用 root 权限来运行进程的话
另外用户可以使用现有工具比如 [Apparmor](https://docs.docker.com/engine/security/apparmor/)[Seccomp](https://docs.docker.com/engine/security/seccomp/)SELinuxGRSEC 来增强安全性;甚至自己在内核中实现更复杂的安全机制。
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

View File

@@ -89,7 +89,7 @@ services:
- monitoring
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
image: ghcr.io/google/cadvisor:latest
ports:
- "8080:8080"
volumes:

View File

@@ -22,10 +22,11 @@ ELK (ElasticsearchLogstashKibana) 是目前业界最流行的开源日志
```yaml
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
image: docker.elastic.co/elasticsearch/elasticsearch:8.17.0
container_name: elasticsearch
environment:
- "discovery.type=single-node"
- "xpack.security.enabled=false"
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ports:
- "9200:9200"
@@ -35,7 +36,7 @@ services:
- logging
kibana:
image: docker.elastic.co/kibana/kibana:7.17.0
image: docker.elastic.co/kibana/kibana:8.17.0
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
@@ -47,7 +48,7 @@ services:
- logging
fluentd:
image: fluent/fluentd-kubernetes-daemonset:v1.14.3-debian-elasticsearch7-1.0
image: fluent/fluentd-kubernetes-daemonset:v1.17-debian-elasticsearch8-1
container_name: fluentd
environment:
- "FLUENT_ELASTICSEARCH_HOST=elasticsearch"

View File

@@ -0,0 +1,632 @@
## 19.3 容器性能优化与故障诊断
容器的轻量级特性不代表性能问题会自动消失在实际运维中性能瓶颈可能来自 CPU 限制内存溢出磁盘 I/O网络拥塞等多个层面本节深入讨论容器性能监控诊断方法和优化策略
### 19.3.1 容器性能监控指标
#### 核心性能指标体系
容器性能监控涉及以下关键指标
**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`文件系统使用量
### 19.3.2 使用 docker stats 实时监控
`docker stats` 是最基础但强大的监控工具提供实时的容器资源使用情况
**基本使用**
```bash
# 实时监控所有运行中的容器
docker stats
# 输出示例:
# CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
# abc123def456 nginx 0.45% 24.3 MiB / 256 MiB 9.49% 1.2kB / 3.4kB 0 B / 0 B
# def789ghi012 redis 0.23% 12.5 MiB / 512 MiB 2.44% 2.1kB / 1.5kB 0 B / 0 B
# 只监控特定容器
docker stats nginx redis
# 一次性输出不进入交互模式
docker stats --no-stream
# 指定刷新间隔(单位:秒,默认 1 秒)
docker stats --no-stream --interval 2
# 格式化输出(使用 Go 模板)
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" --no-stream
# 导出为 JSON 格式用于日志记录
docker stats --format json --no-stream > stats.json
```
**在脚本中使用**
```bash
#!/bin/bash
# 持续监控并记录到文件
while true; do
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
docker stats --no-stream --format "{{.Container}},{{.CPUPerc}},{{.MemUsage}}" | \
awk -v ts="$timestamp" '{print ts","$0}' >> container_stats.log
sleep 10
done
```
**性能指标解读**
```bash
# CPU % 超过 80%:需要增加 CPU 限制或优化应用
# MEM % 接近 100%:容器即将 OOM需要增加内存或排查内存泄漏
# 如果 NET I/O 中 dropped 为非零:网络拥塞或丢包
```
### 19.3.3 cAdvisor 容器监控系统
cAdvisor Google 开发的容器监控工具提供比 `docker stats` 更详细的性能数据
**Docker Compose 部署 cAdvisor**
```yaml
services:
cadvisor:
image: ghcr.io/google/cadvisor:v0.51.0
container_name: cadvisor
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
privileged: true
devices:
- /dev/kmsg
networks:
- monitoring
networks:
monitoring:
driver: bridge
```
启动后访问 `http://localhost:8080` 查看
- 容器性能统计
- 系统资源使用情况
- 历史性能数据
** cAdvisor 提取指标**
```bash
# 获取所有容器的 JSON 格式性能数据
curl http://localhost:8080/api/v1.3/machine | jq .
# 获取特定容器信息
curl http://localhost:8080/api/v1.3/docker | jq '.docker | keys' | head -5
# 获取容器统计信息
curl http://localhost:8080/api/v1.3/docker/abc123/ | jq '.stats[-1]'
```
** Prometheus 集成**
```yaml
# prometheus.yml 配置
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'cadvisor'
static_configs:
- targets: ['localhost:8080']
metrics_path: '/metrics'
```
### 19.3.4 Prometheus 容器监控配置
使用 Prometheus node-exporter 进行长期的容器性能监控
**完整监控栈部署**
```yaml
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
networks:
- monitoring
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
networks:
- monitoring
cadvisor:
image: ghcr.io/google/cadvisor:v0.51.0
container_name: cadvisor
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
privileged: true
networks:
- monitoring
grafana:
image: grafana/grafana:latest
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_INSTALL_PLUGINS=grafana-piechart-panel
volumes:
- grafana_data:/var/lib/grafana
networks:
- monitoring
volumes:
prometheus_data:
grafana_data:
networks:
monitoring:
driver: bridge
```
**Prometheus 配置文件prometheus.yml**
```yaml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'docker'
static_configs:
- targets: ['localhost:9323']
```
**常用的 Prometheus 查询PromQL**
```promql
# 容器 CPU 使用百分比
rate(container_cpu_usage_seconds_total[5m]) * 100
# 容器内存使用百分比
(container_memory_usage_bytes / container_spec_memory_limit_bytes) * 100
# 容器网络入站流量MB/s
rate(container_network_receive_bytes_total[5m]) / 1024 / 1024
# 容器网络出站流量MB/s
rate(container_network_transmit_bytes_total[5m]) / 1024 / 1024
# 容器磁盘读取速率MB/s
rate(container_fs_io_current[5m]) / 1024 / 1024
# CPU 限流情况
rate(container_cpu_cfs_throttled_seconds_total[5m])
# 内存缓存占比
container_memory_cache_bytes / container_memory_usage_bytes
# 按镜像统计容器数
count(container_memory_usage_bytes) by (image)
```
### 19.3.5 容器 OOM 排查与内存限制调优
#### OOM 问题诊断
```bash
# 检查容器是否因 OOM 被杀死
docker inspect <container_id> | grep OOMKilled
# 查看容器退出码137 表示被 OOM 杀死
docker ps -a --format "{{.ID}}\t{{.Status}}" | grep "137"
# 查看容器日志中的 OOM 信息
docker logs <container_id> 2>&1 | grep -i "out of memory\|oom"
# 从宿主机日志查看 OOM 事件
dmesg | grep -i "oom\|kill"
journalctl -u docker -n 100 | grep -i "oom"
```
#### 内存泄漏检测
使用专项工具分析应用内存使用
**Python 应用内存泄漏检测**
```python
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt memory_profiler tracemalloc
COPY app.py .
CMD ["python", "-m", "memory_profiler", "app.py"]
```
```python
# app.py - 内存泄漏示例
from memory_profiler import profile
import tracemalloc
@profile
def memory_leak():
# 不断创建未释放的列表
data = []
while True:
data.append([0] * 1000000)
print(f"List size: {len(data)}")
# 使用 tracemalloc 跟踪内存分配
tracemalloc.start()
# 执行可能泄漏的代码
# ...
current, peak = tracemalloc.get_traced_memory()
print(f"Current: {current / 1024 / 1024:.2f} MB")
print(f"Peak: {peak / 1024 / 1024:.2f} MB")
```
**Java 应用内存分析**
```bash
# 在容器中启用 JVM 远程调试
docker run -e JAVA_OPTS="-Xmx512m -Xms256m -XX:+UseG1GC" \
-p 5005:5005 \
myapp:latest
# 使用 jstat 检查垃圾回收情况
jstat -gc <pid> 1000 # 每秒采样一次
# 输出示例:
# S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU
# 6144 6144 0 6144 39424 12288 149504 84320 50552 47689 6464 5989
```
#### 内存限制最佳实践
```bash
# 为容器设置内存限制
docker run -m 512m --memory-swap 1g myapp:latest
# 参数说明:
# -m / --memory内存限制这里是 512MB
# --memory-swap内存+SWAP 总额(这里是 1GB意味着 SWAP 为 512MB
# 如果不设置 --memory-swap则等于 --memory 值
# Docker Compose 配置
services:
app:
image: myapp:latest
deploy:
resources:
limits:
memory: 512M
reservations:
memory: 256M
```
**内存超额提交Memory Overcommit**
```bash
# 在 Docker Compose 中区分限制和预留
# limits绝不能超过的最大值
# reservationsCompose 排期时的参考值
services:
web:
memory: 512M # 限制
memswap_limit: 1G # SWAP 限制
db:
memory: 2G
memory_reservation: 1G # 预留 1GB允许突发到 2GB
```
### 19.3.6 镜像体积优化与多阶段构建
#### 镜像体积分析工具
**使用 dive 分析镜像层**
```bash
# 安装 dive
wget https://github.com/wagoodman/dive/releases/download/v0.11.0/dive_0.11.0_linux_amd64.deb
sudo apt install ./dive_0.11.0_linux_amd64.deb
# 分析镜像
dive myapp:latest
# 输出详细的分层信息,显示每一层的大小和内容
```
**使用 Dockerfile 分析工具**
```bash
# 安装 hadolint
curl https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64 -L -o hadolint
chmod +x hadolint
# 检查 Dockerfile 最佳实践
./hadolint Dockerfile
```
#### 多阶段构建最佳实践
**Go 应用的最小化镜像构建**
```dockerfile
# Stage 1: 构建阶段
FROM golang:1.20-alpine AS builder
WORKDIR /build
# 安装依赖
RUN apk add --no-cache git ca-certificates tzdata
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# 构建静态二进制(支持 scratch 基础镜像)
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
-a -installsuffix cgo \
-ldflags="-w -s" \
-o app .
# Stage 2: 运行阶段
FROM scratch
# 从 builder 复制必要的文件
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /build/app /app
EXPOSE 8080
ENTRYPOINT ["/app"]
# 最终镜像大小通常 < 15MB相比 golang:1.20-alpine 的 ~1GB
```
**Node.js 应用的多阶段构建**
```dockerfile
# Stage 1: 依赖安装
FROM node:18-alpine AS dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && \
npm cache clean --force
# Stage 2: 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 3: 运行阶段
FROM node:18-alpine
WORKDIR /app
# 从依赖阶段复制 node_modules
COPY --from=dependencies /app/node_modules ./node_modules
# 从构建阶段复制构建产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
# 删除开发依赖和不必要的文件
RUN rm -rf src tests *.config.js
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]
# 镜像大小对比:
# 不优化:~500MB
# 多阶段构建后:~120MB减少 76%
```
**Python 应用的多阶段构建**
```dockerfile
# Stage 1: 构建阶段
FROM python:3.11-slim AS builder
WORKDIR /build
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
&& rm -rf /var/apt/lists/*
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# Stage 2: 运行阶段
FROM python:3.11-slim
WORKDIR /app
# 从 builder 复制虚拟环境
COPY --from=builder /root/.local /root/.local
# 设置 PATH
ENV PATH=/root/.local/bin:$PATH \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1
COPY . .
USER nobody
EXPOSE 5000
CMD ["python", "app.py"]
```
#### 镜像体积优化检查清单
```bash
# 检查清单
□ 使用精简基础镜像Alpine、Distroless
□ 清理包管理器缓存apt-get clean、rm -rf /var/cache/*
□ 在同一 RUN 指令中安装和清理依赖
□ 使用 .dockerignore 排除不必要的文件
□ 多阶段构建避免构建依赖污染最终镜像
□ 去除调试符号:-ldflags="-w -s"Go、strip 命令C/C++
□ 压缩静态资源和应用文件
□ 使用 BuildKit 缓存优化加速构建
# 优化示例:
FROM ubuntu:22.04
# ❌ 不推荐
RUN apt-get update
RUN apt-get install -y curl wget git
RUN apt-get clean
# ✓ 推荐
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
wget \
git && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
```
### 19.3.7 常见性能问题及解决方案
**问题 1: 容器频繁被 OOM 杀死**
症状容器进程被无故杀死exit code 137
解决方案
```bash
# 增加内存限制
docker update -m 1g <container_id>
# 排查内存泄漏
docker exec <container_id> ps aux | grep -E "VSZ|RSS"
# 使用 docker stats 实时监控
docker stats <container_id>
# 启用内存交换(作为最后手段)
docker run -m 512m --memory-swap 1g myapp:latest
```
**问题 2: CPU 被限流CPU Throttling**
症状应用性能突然下降 CPU 使用率不高
诊断
```bash
# 查看 CPU 限流统计
docker exec <container_id> cat /sys/fs/cgroup/cpu/cpu.stat
# 如果 throttled_time > 0说明发生了 CPU 限流
# 解决方案:增加 CPU 限制
docker update --cpus 2 <container_id>
```
**问题 3: 网络丢包或延迟高**
诊断
```bash
# 进入容器检查网络状态
docker exec <container_id> ip -s link show
# 检查路由和 DNS
docker exec <container_id> cat /etc/resolv.conf
# 测试网络延迟
docker exec <container_id> ping 8.8.8.8
# 检查容器网络驱动
docker inspect <container_id> | grep -A 10 NetworkSettings
# 解决方案:更换网络驱动或调整 MTU
docker run --net=host myapp:latest # 使用宿主机网络(性能最佳)
```

View File

@@ -9,9 +9,20 @@
- **容器监控** Prometheus 为主讲解如何采集和展示容器性能指标
- **日志管理** ELK (Elasticsearch, Logstash, Kibana) 套件为例介绍集中式日志收集平台
为了让读者能够在生产环境中真正用起来本章会补齐以下最小闭环
为了让读者能够在生产环境中真正用起来本章会补齐以下最小闭环
* 关键指标与日志的验证方法
* 常见故障排查路径
* 最小告警闭环 (Prometheus -> Alertmanager -> 接收端)
* 日志容量治理的最小实践
## 本章内容
* [Prometheus 监控](19.1_prometheus.md)
* 容器监控基础指标采集与告警配置
* [ELK 日志管理](19.2_elk.md)
* 集中式日志收集存储与检索
* [性能优化](19.3_performance_optimization.md)
* 容器和应用性能优化实践

View File

@@ -5,9 +5,9 @@
* **指标监控** Prometheus + Grafana 为主完成指标采集存储与可视化
* **日志管理** EFK/ELK 为例完成容器日志的集中采集检索与分析
生产环境中建议将可观测性当成一个完整闭环**采集 -> 存储 -> 展示 -> 告警 -> 排错 -> 容量治理**
生产环境中建议将可观测性当成一个完整闭环**采集 -> 存储 -> 展示 -> 告警 -> 排错 -> 容量治理**
## 19.3 Docker 日志驱动
## 扩展阅读Docker 日志驱动
Docker 提供了多种日志驱动 (Log Driver)用于将容器标准输出的日志转发到不同后端
@@ -47,3 +47,6 @@ Docker 提供了多种日志驱动 (Log Driver),用于将容器标准输出的
* Elasticsearch 数据目录已持久化并有明确的日志保留周期与容量上限策略
* Kibana 能查询到最新日志 UI 异常时能用 Elasticsearch API 验证入库
* 可观测性组件未直接暴露到公网访问已加鉴权或置于内网
---
> 📝 **发现错误或有改进建议** 欢迎提交 [Issue](https://github.com/yeasy/docker_practice/issues) 或 [PR](https://github.com/yeasy/docker_practice/pulls)。

Some files were not shown because too many files have changed in this diff Show More