docker 私有 仓库

Docker提供了一个称为“ Distribution”的开源注册表实现 ,使任何人都可以轻松运行私有Docker注册表。 在本文中,我将简要介绍与Docker集成的AWS服务,并描述如何使用AWS托管您自己的注册表。

在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服务的代理,并向命名集群注册。 任务是一个“运行一次”容器,服务是一个容器,如果该容器停止运行,则应重新启动。 创建新任务或服务时,请指定应在其中运行的群集。 群集处理计划任务和服务实例到成员主机。

为了整合所有码头工人的主机与ECS集群,主机必须运行ECSAgent容器,并要在加入设置集群名称/etc/ecs/ecs.config主机上。 如果您准备将ECS主机配置为在名为“默认”的群集中运行,则可以将启动配置的用户数据设置为以下脚本:

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

目前,使用AWS管理控制台的ECS部分创建默认集群。 它将把所有内容置备到新的VPC中。 您可以自己构建一个,但这样做乏味且细微。 如果沿着那条路走,请准备一个更长的项目。 使用Amazon Linux AMI创建ECS实例,其中已预安装Docker和ECS Agent。

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

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

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

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

# Use the AWS ClI and "make bucket" (mb) command.
aws s3 mb s3://my-docker-registry-data

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

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

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::my-docker-registry-data"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::my-docker-registry-data/*"
            ]
        }
    ]
}

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

aws iam create-policy --policy-name registryaccess --policy-document file://registry-policy.json

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

# Create a user
aws iam create-user --user-name Registry
# Create credentials for the new user
aws iam create-access-key --user-name Registry
# Output similar to:
# {
#     "AccessKey": {
#         "UserName": "Registry",
#         "Status": "Active",
#         "CreateDate": "2015-03-09T18:39:23.411Z",
#         "SecretAccessKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
#         "AccessKeyId": "AKIAXXXXXXXXXXXXX"
#     }
# }

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

aws iam attach-user-policy --policy-arn arn:aws:iam::<YOUR AWS ACCOUNT ID>:policy/registryaccess --user-name Registry

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

使用ECS启动私有Docker注册中心

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

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

# config.yml
version: 0.1
log:
    fields:
        service: registry
http:
    addr: :5000
storage:
    cache:
        layerinfo: inmemory
    s3:
        accesskey: <your awsaccesskey>
        secretkey: <your awssecretkey>
        region: <your bucket region>
        bucket: <your bucketname>
        encrypt: true
        secure: true
        v4auth: true
        chunksize: 5242880
        rootdirectory: /
    
# Dockerfile
FROM registry:2
COPY config.yml /etc/docker/registry/config.yml

无论发生什么情况,都不要在这些文件中包括您的AWS Access Key或AWS Secret Key。 这些都必须提交给版本控制才能使用,最后要做的就是将秘密提交给版本控制。 在下一节中,您将看到在运行时注入配置的更好方法。 确定要在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>

[
    {
      "name": "registry",
      "image": "allingeek/registry:2-s3",
      "cpu": 1024,
      "memory": 1000,
      "entryPoint": [],
      "environment": [
        {
          "name": "REGISTRY_STORAGE_S3_ACCESSKEY",
          "value": "<YOUR NEW IAM USER ACCESS KEY>"
        },
        {
          "name": "REGISTRY_STORAGE_S3_SECRETKEY",
          "value": "<YOUR NEW IAM USER SECRET ACCESS KEY>"
        },
        {
          "name": "REGISTRY_STORAGE_S3_REGION",
          "value": "<YOUR S3 BUCKET REGION>"
        },
        {
          "name": "REGISTRY_STORAGE_S3_BUCKET",
          "value": "<YOUR S3 BUCKET NAME>"
        }
      ],
      "command": ["/etc/docker/registry/config.yml"],
      "portMappings": [
        {
          "hostPort": 5000,
          "containerPort": 5000,
          "protocol": "tcp"
        }
      ],
      "volumesFrom": [],
      "links": [],
      "mountPoints": [],
      "essential": true
    }
]

在此容器定义中声明的环境变量将覆盖与映像一起包装的config.yml文件中相应条目的值。 本文档将在AWS中进行版本控制,并且只有拥有ECS服务权限的用户才能访问。 由于本文档包含机密材料,因此请勿将该文件提交版本控制或在任何公共位置使用。

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

aws ecs register-task-definition --family registry --container-definitions file://registry-task.json

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

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

{
  "serviceName": "s3-registry-elb",
  "taskDefinition": "registry",
  "loadBalancers": [
    {
      "loadBalancerName": "<YOUR ELB NAME, something like: EC2Contai-EcsElast-S06278JGSJCM>",
      "containerName": "registry",
      "containerPort": 5000
    }
  ],
  "desiredCount": 1,
  "role": "ecsServiceRole"
}

关于名为“ ecsServiceRole”的IAM角色的快速说明。 这是应该在群集配置期间创建的IAM角色。 如果遇到尚未创建此角色的问题,则可以使用以下策略自行创建它:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "elasticloadbalancing:Describe*",
        "elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
        "elasticloadbalancing:RegisterInstancesWithLoadBalancer",
        "ec2:Describe*",
        "ec2:AuthorizeSecurityGroupIngress"
      ],
      "Resource": [
        "*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::ecs-registry-demo"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::ecs-registry-demo/*"
      ]
    }
  ]
}

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

aws ecs create-service --service-name s3-registry-elb --cluster <YOUR CLUSTER NAME> --cli-input-json file://ecs-simple-service-elb.json

群集启动后,检查ELB的实例成员资格和侦听器配置。 您应该发现端口80已转发到已部署服务的ECS节点上的端口5000。 启用时,启动Web浏览器并点击http://<YOUR ELB CNAME>/v2/ 。 您应该得到如下响应:

{ }

现在,这就是我所说的防斜线! 您已部署了不安全且未经身份验证的Docker注册表。 更好的测试是将图像推入并尝试再次拉出它。 如果要这样做,则需要在本地Docker守护程序上进行配置更改

结论

弹性容器服务和ECS节点可轻松与AWS现有的扩展和负载平衡技术集成。 它与Docker Hub的集成使入门变得简单。 使用此服务的大部分复杂性在于配置群集和相关基础架构。 有了这些,ECS使得定义和部署服务变得非常简单。

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