mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-03-11 12:21:17 +00:00
Fix format issue
This commit is contained in:
@@ -10,17 +10,19 @@ Docker 镜像作为容器运行的基石,其设计理念和实现机制至关
|
||||
|
||||
我们都知道,操作系统分为**内核**和**用户空间**:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 用户空间 │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ 应用程序、工具、库、配置文件... │ │
|
||||
│ │ (这部分被打包成 Docker 镜像) │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Linux 内核 │
|
||||
│ (容器共享宿主机的内核) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph UserSpace ["用户空间"]
|
||||
direction TB
|
||||
App["应用程序、工具、库、配置文件...<br/>(这部分被打包成 Docker 镜像)"]
|
||||
end
|
||||
|
||||
subgraph KernelSpace ["Linux 内核"]
|
||||
direction TB
|
||||
Kernel["容器共享宿主机的内核"]
|
||||
end
|
||||
|
||||
UserSpace --- KernelSpace
|
||||
```
|
||||
|
||||
对于 Linux 而言,内核启动后会挂载 `root` 文件系统来提供用户空间支持。**Docker 镜像**本质上就是一个 `root` 文件系统。
|
||||
@@ -52,28 +54,29 @@ Docker 镜像是一个特殊的文件系统,包含:
|
||||
|
||||
假设你有三个应用,都基于 Ubuntu 运行:
|
||||
|
||||
```
|
||||
传统方式(不分层):
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ App A │ │ App B │ │ App C │
|
||||
│ Ubuntu │ │ Ubuntu │ │ Ubuntu │
|
||||
│ 500MB │ │ 500MB │ │ 500MB │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
总计:1.5GB ❌
|
||||
|
||||
Docker 分层方式:
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ App A │ │ App B │ │ App C │
|
||||
│ 50MB │ │ 30MB │ │ 40MB │
|
||||
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
||||
│ │ │
|
||||
└────────────────┼────────────────┘
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ Ubuntu │
|
||||
│ (共享)500MB │
|
||||
└─────────────────┘
|
||||
总计:620MB ✅
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph Traditional ["传统方式(不分层)总计: 1.5GB ❌"]
|
||||
direction LR
|
||||
AppA_Trad["App A<br/>Ubuntu 500MB"]
|
||||
AppB_Trad["App B<br/>Ubuntu 500MB"]
|
||||
AppC_Trad["App C<br/>Ubuntu 500MB"]
|
||||
end
|
||||
|
||||
subgraph DockerLayered ["Docker 分层方式 总计: 620MB ✅"]
|
||||
direction TB
|
||||
subgraph Apps ["应用层"]
|
||||
direction LR
|
||||
AppA["App A 50MB"]
|
||||
AppB["App B 30MB"]
|
||||
AppC["App C 40MB"]
|
||||
end
|
||||
Ubuntu["Ubuntu<br/>(共享)500MB"]
|
||||
|
||||
AppA --> Ubuntu
|
||||
AppB --> Ubuntu
|
||||
AppC --> Ubuntu
|
||||
end
|
||||
```
|
||||
|
||||
#### 分层是如何工作的?
|
||||
@@ -89,16 +92,14 @@ COPY app.conf /etc/nginx/ # 第 4 层:复制配置文件
|
||||
|
||||
构建后的镜像结构:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ 第 4 层: COPY app.conf (只读) │ ← 最新添加的层
|
||||
├─────────────────────────────────────┤
|
||||
│ 第 3 层: nginx 安装文件 (只读) │
|
||||
├─────────────────────────────────────┤
|
||||
│ 第 2 层: apt 缓存更新 (只读) │
|
||||
├─────────────────────────────────────┤
|
||||
│ 第 1 层: Ubuntu 基础系统 (只读) │ ← 基础镜像层
|
||||
└─────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Layer4["第 4 层: COPY app.conf (只读)<br/>← 最新添加的层"]
|
||||
Layer3["第 3 层: nginx 安装文件 (只读)"]
|
||||
Layer2["第 2 层: apt 缓存更新 (只读)"]
|
||||
Layer1["第 1 层: Ubuntu 基础系统 (只读)<br/>← 基础镜像层"]
|
||||
|
||||
Layer4 --> Layer3 --> Layer2 --> Layer1
|
||||
```
|
||||
|
||||
每一层的特点:
|
||||
|
||||
@@ -14,24 +14,17 @@
|
||||
|
||||
> 💡 **笔者认为,理解这一点是理解 Docker 的关键****容器的本质是一个特殊的进程。**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 普通进程 │
|
||||
│ • 与其他进程共享系统资源 │
|
||||
│ • 可以看到其他进程 │
|
||||
│ • 共享网络和文件系统 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 容器进程 │
|
||||
│ ┌───────────────────────────────────────────────────────┐ │
|
||||
│ │ • 有自己的进程空间(看不到宿主机上的其他进程) │ │
|
||||
│ │ • 有自己的网络(独立 IP、端口) │ │
|
||||
│ │ • 有自己的文件系统(独立的 root 目录) │ │
|
||||
│ │ • 有自己的用户(容器内的 root ≠ 宿主机的 root) │ │
|
||||
│ └───────────────────────────────────────────────────────┘ │
|
||||
│ 但仍然运行在宿主机的内核上 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph NormalProcess ["普通进程"]
|
||||
direction TB
|
||||
N1["• 与其他进程共享系统资源<br/>• 可以看到其他进程<br/>• 共享网络和文件系统"]
|
||||
end
|
||||
|
||||
subgraph ContainerProcess ["容器进程 (运行在宿主机内核上)"]
|
||||
direction TB
|
||||
C1["• 有自己的进程空间(看不到宿主机上的其他进程)<br/>• 有自己的网络(独立 IP、端口)<br/>• 有自己的文件系统(独立的 root 目录)<br/>• 有自己的用户(容器内的 root ≠ 宿主机的 root)"]
|
||||
end
|
||||
```
|
||||
|
||||
这种隔离是通过 Linux 内核的 **Namespace** 技术实现的。
|
||||
@@ -40,21 +33,35 @@
|
||||
|
||||
很多初学者会混淆容器和虚拟机。笔者用一张图来说明:
|
||||
|
||||
```
|
||||
虚拟机 容器
|
||||
┌───────────────────────┐ ┌───────────────────────┐
|
||||
│ App A │ App B │ │ App A │ App B │
|
||||
├────────────┼──────────┤ ├────────────┼──────────┤
|
||||
│ Guest OS │ Guest OS │ │ Container │ Container│
|
||||
│ (完整系统) │ (完整系统)│ │ (仅应用) │ (仅应用) │
|
||||
├────────────┴──────────┤ └────────────┴──────────┤
|
||||
│ Hypervisor │ │ Docker Engine │
|
||||
├───────────────────────┤ ├───────────────────────┤
|
||||
│ Host OS │ │ Host OS │
|
||||
├───────────────────────┤ ├───────────────────────┤
|
||||
│ Hardware │ │ Hardware │
|
||||
└───────────────────────┘ └───────────────────────┘
|
||||
每个 VM 运行完整 OS 所有容器共享宿主机内核
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph VM ["虚拟机 (每个 VM 运行完整 OS)"]
|
||||
direction TB
|
||||
subgraph VMApp ["应用层"]
|
||||
VA[App A] & VB[App B]
|
||||
end
|
||||
subgraph VMGuest ["Guest OS (完整系统)"]
|
||||
G1[Guest OS] & G2[Guest OS]
|
||||
end
|
||||
V[Hypervisor]
|
||||
VMH[Host OS]
|
||||
VMHW[Hardware]
|
||||
VMApp --> VMGuest --> V --> VMH --> VMHW
|
||||
end
|
||||
|
||||
subgraph Container ["容器 (所有容器共享宿主机内核)"]
|
||||
direction TB
|
||||
subgraph CApp ["应用层"]
|
||||
CA[App A] & CB[App B]
|
||||
end
|
||||
subgraph CContainer ["隔离层"]
|
||||
CC1[Container 仅应用] & CC2[Container 仅应用]
|
||||
end
|
||||
CE[Docker Engine]
|
||||
CH[Host OS]
|
||||
CHW[Hardware]
|
||||
CApp --> CContainer --> CE --> CH --> CHW
|
||||
end
|
||||
```
|
||||
|
||||
| 特性 | 容器 | 虚拟机 |
|
||||
@@ -73,19 +80,15 @@
|
||||
|
||||
当容器运行时,Docker 会在镜像的只读层之上创建一个**可写层**(容器存储层):
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 容器存储层(可读写) │ ← 容器运行时创建
|
||||
│ 运行时产生的文件变化记录在这里 │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 镜像第 N 层(只读) │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 镜像第 N-1 层(只读) │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ ... │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ 镜像第 1 层(只读) │ ← 基础镜像层
|
||||
└─────────────────────────────────────────────┘
|
||||
```mermaid
|
||||
flowchart TD
|
||||
ContainerLayer["容器存储层(可读写)<br/>容器运行时创建,记录文件变化"]
|
||||
ImageLayerN["镜像第 N 层(只读)"]
|
||||
ImageLayerN1["镜像第 N-1 层(只读)"]
|
||||
Dots["..."]
|
||||
ImageLayer1["镜像第 1 层(只读)<br/>基础镜像层"]
|
||||
|
||||
ContainerLayer --> ImageLayerN --> ImageLayerN1 --> Dots --> ImageLayer1
|
||||
```
|
||||
|
||||
#### Copy-on-Write(写时复制)
|
||||
@@ -143,34 +146,25 @@ $ docker run -v /host/path:/container/path nginx
|
||||
|
||||
### 容器的生命周期
|
||||
|
||||
掌握容器的生命周期对于管理和调试 Docker 应用非常重要。下图展示了容器从创建到删除的完整状态流转。
|
||||
掌握容器的生命周期对于管理和调试 Docker 应用非常重要。如图 2-1 所示,容器会经历从创建到删除的完整状态流转。
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
direction TB
|
||||
[*] --> Created : docker create
|
||||
Created --> Running : docker start
|
||||
Running --> Stopped : docker stop
|
||||
Running --> Paused : docker pause
|
||||
Paused --> Running : docker unpause
|
||||
|
||||
Created --> Deleted : docker rm
|
||||
Stopped --> Deleted : docker rm
|
||||
Paused --> Deleted : docker rm
|
||||
|
||||
Deleted --> [*]
|
||||
```
|
||||
┌──────────────────────────────────────────────────┐
|
||||
│ 容器生命周期 │
|
||||
└──────────────────────────────────────────────────┘
|
||||
|
||||
docker create docker start docker stop
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ Created │───────────▶│ Running │───────────▶│ Stopped │
|
||||
└─────────┘ └─────────┘ └─────────┘
|
||||
│ │ │
|
||||
│ │ docker pause │
|
||||
│ ▼ │
|
||||
│ ┌─────────┐ │
|
||||
│ │ Paused │ │
|
||||
│ └─────────┘ │
|
||||
│ │ │
|
||||
│ docker rm │ docker rm │
|
||||
└───────────────────────┴──────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────┐
|
||||
│ Deleted │
|
||||
└──────────┘
|
||||
```
|
||||
图 2-1 容器生命周期状态流转图
|
||||
|
||||
#### 常用生命周期命令
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Docker Registry 是镜像分发和管理的核心组件。本节将介绍 Regist
|
||||
|
||||
#### Registry、仓库、标签的关系
|
||||
|
||||
Docker Registry 中可以包含多个 Repository,每个 Repository 可以包含多个 Tag。下图清晰地展示了它们之间的层级关系。
|
||||
Docker Registry 中可以包含多个 Repository,每个 Repository 可以包含多个 Tag。如图 2-2 所示,它们之间具有清晰的层级关系。
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
@@ -37,6 +37,8 @@ Docker Registry 中可以包含多个 Repository,每个 Repository 可以包
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
图 2-2 Registry、Repository 与 Tag 的层级关系
|
||||
|
||||
| 概念 | 说明 | 示例 |
|
||||
|------|------|------|
|
||||
| **Registry** | 存储镜像的服务 | Docker Hub、ghcr.io |
|
||||
@@ -176,7 +178,7 @@ $ docker pull localhost:5000/myapp:v1.0
|
||||
|
||||
#### 完整工作流程
|
||||
|
||||
下图展示了从开发环境构建镜像,推送到 Registry,再到生产环境拉取运行的完整流程。
|
||||
如图 2-3 所示,镜像从开发环境构建后推送到 Registry,再由生产环境拉取并运行。
|
||||
|
||||
```
|
||||
开发者机器 Registry 生产服务器
|
||||
@@ -194,6 +196,8 @@ $ docker pull localhost:5000/myapp:v1.0
|
||||
│ │ 运行容器 │
|
||||
```
|
||||
|
||||
图 2-3 镜像构建、推送与拉取流程
|
||||
|
||||
#### 常用命令
|
||||
|
||||
运行以下命令:
|
||||
@@ -244,16 +248,23 @@ someuser/myapp # ⚠️ 需要评估
|
||||
|
||||
#### 镜像签名
|
||||
|
||||
使用 Docker Content Trust (DCT) 验证镜像来源:
|
||||
当前更推荐使用 Sigstore / Notation 体系进行镜像签名与验证。`Docker Content Trust (DCT)` 已进入退场阶段,不建议作为新项目主方案。
|
||||
|
||||
> 注意:Cosign 默认会把签名写回镜像所在仓库,请使用你有推送权限的镜像地址。
|
||||
|
||||
```bash
|
||||
## 启用镜像签名验证
|
||||
## 准备一个你有写权限的镜像地址
|
||||
$ export IMAGE=<你的仓库名>/nginx:1.27
|
||||
$ docker pull nginx:1.27
|
||||
$ docker tag nginx:1.27 $IMAGE
|
||||
$ docker push $IMAGE
|
||||
|
||||
$ export DOCKER_CONTENT_TRUST=1
|
||||
## 生成签名密钥(会生成 cosign.key / cosign.pub)
|
||||
$ cosign generate-key-pair
|
||||
|
||||
## 此后的 pull/push 会验证签名
|
||||
|
||||
$ docker pull nginx:latest
|
||||
## 使用 Cosign 签名与验证
|
||||
$ cosign sign --key cosign.key $IMAGE
|
||||
$ cosign verify --key cosign.pub $IMAGE
|
||||
```
|
||||
|
||||
#### 漏洞扫描
|
||||
|
||||
Reference in New Issue
Block a user