3. 容器镜像基础:Docker镜像分层原理、镜像仓库与Tag/Digest
3.1 Docker镜像分层原理
Docker镜像并非一个单一的大文件,而是由一系列只读层(Layer)堆叠而成的联合文件系统。每一层代表Dockerfile中的一条指令,这种分层结构是镜像高效存储、传输和复用的核心基础。
核心概念: 镜像层是只读的,容器运行时在镜像层之上添加一个可写层(Container Layer)。所有对文件的修改、删除、新增都发生在这个可写层,遵循“写时复制”(Copy-on-Write, CoW)策略。
最佳实践: 将频繁变更的指令放在Dockerfile末尾,将稳定不变的基础环境放在开头,以最大化利用构建缓存。
3.2 镜像仓库:Harbor vs ECR
镜像仓库是存储、分发和管理容器镜像的核心基础设施。企业级场景中,Harbor(私有部署)和Amazon ECR(托管服务)是最主流的两个选择。
| 对比维度 | Harbor | Amazon ECR |
|---|---|---|
| 部署模式 | 自托管,部署在Kubernetes或VM上 | AWS托管服务,无需运维 |
| 认证方式 | LDAP/AD、OIDC、本地用户、机器人账户 | AWS IAM角色/用户、EC2实例角色 |
| 镜像扫描 | 内置Clair/Trivy,支持CVE漏洞扫描 | 集成Amazon Inspector,基础扫描免费 |
| 复制策略 | 支持P2P、Pull-based、Push-based跨地域复制 | 跨区域复制(Cross-Region Replication) |
| 不可变标签 | 支持,防止同名标签被覆盖 | 支持,通过IAM策略控制 |
| 清理策略 | 基于标签保留、最近使用、正则匹配 | 基于生命周期策略(过期天数/数量) |
| 审计日志 | 操作日志、项目日志、Syslog转发 | AWS CloudTrail + CloudWatch Logs |
注意: 在CSI门禁场景中,Harbor的“不可变标签”和“镜像签名(Cosign)”功能是阻止恶意镜像覆盖的关键能力。ECR则依赖IAM策略和Image Tag Mutability设置实现类似效果。
3.3 镜像Tag与Digest
Tag是镜像的易读标签,而Digest是镜像内容的唯一不可变标识符。理解两者的区别是构建可靠流水线的基础。
3.3.1 Tag的局限性与风险
- 可变性:
myapp:latest可以指向不同镜像,导致环境不一致。 - 覆盖风险: 同名Tag可能被恶意或意外覆盖。
- 语义模糊:
v1.0无法区分是构建号还是版本号。
3.3.2 Digest的不可变性
Digest是镜像内容的SHA256哈希值,格式为 sha256:abcdef123456...。只要镜像内容不变,Digest就唯一且不可变。
# 查看镜像Digest
docker images --digests myapp:latest
# 通过Digest拉取镜像(确保内容一致)
docker pull myregistry.com/myapp@sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890
# 在Kubernetes Deployment中使用Digest
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
template:
spec:
containers:
- name: myapp
image: myregistry.com/myapp@sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890
3.3.3 流水线中的Tag策略
推荐采用 语义化版本 + Git Commit SHA 的组合Tag策略,并在部署时使用Digest确保不可变性。
# 推荐的Tag格式
# 格式:<版本号>-<Git短SHA>
myapp:1.2.3-a1b2c3d
# 在CI流水线中获取Digest并记录
IMAGE_TAG="${VERSION}-${GIT_SHORT_SHA}"
docker build -t myapp:${IMAGE_TAG} .
docker push myapp:${IMAGE_TAG}
# 获取Digest
DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' myapp:${IMAGE_TAG} | cut -d'@' -f2)
echo "Image Digest: ${DIGEST}"
# 将Digest写入部署清单
sed -i "s|image: myapp:.*|image: myapp@${DIGEST}|g" deployment.yaml
门禁集成要点: CSI门禁应验证部署清单中使用的镜像Digest是否与Harbor/ECR中记录的Digest一致,防止中间人攻击或镜像篡改。同时,门禁策略应禁止使用
latest 标签进行生产部署。