Docker 仓库与镜像分发

Docker 仓库与镜像分发

深入理解Docker镜像仓库,掌握镜像分发、版本管理和安全最佳实践。

Docker Hub 私有仓库 镜像分发 版本管理

什么是 Docker 仓库?

Docker 仓库 是用于存储和分发Docker镜像的服务。仓库可以分为公共仓库和私有仓库。

Docker仓库的主要功能:

  • 存储Docker镜像
  • 管理镜像版本
  • 控制镜像访问权限
  • 提供镜像分发服务
  • 支持镜像扫描和安全检查

最著名的公共仓库是 Docker Hub,此外还有各种云服务商提供的仓库服务。

为什么需要镜像仓库?
  • 团队协作和镜像共享
  • 持续集成和持续部署
  • 版本控制和回滚
  • 安全扫描和漏洞管理
  • 镜像分发和缓存
仓库 vs 注册表

注册表 (Registry) 是存储仓库的服务,仓库 (Repository) 是存储特定镜像集合的地方。一个注册表可以包含多个仓库。

Docker 仓库类型

Docker Hub

Docker官方提供的公共仓库,包含大量官方和社区镜像。

公共 免费

云厂商仓库

AWS ECR、Google Container Registry、Azure Container Registry等。

私有 集成

自建私有仓库

使用Docker Registry或Harbor等工具搭建私有仓库。

私有 可控

Docker Hub 详解

私有仓库详解

私有仓库 - 企业级解决方案

私有仓库用于存储企业内部镜像,提供更好的安全性和控制能力。

搭建私有Docker Registry

# 使用Docker运行私有Registry
docker run -d \
  -p 5000:5000 \
  --name registry \
  -v /data/registry:/var/lib/registry \
  registry:2

# 使用TLS证书运行安全Registry
docker run -d \
  -p 5000:5000 \
  --name registry \
  -v /path/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  registry:2
                        
使用私有仓库

# 标记镜像指向私有仓库
docker tag my-app:latest localhost:5000/my-app:latest

# 推送镜像到私有仓库
docker push localhost:5000/my-app:latest

# 从私有仓库拉取镜像
docker pull localhost:5000/my-app:latest

# 使用域名访问私有仓库
docker tag my-app:latest registry.example.com:5000/my-app:latest
docker push registry.example.com:5000/my-app:latest
                        
Harbor - 企业级Registry

Harbor是VMware开源的企业级Registry,提供更多企业级功能:

  • 基于角色的访问控制
  • 镜像漏洞扫描
  • 镜像复制和同步
  • LDAP/AD集成
  • 图形化界面管理

# 使用Docker Compose安装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
cp harbor.yml.tmpl harbor.yml
# 编辑harbor.yml配置
./install.sh
                        

镜像分发工作流程

1
构建镜像

使用Dockerfile构建应用镜像

2
标记镜像

为镜像添加合适的标签,包含仓库地址和版本信息

3
推送镜像

将镜像推送到目标仓库

4
拉取部署

在目标环境拉取镜像并部署

镜像生命周期管理

镜像生命周期示意图

Dockerfile
构建
标记
推送
仓库
拉取
运行
更新

镜像标签策略

镜像标签最佳实践

语义化版本标签

# 语义化版本标签
my-app:1.0.0          # 主版本.次版本.修订版本
my-app:1.0            # 主要版本
my-app:1              # 主要版本系列

# 预发布版本
my-app:1.0.0-rc.1     # 发布候选版本
my-app:1.0.0-beta.1   # 测试版本
my-app:1.0.0-alpha.1  # 开发版本
                        
环境标签

# 环境特定标签
my-app:latest         # 最新稳定版本(生产慎用)
my-app:stable         # 稳定版本
my-app:dev            # 开发版本
my-app:test           # 测试版本
my-app:staging        # 预生产版本
                        
Git集成标签

# 基于Git提交的标签
my-app:git-${COMMIT_SHA:0:8}    # 提交哈希前8位
my-app:branch-${BRANCH_NAME}     # 分支名称
my-app:${BUILD_NUMBER}           # 构建编号

# 实际示例
my-app:git-a1b2c3d4
my-app:branch-feature-login
my-app:build-123
                        
多架构标签

# 多架构镜像标签
my-app:1.0.0-amd64    # AMD64架构
my-app:1.0.0-arm64    # ARM64架构
my-app:1.0.0-armv7    # ARMv7架构

# 使用manifest列表(推荐)
my-app:1.0.0          # 自动选择合适架构
                        

镜像操作命令

命令 描述 示例
docker pull 从仓库拉取镜像 docker pull nginx:latest
docker push 推送镜像到仓库 docker push myrepo/my-app:1.0
docker tag 为镜像创建标签 docker tag my-app:1.0 myrepo/my-app:1.0
docker search 搜索Docker Hub上的镜像 docker search nginx
docker images 列出本地镜像 docker images
docker rmi 删除本地镜像 docker rmi my-app:1.0
docker save 将镜像保存为tar文件 docker save -o my-app.tar my-app:1.0
docker load 从tar文件加载镜像 docker load -i my-app.tar
docker export 将容器导出为tar文件 docker export container > app.tar
docker import 从tar文件导入镜像 docker import app.tar my-app:1.0

镜像安全与签名

镜像安全最佳实践

内容信任 (Docker Content Trust)

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

# 推送签名镜像
docker push myrepo/my-app:1.0

# 拉取并验证签名镜像
docker pull myrepo/my-app:1.0

# 禁用内容信任
export DOCKER_CONTENT_TRUST=0
                        
镜像漏洞扫描

# 使用Docker Scout扫描镜像(Docker Desktop)
docker scout quickview my-app:latest

# 使用Trivy扫描镜像
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image my-app:latest

# 使用Grype扫描镜像
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock anchore/grype my-app:latest
                        
最小化基础镜像

# 使用Alpine Linux基础镜像
FROM alpine:3.18

# 使用Distroless基础镜像(Google)
FROM gcr.io/distroless/base-debian11

# 使用Scratch空镜像
FROM scratch
                        

镜像加速器配置

国内镜像加速器

在国内访问Docker Hub可能较慢,可以配置镜像加速器提高拉取速度。

Docker Desktop 配置

在Docker Desktop设置中配置镜像加速器:


{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://registry.docker-cn.com"
  ]
}
                        
Linux 系统配置

# 创建或编辑Docker配置文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ]
}
EOF

# 重启Docker服务
sudo systemctl daemon-reload
sudo systemctl restart docker
                        
常用镜像加速器
  • 中科大: https://docker.mirrors.ustc.edu.cn
  • 网易: https://hub-mirror.c.163.com
  • 阿里云: 需要登录控制台获取专属加速器地址
  • DaoCloud: https://f1361db2.m.daocloud.io

CI/CD 集成

GitHub Actions 集成

name: Build and Push Docker Image

on:
  push:
    branches: [ main ]
    tags: [ 'v*' ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Build Docker image
      run: docker build -t my-app:${{ github.sha }} .

    - name: Log in to Docker Hub
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}

    - name: Push Docker image
      run: |
        docker tag my-app:${{ github.sha }} ${{ secrets.DOCKER_USERNAME }}/my-app:${{ github.sha }}
        docker tag my-app:${{ github.sha }} ${{ secrets.DOCKER_USERNAME }}/my-app:latest
        docker push ${{ secrets.DOCKER_USERNAME }}/my-app:${{ github.sha }}
        docker push ${{ secrets.DOCKER_USERNAME }}/my-app:latest
        
GitLab CI 集成

image: docker:latest

services:
  - docker:dind

variables:
  DOCKER_HOST: tcp://docker:2375
  DOCKER_DRIVER: overlay2

stages:
  - build
  - push

build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

push:
  stage: push
  script:
    - docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:latest
  only:
    - main
                        

仓库服务对比

特性 Docker Hub AWS ECR Google GCR 自建Registry
成本 免费+付费 按使用量付费 按使用量付费 基础设施成本
私有仓库 有限免费 支持 支持 完全支持
安全性 基础 IAM集成 IAM集成 完全可控
漏洞扫描 付费功能 基础扫描 基础扫描 依赖工具
与云服务集成 有限 深度集成 深度集成 自定义
适用场景 个人/小团队 AWS用户 GCP用户 企业/合规需求

最佳实践

使用多阶段构建

使用多阶段构建减小镜像大小,只包含运行应用所需的文件。


FROM golang:1.19 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/myapp .
CMD ["./myapp"]
                        
使用.dockerignore文件

创建.dockerignore文件排除不必要的文件,减小构建上下文和镜像大小。


# .dockerignore 文件示例
.git
node_modules
npm-debug.log
Dockerfile
.dockerignore
README.md
                        
避免使用latest标签

在生产环境中避免使用latest标签,使用明确的版本标签确保部署一致性。


# 不推荐
docker run my-app:latest

# 推荐
docker run my-app:1.2.3
docker run my-app:1.2.3-git-a1b2c3d4
                        
定期更新基础镜像

定期更新基础镜像以获取安全补丁和性能改进。


# 使用特定版本的基础镜像
FROM node:18.16.0-alpine

# 定期检查并更新到新版本
FROM node:18.17.0-alpine
                        
实施镜像扫描

在CI/CD流水线中集成镜像漏洞扫描,确保部署的镜像没有已知安全漏洞。


# GitHub Actions 扫描步骤
- name: Scan image
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: 'my-app:${{ github.sha }}'
    format: 'sarif'
    output: 'trivy-results.sarif'
                        

常见问题与解决方案

问题描述: 推送镜像到仓库时出现认证错误。

解决方案:

  • 检查Docker登录状态:docker login
  • 验证用户名和密码/访问令牌
  • 检查仓库地址和权限
  • 对于私有仓库,检查网络连接和证书

# 重新登录Docker Hub
docker logout
docker login

# 检查当前登录信息
cat ~/.docker/config.json

# 使用访问令牌而不是密码(GitHub Packages等)
echo $TOKEN | docker login docker.pkg.github.com -u USERNAME --password-stdin
                                    

问题描述: 从Docker Hub拉取镜像速度很慢。

解决方案:

  • 配置国内镜像加速器
  • 使用代理服务器
  • 考虑搭建本地镜像缓存
  • 使用云服务商的镜像服务

# 配置镜像加速器(Linux)
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

# 使用代理
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
                                    

问题描述: 镜像标签过多,难以管理和追踪。

解决方案:

  • 建立统一的标签命名规范
  • 使用语义化版本控制
  • 定期清理不需要的旧镜像
  • 使用自动化工具管理镜像生命周期

# 清理旧的镜像标签
docker images --filter "dangling=true" -q | xargs docker rmi

# 按时间过滤并删除旧镜像
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.CreatedSince}}" | grep "months ago"

# 使用第三方工具清理
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock spotify/docker-gc
                                    
仓库与镜像分发掌握!

恭喜!您已经掌握了Docker仓库与镜像分发的核心知识。现在可以高效管理镜像生命周期,确保应用的安全分发和部署。