26、集中式镜像仓库的增强配置指南

集中式镜像仓库的增强配置指南

1. 构建并测试基础反向代理

1.1 构建镜像

使用以下 docker build 命令构建镜像:

docker build -t dockerinaction/basic_proxy -f basic-proxy.df .

1.2 创建反向代理并测试连接

假设个人镜像仓库已在运行,使用以下命令创建新的反向代理并测试连接:

docker run -d --name basic_proxy -p 80:80 \
    --link personal_registry:registry \ 
    dockerinaction/basic_proxy
docker run --rm -u 1000:1000 --net host \
    dockerinaction/curl \
    -s http://localhost:80/v2/distribution/tags/list
步骤解析
  • 创建反向代理容器 docker run -d --name basic_proxy -p 80:80 --link personal_registry:registry dockerinaction/basic_proxy 命令创建一个名为 basic_proxy 的容器,该容器监听 80 端口,并与 personal_registry 容器建立链接。
  • 测试连接 docker run --rm -u 1000:1000 --net host dockerinaction/curl -s http://localhost:80/v2/distribution/tags/list 命令从运行 Docker 守护进程的主机发起请求,请求通过反向代理转发到镜像仓库,镜像仓库返回 distribution 仓库中的标签列表。

1.3 反向代理作用

此反向代理除了在网络中增加一跳和提供更安全的 HTTP 接口外,没有为系统添加其他功能。后续可以对该基础配置进行修改,以添加 TLS、身份验证和多版本客户端支持。

2. 配置反向代理的 HTTPS (TLS)

2.1 TLS 的重要性

传输层安全(TLS)提供端点识别、消息完整性和消息隐私,是 Docker 守护进程连接到非本地主机上的镜像仓库的必要条件。

2.2 HTTPS 端点与 HTTP 端点的区别

区别点 HTTP 端点 HTTPS 端点
监听端口 通常为 80 通常为 443
证书和密钥 不需要 需要签名的证书和私钥文件
主机名匹配 无严格要求 服务器和代理配置的主机名必须与创建证书时使用的主机名匹配

2.3 生成私钥、公钥对和自签名证书

使用 Docker 命令生成:

docker run --rm -e COMMON_NAME=localhost -e KEY_NAME=localhost \
    -v "$(pwd)":/certs centurylink/openssl

此命令将生成一个 4096 位的 RSA 密钥对,并将私钥文件和自签名证书存储在当前工作目录中。生成的三个文件中,证书签名请求(CSR)文件可删除。

2.4 创建代理配置文件

创建 tls-proxy.conf 文件,内容如下:

upstream docker-registry {
  server registry:5000;
}
server {
  listen 443 ssl; 
  server_name localhost 
  client_max_body_size 0;
  chunked_transfer_encoding on;
  ssl_certificate /etc/nginx/conf.d/localhost.crt;
  ssl_certificate_key /etc/nginx/conf.d/localhost.key;
  location /v2/ {
    proxy_pass                          http://docker-registry;
    proxy_set_header  Host              $http_host;
    proxy_set_header  X-Real-IP         $remote_addr;
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
}

与基础代理配置相比,该配置监听 443 端口,并注册了 SSL 证书和私钥。

2.5 创建 Dockerfile

创建 tls-proxy.df 文件:

FROM nginx:latest
LABEL source=dockerinaction
LABEL category=infrastructure
COPY ["./tls-proxy.conf", \
      "./localhost.crt", \ 
      "./localhost.key", \ 
      "/etc/nginx/conf.d/"]

2.6 构建并测试新镜像

docker build -t dockerinaction/tls_proxy -f tls-proxy.df .
docker run -d --name tls-proxy -p 443:443  \ 
    --link personal_registry:registry \ 
    dockerinaction/tls_proxy
docker run --rm \
    --net host \
    dockerinaction/curl -ks \ 
    https://localhost:443/v2/distribution/tags/list 

由于使用了自签名证书, curl 命令需要使用 -k 选项忽略证书错误。

2.7 SSH 隧道作为替代方案

对于运行集中式镜像仓库的小团队,也可以使用 SSH 隧道来保护镜像仓库的网络流量。步骤如下:
1. 在与镜像仓库同一台机器上安装 SSH 服务器(OpenSSH)。
2. 将镜像仓库仅映射到机器的回环接口(localhost)。
3. 客户端创建 SSH 隧道:

ssh -f -i my_key user@ssh-host -L 4000:localhost:5000 -N
  1. 客户端使用本地端口 4000 访问镜像仓库。

但 SSH 隧道存在账户管理开销大、对用户技术要求较高等问题,扩展性不如 HTTPS。

3. 添加身份验证层

3.1 可用的身份验证机制

Distribution 项目本身包含三种身份验证机制: silly token htpasswd
- silly :完全不安全,仅用于开发目的,可能在后续版本中移除。
- token :使用 JSON Web Token (JWT),与 Docker Hub 使用的身份验证机制相同,但需要部署单独的身份验证服务。目前开源的 JWT 身份验证服务尚不成熟,不适合生产环境。
- htpasswd :使用 Apache Web Server 实用程序中的 htpasswd 程序生成编码的用户名和密码对,采用 HTTP 基本身份验证,需要与 HTTPS 结合使用。

3.2 创建密码文件

3.2.1 构建 htpasswd 镜像

创建 htpasswd.df 文件:

FROM debian:jessie
LABEL source=dockerinaction
LABEL category=utility
RUN apt-get update && \
    apt-get install -y apache2-utils
ENTRYPOINT ["htpasswd"]

构建镜像:

docker build -t htpasswd -f htpasswd.df .
3.2.2 生成密码文件条目
docker run -it --rm htpasswd -nB <USERNAME>

将输出结果复制到 registry.password 文件中。

3.3 在反向代理层实现 HTTP 基本身份验证

创建 tls-authproxy.conf 文件:

# filename: tls-auth-proxy.conf
upstream docker-registry {
  server registry:5000;
}
server {
  listen 443 ssl;
  server_name localhost
  client_max_body_size 0;
  chunked_transfer_encoding on;
  # SSL
  ssl_certificate /etc/nginx/conf.d/localhost.crt;
  ssl_certificate_key /etc/nginx/conf.d/localhost.key;
  location /v2/ {
    auth_basic "registry.localhost"; 
    auth_basic_user_file /etc/nginx/conf.d/registry.password; 
    proxy_pass                          http://docker-registry;
    proxy_set_header  Host              $http_host;
    proxy_set_header  X-Real-IP         $remote_addr;
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
}

3.4 创建 Dockerfile

创建 tls-auth-proxy.df 文件:

FROM nginx:latest
LABEL source=dockerinaction
LABEL category=infrastructure
COPY ["./tls-auth-proxy.conf", \
      "./localhost.crt", \
      "./localhost.key", \
      "./registry.password", \
      "/etc/nginx/conf.d/"]

3.5 直接为镜像仓库添加 TLS 和基本身份验证

创建 tls-auth-registry.yml 配置文件:

version: 0.1
log:
    level: debug
    fields:
        service: registry
        environment: development
storage:
    filesystem:
        rootdirectory: /var/lib/registry
    cache:
        layerinfo: inmemory
    maintenance:
        uploadpurging:
            enabled: false
http:
    addr: :5000
    secret: asecretforlocaldevelopment
    tls:                             
        certificate: /localhost.crt  
        key: /localhost.key          
    debug:
        addr: localhost:5001
auth:                              
    htpasswd:                      
        realm: registry.localhost  
        path: /registry.password   

3.6 创建 Dockerfile

创建 tls-auth-registry.df 文件:

# Filename: tls-auth-registry.df
FROM registry:2
LABEL source=dockerinaction
LABEL category=infrastructure
CMD ["/tls-auth-registry.yml"]
COPY ["./tls-auth-registry.yml", \
      "./localhost.crt", \
      "./localhost.key", \
      "./registry.password", \
      "/"]

3.7 构建并启动新的安全镜像仓库

docker build -t dockerinaction/secure_registry -f tls-auth-registry.df  .
docker run -d --name secure_registry \
    -p 5443:5000 --restart=always \
    dockerinaction/secure_registry

3.8 注意事项

如果直接为镜像仓库启用 TLS,安装反向代理时可能会遇到问题。因为应用层代理软件(如 NGINX 或 Apache httpd)在 HTTP 层操作,需要检查请求流量。如果 TLS 会话在镜像仓库端终止,代理软件将看到加密流量,导致无法正常路由。解决方案是在代理层终止 TLS 会话,或使用在较低网络层(如第 4 层)操作的代理(负载均衡器)。

4. 客户端兼容性

4.1 问题背景

注册表协议在版本 1 和版本 2 之间发生了巨大变化,Docker 1.6 之前的客户端无法与版本 2 的注册表通信。

4.2 解决方案

通过配置代理来区分版本 1 和版本 2 兼容的客户端,并将请求定向到兼容的注册表服务。

4.3 配置步骤

4.3.1 创建 NGINX 配置文件

创建 dual-client-proxy.conf 文件:

upstream docker-registry-v2 { 
  server registry2:5000;      
}                             
upstream docker-registry-v1 { 
  server registry1:5000;      
}                             
server {
  listen 80;
  server_name localhost;
  client_max_body_size 0;
  chunked_transfer_encoding on;
  location /v1/ { 
    proxy_pass                          http://docker-registry-v1; 
    proxy_set_header  Host              $http_host;
    proxy_set_header  X-Real-IP         $remote_addr;
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
  location /v2/ { 
    proxy_pass                          http://docker-registry-v2; 
    proxy_set_header  Host              $http_host;
    proxy_set_header  X-Real-IP         $remote_addr;
    proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;
  }
}
4.3.2 创建 Dockerfile

创建 dual-client-proxy.df 文件:

# 此处假设简单的基础镜像构建,可根据实际调整
FROM nginx:latest
COPY ./dual-client-proxy.conf /etc/nginx/conf.d/
4.3.3 构建新镜像
docker build -t dockerinaction/dual_client_proxy -f dual-client-proxy.df .

4.4 配置说明

该配置与基础代理配置的主要区别在于增加了第二个上游服务器和对以 /v1/ 开头的 URL 的路由规则,实现了根据客户端请求的注册表 API 版本进行路由。

4.5 流程图

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(客户端请求):::process --> B{请求路径前缀}:::process
    B -->|/v1/| C(v1 注册表):::process
    B -->|/v2/| D(v2 注册表):::process

通过以上步骤,可以构建一个支持多版本客户端的注册表代理,确保不同版本的 Docker 客户端都能正常与注册表进行通信。同时,结合前面介绍的 TLS 和身份验证配置,可以进一步提高注册表的安全性。

5. 总结与最佳实践

5.1 配置总结

配置项 关键步骤 注意事项
基础反向代理 构建镜像、创建反向代理容器并测试连接 仅增加网络跳数和强化 HTTP 接口,可作为后续配置基础
HTTPS (TLS) 配置 生成私钥、公钥对和自签名证书,创建代理配置文件和 Dockerfile,构建并测试新镜像 确保主机名匹配,使用自签名证书时 curl 需加 -k 选项;SSH 隧道可作为小团队替代方案但扩展性差
身份验证层 选择合适的身份验证机制(如 htpasswd ),创建密码文件,在反向代理层或镜像仓库直接添加身份验证 直接为镜像仓库启用 TLS 时安装反向代理可能有问题,需注意代理层操作
客户端兼容性 创建 NGINX 配置文件、Dockerfile,构建新镜像 根据客户端请求的注册表 API 版本进行路由

5.2 最佳实践建议

  • 安全性 :始终使用 TLS 加密通信,结合身份验证机制(如 htpasswd )保护镜像仓库。避免将私钥文件复制到生产镜像中,建议使用卷挂载。
  • 兼容性 :如果需要支持不同版本的 Docker 客户端,实现 API 感知的代理层,确保不同版本的客户端都能正常与注册表通信。
  • 性能 :合理选择代理层的部署方式,避免因加密和身份验证带来过多的性能开销。例如,可在代理层终止 TLS 会话,减少镜像仓库的处理负担。

5.3 未来扩展方向

  • 多数据中心支持 :随着业务的发展,可能需要在多个数据中心部署镜像仓库。可以考虑使用分布式存储和负载均衡技术,实现跨数据中心的镜像仓库服务。
  • 自动化管理 :利用自动化工具(如 Ansible、Terraform 等)实现镜像仓库的自动化部署、配置和管理,提高运维效率。
  • 集成 CI/CD 流程 :将镜像仓库与 CI/CD 流程集成,实现镜像的自动构建、推送和部署,加速软件交付周期。

6. 常见问题解答

6.1 为什么 Docker 守护进程不连接没有 TLS 的注册表?

Docker 守护进程默认要求与注册表的连接使用 TLS 加密,除非注册表运行在本地主机上。这是为了确保通信的安全性,防止中间人攻击和数据泄露。

6.2 如何处理自签名证书的问题?

在测试环境中,可以使用 curl -k 选项忽略证书错误。但在生产环境中,建议使用由受信任的证书颁发机构(CA)签发的证书,以确保通信的安全性和可靠性。

6.3 安装反向代理时遇到加密流量问题怎么办?

如果直接为镜像仓库启用 TLS,应用层代理软件(如 NGINX 或 Apache httpd)可能会看到加密流量,导致无法正常路由。解决方案是在代理层终止 TLS 会话,或使用在较低网络层(如第 4 层)操作的代理(负载均衡器)。

6.4 如何选择合适的身份验证机制?

  • 开发环境 :如果仅用于开发和测试,可以考虑使用简单的身份验证机制,如 silly (但不建议在生产环境使用)。
  • 生产环境 :建议使用 htpasswd token 机制。 htpasswd 简单易用,适合小规模部署; token 机制更适合大规模部署和需要与第三方服务集成的场景,但需要部署单独的身份验证服务。

7. 流程图总结

7.1 整体配置流程

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(基础反向代理配置):::process --> B(HTTPS (TLS) 配置):::process
    B --> C(身份验证层配置):::process
    C --> D(客户端兼容性配置):::process

7.2 客户端请求处理流程

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(客户端请求):::process --> B{是否有 TLS 加密}:::process
    B -->|是| C{是否有身份验证}:::process
    B -->|否| E(错误提示:需 TLS 加密):::process
    C -->|是| F{请求 API 版本}:::process
    C -->|否| G(错误提示:需身份验证):::process
    F -->|v1| H(v1 注册表):::process
    F -->|v2| I(v2 注册表):::process

通过以上的配置和优化,可以构建一个安全、稳定、兼容的集中式镜像仓库,满足不同规模和需求的业务场景。在实际应用中,可根据具体情况灵活调整配置,不断提升镜像仓库的性能和安全性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值