在 EC2 上运行私有 Docker 注册表

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

Docker 提供了一个名为“Distribution”的 开源注册表实现 ,使任何人都可以轻松运行私有 Docker 注册表。

在 AWS 云中运行服务器软件有几个优势:

  • 复杂的网络基础设施管理
  • 先进的访问控制工具
  • 弹性负载均衡器
  • 集成 DNS 管理

AWS 还通过 Elastic Container Service (ECS) 和 Elastic Beanstalk 提供 Docker 容器管理服务。这两种服务在一个重要方面有所不同:ECS 专注于在预配置和配置的硬件上管理任务和服务(作为容器运行),而 Elastic Beanstalk 是一种用于配置旨在运行指定应用程序的整个堆栈的工具。

Elastic Beanstalk 用于为其运行的应用程序定义平台和上下文。现在通过 Docker 集成,您可以在容器中运行平台无关的应用程序,并且 ECS 比 Elastic Beanstalk 更能突出基于 Docker 的部署的优势。出于这个原因并考虑到 Elastic Beanstalk 上现有的丰富内容,本文将使用 ECS。

弹性容器服务 (ECS) 不是主机配置服务。虽然管理控制台确实提供了一个用于配置基本集群基础设施的屏幕,但它仅在后端使用 CloudFormation 模板。使用该模板配置集群后,必须直接使用特定于资源的工具对新基础架构进行更改。这也意味着与现有基础架构或专业化的集成很难通过该自动化集群配置器实现。如果您总体上对 AWS 感到满意,您应该配置自己的 ECS 集成 EC2 主机(稍后会详细介绍)。

ECS 从事管理“集群”、“任务”和“服务”的业务。集群是解析为一组成员主机的名称。当一台 ECS 主机上线时,它会启动一个连接到 ECS 服务的代理,并向一个命名的集群注册。任务是“运行一次”的容器,而服务是停止时应该重新启动的容器。当你创建一个新的任务或服务时,你指定了它应该运行的集群。集群为成员主机处理调度任务和服务实例。

要将任何 Docker 主机与 ECS 集群集成,该主机必须运行 ECSAgent 容器并在主机上的 /etc/ecs/ecs.config 中设置要加入的集群名称。如果您要配置 ECS 主机以在名为“default”的集群中运行,您可以将启动配置的用户数据设置为以下脚本:


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

现在,使用 AWS 管理控制台的 ECS 部分创建默认集群。它会将所有内容提供给一个新的 VPC。您可以自己构建一个,但这样做既乏味又微妙。如果您沿着那条路线前进,请为更长的项目做好准备。 ECS 实例是使用 Amazon Linux AMI 创建的,其中已预安装 Docker 和 ECS 代理。

在开始之前,请确保您已创建 AWS 账户、安装 AWS 命令​​行界面 (CLI) 并配置您的环境以使用您的账户。您可以在此处找到有关 安装和配置 CLI 的 信息。

为您的私有 Docker 注册表准备 AWS 资源

Docker Distribution 项目 是 Docker Registry API 的开源实现。虽然 ECS 集群应该已经配置了运行容器所需的所有 AWS 资源,但 Distribution 项目具有(可选)与 S3 的应用程序级集成。要利用它,您需要配置一些应用程序级 AWS 依赖项。

您将创建的第一个 AWS 资源是一个 S3 存储桶,注册表将在其中存储其数据。您可以通过管理控制台或命令行创建新存储桶。在以下命令中将“my-docker-registry-data”替换为您选择的存储桶名称:


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

前面我提到了 AWS 的复杂访问控制工具。好吧,如果您的私有 Docker 注册表无法读取或写入新的 S3 存储桶,那么它就没有用。下一步是创建一个新的 IAM 策略,向存储桶授予读/写权限。

创建一个名为“registry-policy.json”的新文件并包含以下文档。确保将“my-docker-registry-data”替换为您为新 S3 存储桶选择的名称。


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

保存策略文件后,使用以下命令在 AWS 中注册它。此操作将需要 IAM 管理权限:


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

接下来为您的注册表创建一个新的 IAM 用户和凭证,并附加您刚刚创建的策略。选择特定于用例的用户名。我用过“注册表”。您可以使用以下两个命令从命令行创建用户:


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

请注意响应输出提供的 AccessKeyId 和 SecretAccessKey。您需要向注册表提供这些值,以便它可以作为注册表用户向 AWS 进行身份验证。在继续之前,请使用以下命令将您创建的策略附加到新用户。确保将 <YOUR AWS ACCOUNT ID > 替换为您的实际账户 ID。


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

附加策略后,注册表用户将能够(并且只能)读取、写入和列出您创建的存储桶中的文件。这是启动注册表之前所需的最后一项准备工作。

使用 ECS 启动私有 Docker 注册表

在 ECS 集群中启动任何应用程序意味着识别您要运行的一个或多个图像,定义将使用这些图像的容器,并设置缩放选项。在此示例中,您将启动 "registry:2" 映像的特化。

您可以使用类似于以下两个的 config.yml 和 Dockerfile 来构建自己的专业化。您可以在此处找到 Docker Distribution 配置文件 的文档。如果您更愿意重用资源而不是担心创建 Docker Hub 存储库,那么您应该使用我发布的具有这个确切配置的图像。存储库名称是 "allingeek/registry:2-s3." 如果您想进一步专门化您的配置,您将需要构建您自己的或分叉现有的图像。


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

无论发生什么情况,都不要在这些文件中包含您的 AWS 访问密钥或 AWS 秘密密钥。这些需要提交给版本控制才能使用,而您最不想做的就是将秘密提交给版本控制。您将在下一节中看到有更好的方法在运行时注入配置。确定要在 ECS 中运行的映像后,您需要定义任务系列和服务。

任务系列定义了一组版本化的容器定义。在这个例子中,我们只需要一个容器。创建一个名为“registry-task.json”的新文件并粘贴到以下文档中。将 <YOUR NEW IAM USER ACCESS KEY> <YOUR NEW IAM USER SECRET ACCESS KEY> 替换为您之前运行的 create-user 命令返回的 AccessKey 和 SecretAccessKey。您还需要将 <YOUR S3 BUCKET REGION> <YOUR S3 BUCKET NAME> 替换为适当的值。


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

此容器定义中声明的环境变量将覆盖与图像打包的 config.yml 文件中相应条目的值。本文档将在 AWS 中进行版本控制,并且仅供具有 ECS 服务权限的用户访问。由于本文档包含机密材料,因此请勿以其他方式将此文件提交给版本控制或在任何公共位置提供。

创建容器定义列表文件后,使用以下命令注册新任务系列:


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

接下来您需要定义一个将在您的集群上运行的服务。您可以在此处找到 create-service 命令的 CLI 文档 。 ECS 提供的负载均衡器成员资格功能非常节省时间,因此您应该在这里尝试一下。

创建一个描述您的服务的新文档。将新文件命名为“registry-service.json”。将以下内容复制并粘贴到该文件中,并将 <YOUR ELB NAME... 替换为为您的集群创建的负载均衡器的名称。如果您使用管理控制台提供的集群供应器,那么这应该是该 VPC 中唯一的负载均衡器。如果您已经在自己的VPC中搭建了自己的ECS节点并注册了自己的集群,那么您应该在该VPC中创建一个新的ELB。


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

关于名为“ecsServiceRole”的 IAM 角色的快速说明。这是一个 IAM 角色,应该在集群配置期间创建。如果你遇到这个角色还没有创建的问题,你可以用下面的策略自己创建:


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

一旦您创建了服务描述文档(并创建了必需的 IAM 角色),请继续使用您的集群启动该服务。默认情况下,ECS 创建一个名为“default”的集群,您可以在以下命令中省略“cluster”参数。但是,如果您创建了自己的集群,则需要将 <YOUR CLUSTER NAME> 替换为您选择的名称。


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

集群启动后,检查 ELB 的实例成员资格和侦听器配置。您应该会发现80端口正在转发到已部署服务的ECS节点上的5000端口。当它是时,启动网络浏览器并点击 http://<YOUR ELB CNAME>/v2/ 。你应该得到这样的回应:


 #!/bin/bash
echo ECS_CLUSTER=default >> /etc/ecs/ecs.config

现在这就是我所说的虎头蛇尾!您部署了一个不安全且未经身份验证的 Docker 注册表。更好的测试是推送图像并再次尝试拉取它。如果您想这样做,您需要 对本地 Docker 守护进程进行配置更改

综上所述

Elastic Container Service 和 ECS 节点提供与 AWS 现有扩展和负载平衡技术的轻松集成。它与 Docker Hub 的集成使入门变得简单。使用此服务的大部分复杂性在于配置集群和相关基础设施。有了它,ECS 使定义和部署服务变得像几个命令一样简单。

您可以通过几种不同的方式独立扩展此示例。首先,通过将 SSL 证书上传到 AWS 来保护您的私有 Docker 注册表,并使用 HTTPS 侦听器配置您的负载均衡器。其次,考虑实施注册认证机制。可以在 分发配置文档 中找到这样做的说明。最后,尝试将服务扩展到多个实例,看看服务如何维护 ELB 实例成员资格。