Docker 镜像仓库
本章将详细介绍 Docker 镜像仓库的使用和管理,包括公共仓库、私有仓库的搭建、镜像分发策略以及仓库安全配置。
镜像仓库概述
什么是 Docker 镜像仓库?
Docker 镜像仓库是存储和分发 Docker 镜像的服务。它类似于代码仓库,但专门用于管理容器镜像的版本和分发。
仓库架构层次
Registry (仓库服务)
├── Repository (镜像仓库)
│ ├── Tag 1 (标签/版本)
│ ├── Tag 2
│ └── Tag 3
└── Repository
├── Tag 1
└── Tag 2仓库类型
| 类型 | 描述 | 使用场景 | 示例 |
|---|---|---|---|
| 公共仓库 | 开放访问的镜像仓库 | 开源项目、基础镜像 | Docker Hub |
| 私有仓库 | 受限访问的镜像仓库 | 企业内部应用 | Harbor、Nexus |
| 云仓库 | 云服务商提供的仓库 | 云原生应用 | ECR、ACR、GCR |
| 本地仓库 | 本地部署的仓库服务 | 开发测试环境 | Registry |
Docker Hub
Docker Hub 基础使用
bash
# 注册和登录
docker login
# 搜索镜像
docker search nginx
docker search --limit 10 --filter stars=100 nginx
# 拉取镜像
docker pull nginx:latest
docker pull nginx:1.21.6-alpine
# 推送镜像
docker tag myapp:latest username/myapp:latest
docker push username/myapp:latest
# 登出
docker logout镜像命名规范
bash
# Docker Hub 镜像命名格式
[registry_host[:port]/]username/repository[:tag]
# 官方镜像(省略用户名)
nginx:latest
ubuntu:20.04
postgres:13
# 用户镜像
myuser/myapp:v1.0
company/backend:latest
# 私有仓库镜像
registry.company.com:5000/team/app:v1.0自动构建
yaml
# .github/workflows/docker-hub.yml
name: Build and Push to Docker Hub
on:
push:
branches: [ main ]
tags: [ 'v*' ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v3
with:
images: username/myapp
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}私有仓库搭建
使用官方 Registry
bash
# 运行简单的私有仓库
docker run -d \
-p 5000:5000 \
--name registry \
registry:2
# 推送镜像到私有仓库
docker tag myapp:latest localhost:5000/myapp:latest
docker push localhost:5000/myapp:latest
# 从私有仓库拉取
docker pull localhost:5000/myapp:latest持久化存储配置
bash
# 使用数据卷持久化
docker run -d \
-p 5000:5000 \
--name registry \
-v registry-data:/var/lib/registry \
registry:2
# 使用主机目录
docker run -d \
-p 5000:5000 \
--name registry \
-v /opt/registry:/var/lib/registry \
registry:2Registry 配置文件
yaml
# config.yml
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true
http:
addr: :5000
headers:
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3bash
# 使用自定义配置
docker run -d \
-p 5000:5000 \
--name registry \
-v $(pwd)/config.yml:/etc/docker/registry/config.yml \
-v registry-data:/var/lib/registry \
registry:2Harbor 企业级仓库
Harbor 部署
yaml
# docker-compose.yml
version: '3.8'
services:
registry:
image: goharbor/registry-photon:v2.5.0
container_name: registry
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- /data/registry:/storage:z
- ./common/config/registry/:/etc/registry/:z
networks:
- harbor
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "registry"
registryctl:
image: goharbor/harbor-registryctl:v2.5.0
container_name: registryctl
env_file:
- ./common/config/registryctl/env
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- /data/registry:/storage:z
- ./common/config/registry/:/etc/registry/:z
- ./common/config/registryctl/config.yml:/etc/registryctl/config.yml:z
networks:
- harbor
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "registryctl"
postgresql:
image: goharbor/harbor-db:v2.5.0
container_name: harbor-db
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- SETGID
- SETUID
volumes:
- /data/database:/var/lib/postgresql/data:z
networks:
- harbor
env_file:
- ./common/config/db/env
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "postgresql"
core:
image: goharbor/harbor-core:v2.5.0
container_name: harbor-core
env_file:
- ./common/config/core/env
restart: always
cap_drop:
- ALL
cap_add:
- SETGID
- SETUID
volumes:
- /data/ca_download/:/etc/core/ca/:z
- /data/:/data/:z
- ./common/config/core/certificates/:/etc/core/certificates/:z
- ./common/config/core/app.conf:/etc/core/app.conf:z
- ./common/config/core/private_key.pem:/etc/core/private_key.pem:z
- ./common/config/core/key:/etc/core/key:z
networks:
- harbor
depends_on:
- log
- registry
- redis
- postgresql
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "core"
networks:
harbor:
external: falseHarbor 配置
yaml
# harbor.yml
hostname: harbor.company.com
http:
port: 80
https:
port: 443
certificate: /your/certificate/path
private_key: /your/private/key/path
harbor_admin_password: Harbor12345
database:
password: root123
max_idle_conns: 100
max_open_conns: 900
data_volume: /data
trivy:
ignore_unfixed: false
skip_update: false
offline_scan: false
security_check: vuln
insecure: false
jobservice:
max_job_workers: 10
notification:
webhook_job_max_retry: 10
chart:
absolute_url: disabled
log:
level: info
local:
rotate_count: 50
rotate_size: 200M
location: /var/log/harbor
_version: 2.5.0
proxy:
http_proxy:
https_proxy:
no_proxy:
components:
- core
- jobservice
- trivy云仓库服务
Amazon ECR
bash
# 安装 AWS CLI
pip install awscli
# 配置 AWS 凭证
aws configure
# 获取登录令牌
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-west-2.amazonaws.com
# 创建仓库
aws ecr create-repository --repository-name myapp
# 推送镜像
docker tag myapp:latest 123456789012.dkr.ecr.us-west-2.amazonaws.com/myapp:latest
docker push 123456789012.dkr.ecr.us-west-2.amazonaws.com/myapp:latestAzure Container Registry
bash
# 安装 Azure CLI
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# 登录 Azure
az login
# 创建资源组
az group create --name myResourceGroup --location eastus
# 创建 ACR
az acr create --resource-group myResourceGroup --name myregistry --sku Basic
# 登录 ACR
az acr login --name myregistry
# 推送镜像
docker tag myapp:latest myregistry.azurecr.io/myapp:latest
docker push myregistry.azurecr.io/myapp:latestGoogle Container Registry
bash
# 安装 Google Cloud SDK
curl https://sdk.cloud.google.com | bash
# 初始化 gcloud
gcloud init
# 配置 Docker 认证
gcloud auth configure-docker
# 推送镜像
docker tag myapp:latest gcr.io/project-id/myapp:latest
docker push gcr.io/project-id/myapp:latest仓库安全配置
HTTPS 配置
bash
# 生成自签名证书
mkdir -p certs
openssl req \
-newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key \
-x509 -days 365 -out certs/domain.crt \
-subj "/C=US/ST=CA/L=San Francisco/O=Docker/CN=localhost"
# 运行带 HTTPS 的仓库
docker run -d \
--name registry \
-p 5000:5000 \
-v $(pwd)/certs:/certs \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry:2基础认证
bash
# 创建密码文件
mkdir auth
docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > auth/htpasswd
# 运行带认证的仓库
docker run -d \
--name registry \
-p 5000:5000 \
-v $(pwd)/auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
registry:2
# 登录私有仓库
docker login localhost:5000Token 认证
yaml
# config.yml
version: 0.1
log:
level: debug
storage:
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
auth:
token:
realm: https://auth.company.com/token
service: registry.company.com
issuer: auth.company.com
rootcertbundle: /etc/docker/registry/auth.crt镜像分发策略
镜像标签策略
bash
# 语义化版本标签
docker tag myapp:latest myapp:1.0.0
docker tag myapp:latest myapp:1.0
docker tag myapp:latest myapp:1
# 环境标签
docker tag myapp:latest myapp:dev
docker tag myapp:latest myapp:staging
docker tag myapp:latest myapp:prod
# Git 提交标签
docker tag myapp:latest myapp:$(git rev-parse --short HEAD)
docker tag myapp:latest myapp:$(git describe --tags)
# 时间戳标签
docker tag myapp:latest myapp:$(date +%Y%m%d-%H%M%S)多架构镜像
bash
# 创建多架构构建器
docker buildx create --name multiarch --use
# 构建多架构镜像
docker buildx build \
--platform linux/amd64,linux/arm64,linux/arm/v7 \
--tag myregistry/myapp:latest \
--push .
# 查看镜像清单
docker buildx imagetools inspect myregistry/myapp:latest镜像同步
bash
#!/bin/bash
# sync-images.sh
SOURCE_REGISTRY="source.registry.com"
TARGET_REGISTRY="target.registry.com"
IMAGES=(
"myapp:latest"
"myapp:v1.0.0"
"database:latest"
)
for image in "${IMAGES[@]}"; do
echo "同步镜像: $image"
# 拉取源镜像
docker pull $SOURCE_REGISTRY/$image
# 重新标记
docker tag $SOURCE_REGISTRY/$image $TARGET_REGISTRY/$image
# 推送到目标仓库
docker push $TARGET_REGISTRY/$image
# 清理本地镜像
docker rmi $SOURCE_REGISTRY/$image $TARGET_REGISTRY/$image
done仓库管理
镜像清理
bash
# Registry 垃圾回收
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
# 删除未标记的镜像
docker exec registry bin/registry garbage-collect --delete-untagged /etc/docker/registry/config.yml
# 自动清理脚本
#!/bin/bash
# cleanup-registry.sh
REGISTRY_CONTAINER="registry"
DAYS_TO_KEEP=30
# 停止仓库服务
docker stop $REGISTRY_CONTAINER
# 执行垃圾回收
docker run --rm \
-v registry-data:/var/lib/registry \
registry:2 \
bin/registry garbage-collect --delete-untagged /etc/docker/registry/config.yml
# 重启仓库服务
docker start $REGISTRY_CONTAINER
echo "清理完成"仓库备份
bash
#!/bin/bash
# backup-registry.sh
BACKUP_DIR="/backup/registry"
DATE=$(date +%Y%m%d-%H%M%S)
REGISTRY_DATA="/var/lib/docker/volumes/registry-data/_data"
# 创建备份目录
mkdir -p $BACKUP_DIR
# 停止仓库服务
docker stop registry
# 备份数据
tar czf $BACKUP_DIR/registry-backup-$DATE.tar.gz -C $REGISTRY_DATA .
# 重启仓库服务
docker start registry
# 保留最近 7 天的备份
find $BACKUP_DIR -name "registry-backup-*.tar.gz" -mtime +7 -delete
echo "备份完成: registry-backup-$DATE.tar.gz"仓库监控
yaml
# docker-compose.monitoring.yml
version: '3.8'
services:
registry:
image: registry:2
ports:
- "5000:5000"
volumes:
- registry-data:/var/lib/registry
environment:
- REGISTRY_HTTP_DEBUG_ADDR=0.0.0.0:5001
- REGISTRY_HTTP_DEBUG_PROMETHEUS_ENABLED=true
networks:
- registry-network
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- registry-network
grafana:
image: grafana/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana-data:/var/lib/grafana
networks:
- registry-network
volumes:
registry-data:
grafana-data:
networks:
registry-network:
driver: bridgeAPI 操作
Registry API v2
bash
# 列出仓库
curl -X GET http://localhost:5000/v2/_catalog
# 列出标签
curl -X GET http://localhost:5000/v2/myapp/tags/list
# 获取镜像清单
curl -X GET \
-H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
http://localhost:5000/v2/myapp/manifests/latest
# 删除镜像
curl -X DELETE http://localhost:5000/v2/myapp/manifests/sha256:digest自动化脚本
bash
#!/bin/bash
# registry-api.sh
REGISTRY_URL="http://localhost:5000"
list_repositories() {
curl -s "$REGISTRY_URL/v2/_catalog" | jq -r '.repositories[]'
}
list_tags() {
local repo=$1
curl -s "$REGISTRY_URL/v2/$repo/tags/list" | jq -r '.tags[]'
}
get_manifest() {
local repo=$1
local tag=$2
curl -s -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
"$REGISTRY_URL/v2/$repo/manifests/$tag"
}
delete_image() {
local repo=$1
local digest=$2
curl -X DELETE "$REGISTRY_URL/v2/$repo/manifests/$digest"
}
# 使用示例
case "$1" in
"list-repos")
list_repositories
;;
"list-tags")
list_tags "$2"
;;
"get-manifest")
get_manifest "$2" "$3"
;;
"delete")
delete_image "$2" "$3"
;;
*)
echo "Usage: $0 {list-repos|list-tags|get-manifest|delete} [args...]"
exit 1
;;
esac最佳实践
仓库设计原则
- 命名规范:使用一致的命名约定
- 版本管理:实施语义化版本控制
- 安全配置:启用 HTTPS 和认证
- 访问控制:实施细粒度权限管理
- 监控告警:监控仓库健康状态
镜像管理策略
bash
# 镜像生命周期管理
#!/bin/bash
# image-lifecycle.sh
# 开发阶段
docker build -t myapp:dev-$(git rev-parse --short HEAD) .
docker push myregistry/myapp:dev-$(git rev-parse --short HEAD)
# 测试阶段
docker tag myapp:dev-$(git rev-parse --short HEAD) myapp:test-$(date +%Y%m%d)
docker push myregistry/myapp:test-$(date +%Y%m%d)
# 生产发布
docker tag myapp:test-$(date +%Y%m%d) myapp:v1.0.0
docker tag myapp:v1.0.0 myapp:latest
docker push myregistry/myapp:v1.0.0
docker push myregistry/myapp:latest安全检查清单
- [ ] 启用 HTTPS 加密
- [ ] 配置用户认证
- [ ] 实施访问控制
- [ ] 定期扫描漏洞
- [ ] 监控访问日志
- [ ] 备份重要数据
- [ ] 更新仓库软件
本章小结
本章全面介绍了 Docker 镜像仓库的各个方面:
关键要点:
- 仓库类型:公共、私有、云仓库的特点和使用
- 私有仓库:Registry、Harbor 等解决方案
- 安全配置:HTTPS、认证、访问控制
- 镜像管理:标签策略、多架构、同步
- 运维管理:监控、备份、清理
最佳实践:
- 选择合适的仓库解决方案
- 实施安全配置和访问控制
- 建立镜像生命周期管理
- 监控仓库健康状态
- 定期备份和清理
应用场景:
- 企业内部镜像管理
- CI/CD 流水线集成
- 多环境镜像分发
- 大规模容器部署
掌握镜像仓库的管理技能对于容器化应用的开发和部署至关重要。