镜像分发与存储 #

镜像存储原理 #

分层存储架构 #

text
┌─────────────────────────────────────────────────────┐
│                   镜像分层存储                       │
├─────────────────────────────────────────────────────┤
│                                                     │
│  ┌─────────────────────────────────────────────┐   │
│  │              Container Layer                 │   │
│  │              (可读写层)                       │   │
│  ├─────────────────────────────────────────────┤   │
│  │              Image Layer N                   │   │
│  │              (只读层)                         │   │
│  ├─────────────────────────────────────────────┤   │
│  │              Image Layer N-1                 │   │
│  │              (只读层)                         │   │
│  ├─────────────────────────────────────────────┤   │
│  │              Image Layer 2                   │   │
│  │              (只读层)                         │   │
│  ├─────────────────────────────────────────────┤   │
│  │              Image Layer 1                   │   │
│  │              (只读层/基础层)                  │   │
│  └─────────────────────────────────────────────┘   │
│                                                     │
└─────────────────────────────────────────────────────┘

存储驱动 #

驱动 说明 适用场景
overlay2 默认推荐,性能最好 大多数Linux发行版
aufs 早期默认驱动 Ubuntu 14.04及以下
devicemapper 块设备存储 企业级存储
btrfs 文件系统级存储 需要快照功能
zfs 高级文件系统 需要高级存储功能

查看存储驱动 #

bash
# 查看当前存储驱动
docker info | grep "Storage Driver"

# 查看存储驱动详情
docker info -f '{{.Driver}}'

配置存储驱动 #

json
// /etc/docker/daemon.json
{
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}

镜像存储位置 #

默认存储路径 #

bash
# Linux默认路径
/var/lib/docker/

# macOS默认路径
~/Library/Containers/com.docker.docker/Data/

# Windows默认路径
C:\ProgramData\Docker\

目录结构 #

text
/var/lib/docker/
├── aufs/              # AUFS存储驱动数据
├── containers/        # 容器数据
├── image/             # 镜像元数据
│   └── overlay2/
│       ├── distribution/
│       ├── imagedb/
│       │   ├── content/
│       │   └── metadata/
│       ├── layerdb/
│       └── repositories.json
├── overlay2/          # Overlay2存储驱动数据
│   ├── <layer-id>/
│   │   ├── diff/      # 层数据
│   │   ├── link       # 层链接
│   │   ├── lower      # 下层引用
│   │   └── merged/    # 合并视图
├── volumes/           # 数据卷
└── network/           # 网络配置

更改存储路径 #

json
// /etc/docker/daemon.json
{
  "data-root": "/mnt/docker-data"
}
bash
# 重启Docker服务
sudo systemctl restart docker

镜像分发机制 #

Registry架构 #

text
┌─────────────────────────────────────────────────────┐
│                   Registry 架构                      │
├─────────────────────────────────────────────────────┤
│                                                     │
│  ┌─────────────┐    Push/Pull    ┌─────────────┐   │
│  │   Docker    │ ──────────────→ │  Registry   │   │
│  │   Client    │ ←────────────── │   Server    │   │
│  └─────────────┘                 └──────┬──────┘   │
│                                         │          │
│                                         ↓          │
│                                  ┌─────────────┐   │
│                                  │   Storage   │   │
│                                  │   Backend   │   │
│                                  └─────────────┘   │
│                                                     │
└─────────────────────────────────────────────────────┘

镜像推送流程 #

text
┌─────────────────────────────────────────────────────┐
│                   镜像推送流程                       │
├─────────────────────────────────────────────────────┤
│                                                     │
│  1. 检查本地镜像                                    │
│           │                                         │
│           ↓                                         │
│  2. 认证到Registry                                  │
│           │                                         │
│           ↓                                         │
│  3. 检查哪些层已存在                                │
│           │                                         │
│           ↓                                         │
│  4. 上传缺失的层                                    │
│           │                                         │
│           ↓                                         │
│  5. 上传manifest                                    │
│           │                                         │
│           ↓                                         │
│  6. 完成推送                                        │
│                                                     │
└─────────────────────────────────────────────────────┘

镜像拉取流程 #

text
┌─────────────────────────────────────────────────────┐
│                   镜像拉取流程                       │
├─────────────────────────────────────────────────────┤
│                                                     │
│  1. 认证到Registry                                  │
│           │                                         │
│           ↓                                         │
│  2. 获取manifest                                    │
│           │                                         │
│           ↓                                         │
│  3. 解析manifest获取层列表                          │
│           │                                         │
│           ↓                                         │
│  4. 检查本地已有哪些层                              │
│           │                                         │
│           ↓                                         │
│  5. 下载缺失的层                                    │
│           │                                         │
│           ↓                                         │
│  6. 组装镜像                                        │
│                                                     │
└─────────────────────────────────────────────────────┘

镜像仓库操作 #

Docker Hub #

bash
# 登录Docker Hub
docker login

# 登出Docker Hub
docker logout

# 推送镜像到Docker Hub
docker tag myapp:v1.0 username/myapp:v1.0
docker push username/myapp:v1.0

# 拉取私有镜像
docker pull username/myapp:v1.0

私有仓库 #

bash
# 启动私有仓库
docker run -d -p 5000:5000 --name registry \
  -v /data/registry:/var/lib/registry \
  registry:2

# 推送镜像到私有仓库
docker tag myapp:v1.0 localhost:5000/myapp:v1.0
docker push localhost:5000/myapp:v1.0

# 拉取镜像
docker pull localhost:5000/myapp:v1.0

配置非HTTPS仓库 #

json
// /etc/docker/daemon.json
{
  "insecure-registries": [
    "localhost:5000",
    "registry.example.com:5000"
  ]
}

镜像传输优化 #

镜像压缩 #

bash
# 导出压缩镜像
docker save myapp:v1.0 | gzip > myapp.tar.gz

# 导入压缩镜像
docker load < myapp.tar.gz

层共享 #

dockerfile
# 使用相同基础镜像实现层共享
FROM node:18-alpine

# 多个镜像共享相同的基础层

并行推送/拉取 #

bash
# 并行推送多个镜像
docker push myapp:v1.0 &
docker push myapp:v2.0 &
wait

# 使用skopeo并行操作
skopeo copy docker://myapp:v1.0 docker://registry.example.com/myapp:v1.0

镜像签名与验证 #

Docker Content Trust #

bash
# 启用内容信任
export DOCKER_CONTENT_TRUST=1

# 推送签名镜像
docker push myapp:v1.0

# 拉取签名镜像
docker pull myapp:v1.0

# 查看签名信息
docker trust inspect myapp:v1.0

# 禁用内容信任
export DOCKER_CONTENT_TRUST=0

签名密钥管理 #

bash
# 生成密钥
docker trust key generate mykey

# 添加签名者
docker trust signer add --key mykey.pub user myapp

# 移除签名者
docker trust signer remove user myapp

# 撤销签名
docker trust revoke myapp:v1.0

镜像安全扫描 #

docker scout #

bash
# 快速查看
docker scout quickview myapp:v1.0

# 查看CVE漏洞
docker scout cves myapp:v1.0

# 查看建议
docker scout recommendations myapp:v1.0

# 比较镜像
docker scout compare myapp:v1.0 myapp:v2.0

Trivy扫描 #

bash
# 安装trivy
brew install trivy

# 扫描镜像
trivy image myapp:v1.0

# 输出JSON格式
trivy image --format json --output results.json myapp:v1.0

# 只扫描高危漏洞
trivy image --severity HIGH,CRITICAL myapp:v1.0

镜像清理策略 #

自动清理 #

bash
# 清理悬空镜像
docker image prune -f

# 清理所有未使用镜像
docker image prune -a -f

# 设置过期时间
docker image prune -a --filter "until=168h"

# 完整清理
docker system prune -a --volumes

定时清理脚本 #

bash
#!/bin/bash
# clean-docker-images.sh

# 清理7天前的镜像
docker image prune -a --filter "until=168h" -f

# 清理停止的容器
docker container prune -f

# 清理未使用的网络
docker network prune -f

# 清理构建缓存
docker builder prune -f

echo "Cleanup completed at $(date)"

Cron定时任务 #

bash
# 编辑crontab
crontab -e

# 每天凌晨2点执行清理
0 2 * * * /path/to/clean-docker-images.sh >> /var/log/docker-cleanup.log 2>&1

镜像分发最佳实践 #

1. 使用语义化版本 #

bash
# 推荐的标签策略
myapp:1.0.0          # 具体版本
myapp:1.0            # 次版本
myapp:1              # 主版本
myapp:latest         # 最新版本
myapp:1.0.0-alpine   # 带变体标识

2. 多架构镜像 #

bash
# 创建多架构镜像
docker buildx build --platform linux/amd64,linux/arm64 \
  -t myapp:v1.0 --push .

3. 镜像瘦身 #

dockerfile
# 使用alpine基础镜像
FROM alpine:3.18

# 多阶段构建
FROM builder AS build
FROM alpine:3.18
COPY --from=build /app /app

4. 使用镜像缓存 #

bash
# 利用远程镜像作为缓存
docker build --cache-from myapp:latest -t myapp:v1.0 .

小结 #

本节学习了Docker镜像的存储和分发:

  • 镜像分层存储原理
  • 存储驱动和存储位置
  • 镜像分发机制
  • 镜像仓库操作
  • 镜像安全和清理

下一步 #

接下来,让我们学习 容器基础操作,了解Docker容器的基本管理方法。