定义:
Docker Registry = Docker镜像仓库
就像: 存放集装箱的专用仓库
核心功能:
├─ 存储Docker镜像
├─ 分发镜像到客户端
├─ 版本管理
├─ 访问控制
└─ 镜像同步
Registry类型:
├─ Docker Hub: 公共仓库
├─ Docker Registry: 私有仓库
├─ Harbor: 企业级仓库
└─ 其他: Quay, Nexus等
东巴文理解:
镜像仓库对比:
┌──────────────────┬──────────────┬──────────────┐
│ 特性 │ 公共仓库 │ 私有仓库 │
├──────────────────┼──────────────┼──────────────┤
│ 访问权限 │ 公开 │ 私有 │
│ 网络速度 │ 较慢 │ 快速 │
│ 安全性 │ 一般 │ 高 │
│ 成本 │ 免费 │ 自建成本 │
│ 适用场景 │ 开源项目 │ 企业内部 │
└──────────────────┴──────────────┴──────────────┘
为什么需要私有仓库:
├─ 网络速度: 内网访问更快
├─ 安全性: 镜像不外泄
├─ 成本: 节省带宽成本
├─ 合规: 满足合规要求
└─ 自定义: 灵活配置
架构图:
┌─────────────────────────────────────────┐
│ Docker Registry架构 │
├─────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ │
│ │ Docker Client │ │
│ │ (docker push/pull) │ │
│ └──────────────┬──────────────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────────────────────┐ │
│ │ Registry API │ │
│ │ (HTTP/HTTPS) │ │
│ └──────────────┬──────────────────┘ │
│ │ │
│ ↓ │
│ ┌─────────────────────────────────┐ │
│ │ Storage Backend │ │
│ │ ├─ Filesystem (本地) │ │
│ │ ├─ S3 (AWS) │ │
│ │ ├─ Azure Blob │ │
│ │ └─ GCS (Google) │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
版本说明:
Registry V1:
├─ 已废弃
├─ 性能较差
└─ 不推荐使用
Registry V2:
├─ 当前版本
├─ 性能优秀
├─ 安全性高
├─ 支持多种存储后端
└─ 推荐使用
特性对比:
┌──────────────────┬──────────────┬──────────────┐
│ 特性 │ V1 │ V2 │
├──────────────────┼──────────────┼──────────────┤
│ 性能 │ 一般 │ 优秀 │
│ 安全性 │ 低 │ 高 │
│ 存储后端 │ 单一 │ 多种 │
│ 并发性能 │ 差 │ 好 │
│ 镜像格式 │ 图层 │ 清单 │
└──────────────────┴──────────────┴──────────────┘
启动Registry容器:
# 启动Registry容器
docker run -d \
--name registry \
-p 5000:5000 \
-v /data/registry:/var/lib/registry \
--restart=always \
registry:2
# 查看容器状态
docker ps | grep registry
# 输出
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1b2c3d4e5f6 registry:2 "/entrypoint.sh /etc…" 5 seconds ago Up 4 seconds 0.0.0.0:5000->5000/tcp registry
验证Registry:
# 查看Registry状态
curl http://localhost:5000/v2/
# 输出
{}
# 查看仓库列表
curl http://localhost:5000/v2/_catalog
# 输出
{"repositories":[]}
推送镜像:
# 拉取测试镜像
docker pull nginx:latest
# 标记镜像
docker tag nginx:latest localhost:5000/mynginx:latest
# 推送镜像
docker push localhost:5000/mynginx:latest
# 输出
The push refers to repository [localhost:5000/mynginx]
a1b2c3d4e5f6: Pushed
latest: digest: sha256:123456... size: 1362
拉取镜像:
# 删除本地镜像
docker rmi nginx:latest
docker rmi localhost:5000/mynginx:latest
# 从私有仓库拉取
docker pull localhost:5000/mynginx:latest
# 查看镜像
docker images | grep mynginx
# 输出
localhost:5000/mynginx latest a1b2c3d4e5f6 2 weeks ago 142MB
docker-compose.yml:
version: '3.8'
services:
registry:
image: registry:2
container_name: registry
restart: always
ports:
- "5000:5000"
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry
REGISTRY_STORAGE_DELETE_ENABLED: "true"
volumes:
- registry_data:/var/lib/registry
- ./config:/etc/docker/registry
- ./auth:/auth
networks:
- registry-net
volumes:
registry_data:
networks:
registry-net:
启动服务:
# 启动Registry
docker compose up -d
# 查看日志
docker compose logs -f registry
# 查看服务状态
docker compose ps
config.yml:
version: 0.1
log:
level: info
formatter: text
fields:
service: registry
environment: production
storage:
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
cache:
blobdescriptor: inmemory
maintenance:
uploadpurging:
enabled: true
age: 168h
interval: 24h
dryrun: false
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
tls:
certificate: /etc/docker/registry/ssl/registry.crt
key: /etc/docker/registry/ssl/registry.key
auth:
htpasswd:
realm: Registry Realm
path: /auth/htpasswd
notifications:
endpoints:
- name: listener
url: http://localhost:5003/callback
headers:
Authorization: [Bearer <token>]
timeout: 500ms
threshold: 5
backoff: 1s
配置说明:
配置项说明:
├─ log: 日志配置
│ ├─ level: 日志级别
│ ├─ formatter: 日志格式
│ └─ fields: 日志字段
│
├─ storage: 存储配置
│ ├─ filesystem: 本地文件系统
│ ├─ delete: 删除功能
│ ├─ cache: 缓存配置
│ └─ maintenance: 维护配置
│
├─ http: HTTP配置
│ ├─ addr: 监听地址
│ ├─ headers: HTTP头
│ └─ tls: TLS配置
│
├─ auth: 认证配置
│ └─ htpasswd: 密码文件认证
│
└─ notifications: 通知配置
└─ endpoints: 通知端点
生成自签名证书:
# 创建证书目录
mkdir -p /data/registry/ssl
# 生成私钥
openssl genrsa -out /data/registry/ssl/registry.key 2048
# 生成证书
openssl req -new -x509 \
-key /data/registry/ssl/registry.key \
-out /data/registry/ssl/registry.crt \
-days 365 \
-subj /CN=registry.example.com
# 查看证书
openssl x509 -in /data/registry/ssl/registry.crt -text -noout
使用CA证书:
# 创建CA私钥
openssl genrsa -out ca.key 2048
# 创建CA证书
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
# 创建服务器私钥
openssl genrsa -out registry.key 2048
# 创建证书签名请求
openssl req -new -key registry.key -out registry.csr
# 使用CA签名证书
openssl x509 -req -days 365 \
-in registry.csr \
-CA ca.crt -CAkey ca.key \
-CAcreateserial \
-out registry.crt
Registry配置:
# config.yml
http:
addr: :5000
tls:
certificate: /etc/docker/registry/ssl/registry.crt
key: /etc/docker/registry/ssl/registry.key
Docker Compose配置:
version: '3.8'
services:
registry:
image: registry:2
ports:
- "5000:5000"
volumes:
- registry_data:/var/lib/registry
- ./ssl:/etc/docker/registry/ssl
- ./config:/etc/docker/registry
environment:
REGISTRY_HTTP_TLS_CERTIFICATE: /etc/docker/registry/ssl/registry.crt
REGISTRY_HTTP_TLS_KEY: /etc/docker/registry/ssl/registry.key
volumes:
registry_data:
客户端配置:
# 信任自签名证书
# 方法1: 复制证书到Docker目录
mkdir -p /etc/docker/certs.d/registry.example.com:5000
cp registry.crt /etc/docker/certs.d/registry.example.com:5000/ca.crt
# 方法2: 添加到系统信任列表
cp registry.crt /usr/local/share/ca-certificates/registry.crt
update-ca-certificates
# 重启Docker
systemctl restart docker
# 测试HTTPS
curl -k https://registry.example.com:5000/v2/
创建密码文件:
# 安装htpasswd工具
apt-get install apache2-utils # Ubuntu/Debian
yum install httpd-tools # CentOS/RHEL
# 创建密码文件
htpasswd -c /data/registry/auth/htpasswd admin
# 输入密码
New password:
Re-type new password:
Adding password for user admin
# 添加更多用户
htpasswd /data/registry/auth/htpasswd user1
Registry配置:
# config.yml
auth:
htpasswd:
realm: Registry Realm
path: /auth/htpasswd
Docker Compose配置:
version: '3.8'
services:
registry:
image: registry:2
ports:
- "5000:5000"
volumes:
- registry_data:/var/lib/registry
- ./auth:/auth
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
volumes:
registry_data:
使用认证:
# 登录Registry
docker login registry.example.com:5000
# 输入用户名和密码
Username: admin
Password:
Login Succeeded
# 推送镜像
docker push registry.example.com:5000/mynginx:latest
# 拉取镜像
docker pull registry.example.com:5000/mynginx:latest
# 登出
docker logout registry.example.com:5000
Token认证配置:
# config.yml
auth:
token:
realm: https://auth.example.com/auth
service: registry.example.com
issuer: Auth Service
rootcertbundle: /etc/docker/registry/ssl/auth.crt
说明:
Token认证流程:
├─ 客户端请求Registry
├─ Registry返回401,要求认证
├─ 客户端向认证服务请求Token
├─ 认证服务验证身份,返回Token
├─ 客户端携带Token访问Registry
└─ Registry验证Token,允许访问
优势:
✅ 集中认证管理
✅ 支持多种认证方式
✅ 细粒度权限控制
✅ 支持单点登录
查看仓库列表:
# 查看所有仓库
curl -u admin:password http://localhost:5000/v2/_catalog
# 输出
{"repositories":["mynginx","myapp","mysql"]}
# 查看镜像标签
curl -u admin:password http://localhost:5000/v2/mynginx/tags/list
# 输出
{"name":"mynginx","tags":["latest","v1.0","v1.1"]}
查看镜像详情:
# 查看镜像manifest
curl -u admin:password \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
http://localhost:5000/v2/mynginx/manifests/latest
# 输出
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 7023,
"digest": "sha256:b5b2b2b..."
},
"layers": [...]
}
启用删除功能:
# config.yml
storage:
delete:
enabled: true
删除镜像:
# 1. 获取镜像digest
DIGEST=$(curl -u admin:password \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
-I http://localhost:5000/v2/mynginx/manifests/latest \
2>&1 | grep Docker-Content-Digest | awk '{print $2}')
# 2. 删除镜像
curl -u admin:password -X DELETE \
http://localhost:5000/v2/mynginx/manifests/$DIGEST
# 3. 运行垃圾回收
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
# 输出
mynginx
mynginx: marking manifest sha256:123456...
mynginx: marking blob sha256:abcdef...
...
从Docker Hub迁移:
# 拉取镜像
docker pull nginx:latest
# 标记镜像
docker tag nginx:latest registry.example.com:5000/nginx:latest
# 推送到私有仓库
docker push registry.example.com:5000/nginx:latest
批量迁移脚本:
#!/bin/bash
# migrate-images.sh
# 镜像列表
images=(
"nginx:latest"
"mysql:5.7"
"redis:alpine"
"python:3.9"
)
# 私有仓库地址
REGISTRY="registry.example.com:5000"
# 迁移镜像
for image in "${images[@]}"; do
echo "Migrating $image..."
# 拉取镜像
docker pull $image
# 标记镜像
docker tag $image $REGISTRY/$image
# 推送镜像
docker push $REGISTRY/$image
echo "Migrated $image successfully"
done
echo "Migration completed!"
使用docker-retag:
# 安装docker-retag
go get github.com/jessfraz/docker-retag
# 同步镜像
docker-retag \
-s source-registry.com:5000 \
-d dest-registry.com:5000 \
-i "nginx,mysql,redis"
使用skopeo:
# 安装skopeo
apt-get install skopeo # Ubuntu/Debian
yum install skopeo # CentOS/RHEL
# 同步镜像
skopeo copy \
docker://source-registry.com:5000/nginx:latest \
docker://dest-registry.com:5000/nginx:latest
# 批量同步
skopeo sync \
--src docker \
--dest docker \
source-registry.com:5000 \
dest-registry.com:5000
配置示例:
# config.yml
storage:
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
cache:
blobdescriptor: inmemory
S3配置:
# config.yml
storage:
s3:
accesskey: AWS_ACCESS_KEY
secretkey: AWS_SECRET_KEY
region: us-west-1
bucket: my-registry-bucket
encrypt: true
secure: true
v4auth: true
chunksize: 5242880
rootdirectory: /registry
环境变量配置:
version: '3.8'
services:
registry:
image: registry:2
environment:
REGISTRY_STORAGE: s3
REGISTRY_STORAGE_S3_ACCESSKEY: AWS_ACCESS_KEY
REGISTRY_STORAGE_S3_SECRETKEY: AWS_SECRET_KEY
REGISTRY_STORAGE_S3_REGION: us-west-1
REGISTRY_STORAGE_S3_BUCKET: my-registry-bucket
Azure配置:
# config.yml
storage:
azure:
accountname: myaccount
accountkey: mykey
container: mycontainer
realm: core.windows.net
配置示例:
# config.yml
notifications:
endpoints:
- name: webhook-listener
disabled: false
url: https://webhook.example.com/callback
headers:
Authorization: [Bearer mytoken]
timeout: 500ms
threshold: 5
backoff: 1s
ignoredmediatypes:
- application/octet-stream
Webhook事件:
事件类型:
├─ push: 镜像推送
├─ pull: 镜像拉取
├─ mount: 镜像挂载
├─ delete: 镜像删除
└─ tag: 标签操作
事件数据:
{
"id": "asdflkj...",
"timestamp": "2024-01-01T00:00:00Z",
"action": "push",
"target": {
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 7023,
"digest": "sha256:b5b2b2b...",
"length": 7023,
"repository": "mynginx",
"tag": "latest"
},
"request": {
"id": "asdfasdf...",
"addr": "192.168.1.100:12345",
"host": "registry.example.com:5000",
"method": "PUT",
"useragent": "docker/20.10.0"
},
"actor": {
"name": "admin"
}
}
Harbor优势:
Harbor = 企业级Docker Registry
就像: 功能齐全的专业仓储中心
核心特性:
├─ 基于角色的访问控制(RBAC)
├─ 镜像漏洞扫描
├─ 镜像签名验证
├─ 镜像复制
├─ 图形化管理界面
├─ 审计日志
├─ 垃圾回收
└─ Helm Chart支持
与Registry对比:
┌──────────────────┬──────────────┬──────────────┐
│ 特性 │ Registry │ Harbor │
├──────────────────┼──────────────┼──────────────┤
│ Web界面 │ 无 │ 有 │
│ 认证方式 │ 简单 │ 多种 │
│ 权限管理 │ 基础 │ RBAC │
│ 镜像扫描 │ 无 │ 有 │
│ 镜像复制 │ 无 │ 有 │
│ 审计日志 │ 无 │ 有 │
└──────────────────┴──────────────┴──────────────┘
下载Harbor:
# 下载Harbor离线安装包
wget https://github.com/goharbor/harbor/releases/download/v2.5.0/harbor-offline-installer-v2.5.0.tgz
# 解压
tar xzf harbor-offline-installer-v2.5.0.tgz
# 进入目录
cd harbor
配置Harbor:
# 复制配置文件
cp harbor.yml.tmpl harbor.yml
# 编辑配置文件
vim harbor.yml
# 主要配置
hostname: harbor.example.com
http:
port: 80
https:
port: 443
certificate: /data/ssl/harbor.crt
private_key: /data/ssl/harbor.key
harbor_admin_password: Harbor12345
database:
password: root123
data_volume: /data/harbor
安装Harbor:
# 安装
./install.sh
# 输出
[Step 0]: checking if docker is installed ...
[Step 1]: checking docker-compose is installed ...
[Step 2]: loading Harbor images ...
[Step 3]: preparing environment ...
[Step 4]: preparing harbor configs ...
[Step 5]: starting Harbor ...
✔ ----Harbor has been installed and started successfully.----
访问Web界面:
URL: https://harbor.example.com
用户名: admin
密码: Harbor12345
功能:
├─ 项目管理
├─ 镜像管理
├─ 用户管理
├─ 日志审计
├─ 系统设置
└─ 垃圾回收
Docker客户端配置:
# 添加Harbor到Docker信任列表
mkdir -p /etc/docker/certs.d/harbor.example.com
cp harbor.crt /etc/docker/certs.d/harbor.example.com/ca.crt
# 重启Docker
systemctl restart docker
# 登录Harbor
docker login harbor.example.com
# 推送镜像
docker tag nginx:latest harbor.example.com/library/nginx:latest
docker push harbor.example.com/library/nginx:latest
# 拉取镜像
docker pull harbor.example.com/library/nginx:latest
Registry类型:
├─ Docker Hub: 公共仓库
├─ Docker Registry: 私有仓库
├─ Harbor: 企业级仓库
└─ 其他: Quay, Nexus
Registry配置:
├─ 存储配置: filesystem, s3, azure
├─ 安全配置: TLS, 认证
├─ 通知配置: webhook
└─ 维护配置: 垃圾回收
镜像操作:
├─ 推送: docker push
├─ 拉取: docker pull
├─ 查看: curl API
└─ 删除: DELETE + GC
TLS/SSL配置:
├─ 生成证书: openssl
├─ 配置HTTPS: config.yml
└─ 客户端信任: ca.crt
认证配置:
├─ 基本认证: htpasswd
├─ Token认证: auth server
└─ Harbor: RBAC
访问控制:
├─ 用户管理
├─ 权限控制
├─ 项目隔离
└─ 审计日志
安全配置:
✅ 启用HTTPS
✅ 配置认证
✅ 定期更新证书
✅ 启用审计日志
性能优化:
✅ 使用高性能存储
✅ 配置缓存
✅ 定期垃圾回收
✅ 监控资源使用
运维管理:
✅ 定期备份
✅ 监控告警
✅ 文档化流程
✅ 灾难恢复方案
项目管理:
✅ 按团队创建项目
✅ 设置访问权限
✅ 配置镜像扫描
✅ 启用镜像签名
镜像管理:
✅ 规范镜像命名
✅ 定期清理无用镜像
✅ 配置镜像复制
✅ 启用漏洞扫描
用户管理:
✅ 使用RBAC
✅ 定期审计用户
✅ 配置LDAP/AD
✅ 启用双因素认证
下一章: Docker安全
将学习:
搭建Registry: 使用Docker命令快速搭建一个Registry,推送和拉取一个nginx镜像。
基本认证: 为Registry配置基本认证,创建用户并测试登录。
HTTPS配置: 为Registry配置HTTPS,生成自签名证书并配置客户端信任。
Docker Compose部署: 使用Docker Compose部署一个完整的Registry,包含认证、HTTPS和持久化存储。
镜像管理: 编写脚本批量迁移Docker Hub的镜像到私有仓库。
Harbor安装: 安装Harbor企业级仓库,配置项目、用户和权限。
完整Registry方案: 设计一个生产环境的Registry方案,要求:
多仓库同步: 设计一个多仓库镜像同步方案,实现: