持续部署、Circleci、AWS(Elastic Beanstalk)、Docker

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

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

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

介绍

我们在 Elastic Beanstalk (EB) 下的 Docker 容器中运行我们的一些服务。我们将 Circleci 用于我们的 CI 循环。 EB、Docker 和 Circlec 集成非常适合自动部署。

将所有服务设置为协同工作相当容易。在这篇文章中,我总结了执行此操作的步骤。

关于 EB 应用程序和版本

Elastic Beanstalk 具有应用程序、环境和应用程序版本的概念。我在这里描述的自动步骤直到在 EB 中创建一个新的 应用程序版本 为止。实际部署是使用 Elastic Beanstalk 管理 UI 手动完成的。我也描述一下。

使最后一步自动化很容易,我会在未来添加一篇关于它的帖子。

我不打算描述 CI 周期(测试、自动化等)。这是一个完全不同的、非常重要的话题。但超出了这篇文章的范围。将 GitHub 连接到 circleci 也不在本文的讨论范围之内。

架构

我需要集成四种不同的服务:

基本流程

一切都从推送到 GitHub(我没有包括在上面的列表中)开始。一旦我们将内容推送到 GitHub,circleci 就会被触发并根据 circle.yml 文件运行。 CI 将创建 Docker 映像并将其上传到 Docker-hub。我们使用私有存储库。下一步,CI 将上传一个特殊的 json 文件到 S3。这个文件会告诉EB从哪里得到图像,图像和其他参数。作为交付的最后一步,它将在 EB 中创建一个新的 应用程序版本

流程图

CI Docker EB 部署高级架构

上面的描述和图表是针对从 CI (GitHub) 到 AWS (EB) 的部署部分。它没有描述在 EB 中部署新应用程序修订版的最后一部分。我将在本文后面对此进行描述。

权限

该帖子描述了如何在 docker hub 中使用私有存储库。为了使用私有存储库,我们需要设置几个权限。

  • circleci 需要能够:
    1. 上传镜像到 Docker-Hub
    2. 将 JSON 文件上传到 S3 中的存储桶
    3. 向 Elastic Benastalk 调用 AWS 命令​​(创建新的应用程序修订版)
  • AWS EB 需要能够:
    1. 从 S3 存储桶中提取(获取/列出)数据
    2. 从 Docker-Hub 拉取镜像

我省略了在 GitHub、Circleci、Docker-Hub 和 AWS 中创建用户的部分。

Docker 身份验证

在我们设置身份验证之前,我们需要登录到 Docker 并创建一个 dockercfg 文件。

dockercfg文件

Docker有一个特殊的配置文件,通常命名为.dockercfg。我们需要为有权将图像上传到 docker-hub 和下载图像的用户生成此文件。为了创建它,您需要运行以下命令:
docker login
此命令将在 ~/.docker/.dockercfg 中创建文件
如果要为不同的电子邮件(用户)创建此文件,请使用 -e 选项。
检查: docker登录文档
重要的
Docker 版本 1.6 和 1.7 的文件格式不同。
目前,我们需要使用 1.6 格式。否则 AWS 将无法连接到存储库。

“旧”版本,Docker 1.6


 {
  "https://index.docker.io/v1/": {
    "auth": "AUTH_KEY",
    "email": "DOCKER_EMAIL"
  }
}

较新的 (Docker 1.7) 版本的配置文件

这可能是在您的计算机中生成的文件。


 {
  "https://index.docker.io/v1/": {
    "auth": "AUTH_KEY",
    "email": "DOCKER_EMAIL"
  }
}


正确的格式基于 EB 使用的 Docker 版本。我们需要将其添加到可访问的 S3 存储桶中。这在后面的帖子中解释。

从 Circleci 上传到 Docker Hub

在 Docker Hub 中设置用户

  1. 在 docker hub 中,创建一个团队(为您的组织)。
  2. 在存储库中,单击“协作者”并添加具有写入权限的团队。
  3. 在组织下,单击团队。将“部署者”用户添加到团队中。这是拥有前面描述的文件的用户。

我创建了一个特殊的用户,专门为此使用了特定的电子邮件。
该团队中的用户(写权限)需要有一个 dockercfg 文件。

使用 Docker-Hub 权限设置 circle.yml 文件

文档 解释了如何设置权限,如下所示:
docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
但我们的做法有所不同。在部署部分,我们操作了 dockercfg 文件。这是我们的 circle.yml 文件中的部分:


 {
  "https://index.docker.io/v1/": {
    "auth": "AUTH_KEY",
    "email": "DOCKER_EMAIL"
  }
}


Circleci 使用环境变量。所以我们也需要设置它们。
我们需要设置 docker 身份验证密钥和电子邮件。
稍后我们会设置更多。

在 circleci 中设置环境变量

在 Circelci 的项目设置下,点击 Environment Variables

设置 -> 环境变量

添加两个环境变量: DOCKER_AUTH DOCKER_EMAIL
这些值应该是之前创建的文件中的值。

将 JSON 文件上传到 S3 中的存储桶

部署周期的一部分是将 JSON 描述符文件上传到 S3。所以Circleci需要有这个操作的权限。我们将使用 AWS 的 IAM 权限策略。我决定为所有项目的所有部署使用一个 S3 存储桶。这将使我的生活更轻松,因为我将能够使用相同的用户、权限和策略。每个项目/可部署部分将位于不同的目录中。

以下是设置 AWS 环境的步骤。

  1. 创建部署桶
  2. 在 AWS 中创建用户(或决定使用现有用户)
  3. 将 AWS 提供的用户凭证(已下载)保存在手边
  4. 在 AWS 中创建允许以下操作的策略:
    1. 访问存储桶
    2. 在 EB 中创建应用程序版本
  5. 将此策略添加到用户(在 circleci 中设置)
  6. 使用 AWS 提供的凭证在 Circleci 中设置环境变量

创建策略

在 AWS 中,转到 IAM 并单击左侧导航栏中的 策略
单击 创建策略
您可以使用策略管理器,也可以创建以下策略:


 {
  "https://index.docker.io/v1/": {
    "auth": "AUTH_KEY",
    "email": "DOCKER_EMAIL"
  }
}


如上所述,此策略允许访问特定存储桶 (MY_DEPLOY_BUCKET) 的子目录。它允许触发在 EB 中创建新的应用程序版本。本政策将由在circleci注册的用户使用。

Circleci 中的 AWS 权限

Circleci 对 AWS 集成有特殊设置。
在左侧导航栏中,单击 AWS 权限
将访问密钥和秘密放在正确的字段中。
您应该从 AWS 生成的凭证文件中获得这些密钥。

从 S3 存储桶中提取(获取/列出)数据

我们现在需要授予对 EB 实例的访问权限以从 S3 获取一些数据。
EB 实例将需要获取 dockercfg 文件(如前所述)
在 EB 中,您可以设置 Instance profile 。此配置文件将授予实例权限。
但首先,我们需要制定一项政策。和我们之前做的一样。

在 AWS 中创建策略


 {
  "https://index.docker.io/v1/": {
    "auth": "AUTH_KEY",
    "email": "DOCKER_EMAIL"
  }
}


此策略授予对部署存储桶和子目录的读取访问权限。 EB 实例将需要访问存储桶的根目录,因为这是我将放置 dockercfg 文件的地方。它需要子目录访问权限,因为这是 circleci 上传 JSON 描述符文件的位置。

为 EB 实例设置此策略

在 EB 仪表板中:

  1. 转到应用程序仪表板(单击您正在设置的应用程序)➜
  2. 单击要自动部署的环境 ➜
  3. 单击左侧导航栏中的 配置
  4. 单击实例的设置按钮 ➜
  5. 您将看到 Instance profile 您需要设置一个角色。确保此角色具有您在上一步中创建的策略。 ➜
  6. 应用更改

从 Docker-Hub 拉取镜像

为了让 EB 实例能够从 Dockerhub 下载镜像,我们需要给它权限。
EB 为此使用 dockercfg。
将 dockercfg(如上所述)上传到 EB 具有权限的存储桶(在我的示例中: MY_DEPLOY_BUCKET
放在bucket的根目录下。
稍后,您将使用此文件名在 circleci 中设置环境变量。

设置 Circleci 脚本

设置完所有权限和环境后,我们就可以设置circleci脚本了。 Circleci 使用 circle.yml 文件来配置构建项目的步骤。在本节中,我将解释如何配置此文件以使用 Docker 和 EB 进行持续部署。该文件中的其他元素超出范围。我将示例脚本添加到 GitHub

circle.yml 文件

以下是 circle.yml 文件中的相关部分


 {
  "https://index.docker.io/v1/": {
    "auth": "AUTH_KEY",
    "email": "DOCKER_EMAIL"
  }
}

模板描述文件

AWS EB 使用一个 JSON 文件来获取 docker hub 的信息。它需要知道图像在哪里(组织、图像、标签)。它还需要知道从哪里获取 dockercfg 文件。将此文件放在项目的根目录中。


 {
  "https://index.docker.io/v1/": {
    "auth": "AUTH_KEY",
    "email": "DOCKER_EMAIL"
  }
}


我们运行的第一个脚本将替换标签并创建一个新文件。环境变量列表如下所述。

操作描述符模板文件的脚本

将此文件放在项目的根目录中。


 {
  "https://index.docker.io/v1/": {
    "auth": "AUTH_KEY",
    "email": "DOCKER_EMAIL"
  }
}

向 EB 添加新 应用程序版本 的脚本

最后一个自动化步骤是使用新的应用程序版本触发 AWS EB。
每次提交(在 master 中)使用标签和不同的图像,有助于跟踪哪个版本在哪个环境中。
即使我们使用单一环境(“真正的”持续部署),也更容易跟踪和回滚。
将此文件放在项目的根目录中。


 {
  "https://index.docker.io/v1/": {
    "auth": "AUTH_KEY",
    "email": "DOCKER_EMAIL"
  }
}

在 circleci 中设置环境变量

为了使脚本和配置文件可重用,我到处都使用了环境变量。以下是我用于配置文件和脚本的环境变量。

AUTHENTICATION_KEY – dockercfg 文件的名称,位于 S3 存储桶中。
AWS_APPLICATION_NAME – EB 中的应用程序名称
BUCKET_DIRECTORY – 我们上传 JSON 描述符文件的目录
DEPLOYMENT_BUCKET – S3 存储桶名称
DOCKER_AUTH – 连接到 dockerhub 的授权密钥(使用 docker login 创建)
DOCKER_EMAIL – 授权密钥的电子邮件
EXPOSED_PORTS – Docker 端口
IMAGE_NAME – 每个 Docker 镜像都有一个名称。然后是: Organisation:Image-Name
REGION – EB 应用程序的 AWS 区域

脚本/配置文件中的一些环境变量由circleci提供(如CIRCLE_SHA1和CIRCLE_BRANCH)

在 AWS EB 中部署

将应用程序版本上传到 EB 后,我们可以决定将其部署到 EB 中的环境。按着这些次序:

  1. 在 EB 中,在应用程序仪表板中,单击左侧导航栏中的 应用程序版本
  2. 您将看到一个包含所有标记版本的表格。检查您要部署的版本(SHA1 可以帮助了解部署的提交和内容)
  3. 点击部署
  4. 选择环境
  5. 你完成了

AWS EB 应用程序版本

概括

为一个项目设置好后,就可以轻松地为其他项目重用脚本和权限。有了这个 CD 程序,部署和版本跟踪就变得容易了。下一步,即将新版本部署到 EB 环境非常简单。我会为此添加一个不同的帖子。