用 Docker Compose搭建一个 Docker 镜像仓库

背景

在构建和管理多个项目时,自动化部署变得至关重要。在这个过程中,拥有一个私有的 Docker 镜像仓库是极其有用的。虽然许多云服务平台提供了这样的仓库服务,但对于那些预算有限或更愿意自行搭建的用户来说,自建一个 Docker 镜像仓库是一个很好的选择。

为了简化配置和管理过程,我们可以采用 Docker Compose 来搭建和维护这个仓库。Docker Compose 允许我们通过一个 docker-compose.yml 文件来定义和配置所有需要的服务,从而使启动和运行整个 Docker 环境变得既简单又高效。

搭建Docker Registry 服务

接下来,我将展示一个基础的 docker-compose.yml 文件示例,用于配置和启动一个本地的 Docker Registry 服务:

version: '3'
services:
  registry:
    image: registry:latest
    ports:
      - "5000:5000"
    environment:
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      - ./data:/data
    restart: always

在同级目录,创建一个 data 目录, ./data 目录挂载到容器的 /data 目录,用来持久化存储数据。

一旦你创建了 docker-compose.yml 文件,就可以使用以下命令来启动你的 Docker Registry:

docker-compose up -d

用 Nginx 设置密码

至此虽然可以用了,但是为了安全性,最好加一个密码,同时我们也会用 https。
我们可以用Nginx 作为反向代理并设置 HTTP 基本认证。

1. 创建一个密码文件

使用 htpasswd 命令来创建这个文件:

htpasswd -Bc registry.passwords yourusername

yourusername 改成你自己的用户名,这个命令将提示你输入密码,并创建一个名为 registry.passwords 的文件,其中包含加密的密码。

  • -B 使用 bcrypt 算法进行加密,这是当前推荐的加密方式,因为它比默认的 md5crypt 更安全。
  • -c 创建一个新的密码文件。如果文件已经存在,它会被覆盖。所以要注意只有在第一次创建密码文件时才使用 -c 参数,之后添加新用户应该去掉 -c,以防止覆盖现有的密码文件。

2. 申请 https 证书

我是在阿里云申请的,有免费的 ssl 证书。你也可以选择别的平台申请
image.png
申请完之后,下载 nginx 证书。有 .pem.key 两个文件。

docker-compose.yml 同级目录创建 certs 文件夹,将下载的两个证书 copy 进去。
我一般是打开复制内容,然后在服务端用 vim 编辑,这样避免了复制文件。

3. docker-compose.yml 的配置

version: '3'
services:
  registry:
    image: registry:latest 
    container_name: registry
    volumes:
      - ./data:/var/lib/registry
      - ./certs:/certs
    networks:
      - registry-net

  nginx:
    image: nginx:alpine
    container_name: nginx
    ports:
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./registry.passwords:/etc/nginx/registry.passwords:ro
      - ./certs:/certs:ro
    depends_on:
      - registry
    networks:
      - registry-net

networks:
  registry-net:
    driver: bridge

volumes:
  registry-data:
    driver: local

请注意,你需要将 ./certs 替换为你的 SSL 证书和密钥的路径,同时将 ./nginx.conf 替换为你的 Nginx 配置文件的路径。同样,registry.passwords 需要替换为你的密码文件路径。

4. 配置 nginx.conf

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    sendfile on;

    upstream docker-registry {
        server registry:5000;
    }

    server {
        listen 443 ssl;
        server_name myregistry.domain.com;

        ssl_certificate /certs/domain.crt;
        ssl_certificate_key /certs/domain.key;

        # SSL configurations go here

        location / {
            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;

            auth_basic "Registry Realm";
            auth_basic_user_file /etc/nginx/registry.passwords;
        }
    }
}

确保替换 myregistry.domain.com 为你的域名,/certs/domain.crt/certs/domain.key 为你的证书和密钥文件的路径。registry.passwords 是你的密码文件。

现在,运行 docker-compose up -d 命令将启动你的带有基本认证的 Docker Registry。任何尝试访问你的 Docker Registry 的客户端现在都需要提供有效的用户名和密码。

如何使用

一旦你已经搭建好带有密码保护的 Docker Registry,并且正在运行,你就可以开始使用它来推送(上传)和拉取(下载)镜像了。这里是使用带有基本认证的私有 Docker Registry 的步骤:

1. 登录到你的 Docker Registry

在你可以推送或拉取任何镜像之前,你需要使用 docker login 命令登录到你的私有 Registry。

docker login myregistry.domain.com

你需要输入你在创建 registry.passwords 文件时设置的用户名和密码。成功登录后,Docker 会存储你的凭证,所以你不需要每次推送或拉取时都登录。

2. 标记本地镜像

在你推送一个镜像之前,你需要使用正确的仓库地址标记你的本地镜像。标记命令的格式是 docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

docker tag my-image myregistry.domain.com/my-image

这里,my-image 是你本地的镜像名,myregistry.domain.com/my-image 是你想要推送到的 Registry 的地址和路径。

3. 推送镜像到 Registry

使用 docker push 命令将镜像推送到你的 Registry

docker push myregistry.domain.com/my-image

4. 从 Registry 拉取镜像

docker pull myregistry.domain.com/my-image

5. 使用 Docker Compose 与私有 Registry

如果你在使用 Docker Compose 并且想要使用你的私有 Registry 中的镜像,你需要在 docker-compose.yml 文件中使用完整的镜像名称。例如:

version: '3'
services:
  myservice:
    image: myregistry.domain.com/my-image
    ports:
     - "8080:80"

确保你已经使用 docker login 登录到你的 Registry,Docker Compose 将会使用存储的凭证来拉取镜像。

6. 注销

当你完成操作后,如果你想要从你的 Docker 客户端注销 Registry,可以使用以下命令:

docker logout myregistry.domain.com

把密码放在了 nginx 端的合理性

将密码(用于基本 HTTP 认证)放在 Nginx 端是一种常见且合理的做法,尤其是当你使用 Nginx 作为 Docker Registry 的反向代理时。这种配置的优点包括:

  1. 安全性:
    • 通过在 Nginx 端处理认证,你可以在请求到达 Docker Registry 之前进行用户验证。这增加了一个安全层,可以防止未授权的访问。
  2. 灵活性和控制:
    • 使用 Nginx 作为认证点可以让你更灵活地控制认证过程,例如,通过自定义 Nginx 的配置来实现更复杂的认证逻辑。
  3. 简化 Docker Registry 的配置:
    • 通过在 Nginx 端处理认证,可以减少 Docker Registry 自身需要的配置。这意味着 Docker Registry 可以以更简单的方式运行,仅专注于其主要功能。
  4. 集中化管理:
    • 如果你运行多个服务,并使用 Nginx 作为统一的入口点,那么在 Nginx 端管理认证可以让你集中管理访问控制。

确保认证信息(如 .htpasswd 文件)安全是非常重要的。这个文件应该存放在一个安全的位置,并确保只有需要的用户(如 Nginx)能够访问。

综上所述,将认证逻辑放在 Nginx 端是一种有效且常见的做法,特别适用于通过 Nginx 作为反向代理来增加额外的安全层和灵活性。只要妥善管理认证凭据,并确保 Nginx 的配置是安全的,这种做法是合理的。


已发布

分类

作者:

标签

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注