

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 教程：使用 Amazon ECS 标准部署 CodePipeline
<a name="ecs-cd-pipeline"></a>

本教程可帮助您使用 Amazon ECS 创建完整的 end-to-end持续部署 (CD) 管道 CodePipeline。

**重要**  
作为在控制台中创建管道的一部分，S3 工件存储桶将 CodePipeline用于项目。（这与用于 S3 源操作的存储桶不同。） 如果 S3 工件存储桶与您的管道账户位于不同的账户中，请确保 S3 工件存储桶归其所有 AWS 账户 ，该存储桶是安全且可靠的。

**注意**  
本教程适用于 Amazon ECS 的标准部署操作 CodePipeline。有关中使用 Amazon ECS 进行 CodeDeploy 蓝/绿部署操作的教程 CodePipeline，请参阅。[教程：使用 Amazon ECR 源和 ECS-to-CodeDeploy部署创建管道](tutorials-ecs-ecr-codedeploy.md)

**注意**  
本教程适用于 CodePipeline 带有源操作的 Amazon ECS 标准部署操作。有关使用 Amazon ECSstandard 部署操作和 ECRBuildAndPublish 构建操作 CodePipeline 来推送映像的教程，请参阅[教程：使用 CodePipeline （V2 类型）构建 Docker 镜像并将其推送到亚马逊 ECR](tutorials-ecr-build-publish.md)。

## 先决条件
<a name="ecs-cd-prereqs"></a>

您必须先部署一些资源，然后才能使用本教程创建您的 CD 管道。以下是您在开始操作之前需要的资源：

**注意**  
所有这些资源都应在同一个 AWS 区域内创建。
+ 包含您的 Dockerfile 和应用程序源的源代码控制存储库（本教程使用 CodeCommit）。有关更多信息，请参阅《*AWS CodeCommit 用户指南》*中的 “[创建 CodeCommit存储库](https://docs.aws.amazon.com/codecommit/latest/userguide/how-to-create-repository.html)”。
+ 一个 Docker 映像存储库（本教程使用 Amazon ECR），其中包含您从 Dockerfile 和应用程序源构建的映像。有关更多信息，请参阅 *Amazon Elastic Container Registry 用户指南* 中的[创建存储库](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html)和[推送映像](https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-ecr-image.html)。
+ 一个 Amazon ECS 任务定义，该定义会引用在您的映像存储库中托管的 Docker 映像。有关更多信息，请参阅 *Amazon Elastic Container Service 开发者指南* 中的[创建任务定义](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-task-definition.html)。
**重要**  
Amazon ECS 的标准部署操作会根据 Amazon ECS 服务使用的修订版 CodePipeline 创建自己的任务定义修订版。如果您在不更新 Amazon ECS 服务的情况下为任务定义创建新的修订，则部署操作将忽略这些修订。

  以下是本教程中使用的一个任务定义示例。您对 `name` 和 `family` 使用的值将在下一步中用于构建规范文件。

  ```
  {
    "ipcMode": null,
    "executionRoleArn": "{{role_ARN}}",
    "containerDefinitions": [
      {
        "dnsSearchDomains": null,
        "environmentFiles": null,
        "logConfiguration": {
          "logDriver": "awslogs",
          "secretOptions": null,
          "options": {
            "awslogs-group": "/ecs/{{hello-world}}",
            "awslogs-region": "us-west-2",
            "awslogs-stream-prefix": "ecs"
          }
        },
        "entryPoint": null,
        "portMappings": [
          {
            "hostPort": 80,
            "protocol": "tcp",
            "containerPort": 80
          }
        ],
        "command": null,
        "linuxParameters": null,
        "cpu": 0,
        "environment": [],
        "resourceRequirements": null,
        "ulimits": null,
        "dnsServers": null,
        "mountPoints": [],
        "workingDirectory": null,
        "secrets": null,
        "dockerSecurityOptions": null,
        "memory": null,
        "memoryReservation": 128,
        "volumesFrom": [],
        "stopTimeout": null,
        "image": "{{image_name}}",
        "startTimeout": null,
        "firelensConfiguration": null,
        "dependsOn": null,
        "disableNetworking": null,
        "interactive": null,
        "healthCheck": null,
        "essential": true,
        "links": null,
        "hostname": null,
        "extraHosts": null,
        "pseudoTerminal": null,
        "user": null,
        "readonlyRootFilesystem": null,
        "dockerLabels": null,
        "systemControls": null,
        "privileged": null,
        "name": "{{hello-world}}"
      }
    ],
    "placementConstraints": [],
    "memory": "2048",
    "taskRoleArn": null,
    "compatibilities": [
      "EC2",
      "FARGATE"
    ],
    "taskDefinitionArn": "{{ARN}}",
    "family": "{{hello-world}}",
    "requiresAttributes": [],
    "pidMode": null,
    "requiresCompatibilities": [
      "FARGATE"
    ],
    "networkMode": "awsvpc",
    "cpu": "1024",
    "revision": 1,
    "status": "ACTIVE",
    "inferenceAccelerators": null,
    "proxyConfiguration": null,
    "volumes": []
  }
  ```
+ 一个 Amazon ECS 集群，该集群运行着一项使用前述任务定义的服务。有关更多信息，请参阅 *Amazon Elastic Container Service 开发者指南* 中的[创建集群](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html)和[创建服务](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-service-console-v2.html)。

在满足这些先决条件后，您可以继续完成本教程并创建您的 CD 管道。

## 步骤 1：将构建规范文件添加至您的源存储库
<a name="cd-buildspec"></a>

本教程用于 CodeBuild 构建 Docker 镜像并将镜像推送到 Amazon ECR。将 `buildspec.yml` 文件添加至您的源代码存储库以指示 CodeBuild 如何执行此操作。下面的示例构建规范将执行以下操作：
+ 构建前阶段：
  + 登录 Amazon ECR。
  + 将存储库 URI 设置为您的 ECR 映像并添加包含源的 Git 提交 ID 的前七个字符的映像标签。
+ 构建阶段：
  + 构建 Docker 映像并使用 Git 提交 ID 将该映像标记为 `latest`。
+ 构建后阶段：
  + 使用两个标签将该映像推送至 ECR 存储库。
  + 在根目录中编写一个称为 `imagedefinitions.json` 文件，其中包含您的 Amazon ECS 服务的容器名称以及映像和标签。您的 CD 管道的部署阶段将使用此信息来创建您的服务的任务定义的新修订，然后它会将该服务更新为使用此新任务定义。ECS 作业辅助角色需要 `imagedefinitions.json` 文件。

粘贴此示例文本以创建您的 `buildspec.yml` 文件，然后替换映像和任务定义的值。此文本使用示例账户 ID 111122223333。

```
version: 0.2

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - aws --version
      - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin 111122223333.dkr.ecr.us-west-2.amazonaws.com
      - REPOSITORY_URI=012345678910.dkr.ecr.us-west-2.amazonaws.com/hello-world
      - COMMIT_HASH=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
      - IMAGE_TAG=${COMMIT_HASH:=latest}
  build:
    commands:
      - echo Build started on `date`
      - echo Building the Docker image...
      - docker build -t $REPOSITORY_URI:latest .
      - docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker images...
      - docker push $REPOSITORY_URI:latest
      - docker push $REPOSITORY_URI:$IMAGE_TAG
      - echo Writing image definitions file...
      - printf '[{"name":"hello-world","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
    files: imagedefinitions.json
```

构建规范为[先决条件](#ecs-cd-prereqs)中提供的示例任务定义而编写，本教程中的 Amazon ECS 服务使用了该定义。`REPOSITORY_URI` 值对应于 `image` 存储库 (没有任何映像标签)，此文件末尾附近的 `{{hello-world}}` 值对应于该服务的任务定义中的容器名称。

**将 `buildspec.yml` 文件添加至您的源存储库**

1. 打开文本编辑器，然后将上述构建规范复制并粘贴到新文件中。

1. 将 `REPOSITORY_URI` 值 (`{{012345678910.dkr.ecr.us-west-2.amazonaws.com/hello-world}}`) 替换为您的 Docker 映像的 Amazon ECR 存储库 URI（无任何映像标签）。将 `{{hello-world}}` 替换为引用您的 Docker 映像的服务的任务定义中的容器名称。

1. 提交您的 `buildspec.yml` 文件并将其推送至源存储库。

   1. 添加文件。

      ```
      git add .
      ```

   1. 提交更改。

      ```
      git commit -m "Adding build specification."
      ```

   1. 推送提交。

      ```
      git push
      ```

## 步骤 2：创建持续部署管道
<a name="pipeline-wizard"></a>

使用向 CodePipeline 导创建管道阶段并将源存储库连接到 ECS 服务。

**创建管道**

1. 打开 CodePipeline 控制台，网址为[https://console.aws.amazon.com/codepipeline/](https://console.aws.amazon.com/codepipeline/)。

1. 在 **Welcome** 页面上，选择 **Create pipeline**。

   如果这是您第一次使用 CodePipeline，则会显示介绍性页面，而不是 “**欢迎**”。选择 **Get Started Now (立即开始)**。

1. 在**步骤 1：选择创建选项**页面上的**创建选项**下，选择**构建自定义管道**选项。选择**下一步**。

1. 在**步骤 2：选择管道设置**的**管道名称**中，输入管道的名称。在本教程中，管道名称为 **hello-world**。

1. 在**管道类型**中，保留默认选择 **V2**。管道类型有不同的特点和价格。有关更多信息，请参阅 [管道类型](pipeline-types.md)。选择**下一步**。

1. 在 “**步骤 3：添加源舞台**” 页面上，对于**源提供者**，选择** AWS CodeCommit**。

   1. 对于**存储库名称**，选择要用作您的管道的源位置的 CodeCommit 存储库的名称。

   1. 对于 **Branch name (分支名称)**，选择要使用的分支，然后选择 **Next (下一步)**。

1. 在 “**步骤 4：添加构建阶段**” 页面上，选择 “**生成提供者**” **AWS CodeBuild**，然后选择 “**创建项目**”。

   1. 对于 **Project name**，为您的构建项目选择唯一名称。在本教程中，项目名称为 **hello-world**。

   1. 对于**环境映像**，选择**托管映像**。

   1. 对于**操作系统**，选择 **Amazon Linux 2**。

   1. 对于**运行时**，选择**标准**。

   1. 对于**映像**，请选择 **`aws/codebuild/amazonlinux2-x86_64-standard:3.0`**。

   1. 对于 **Image version (映像版本)** 和 **Environment type (环境类型)**，请使用默认值。

   1. 选择**如果要构建 Docker 映像或希望您的构建获得提升的特权，请启用此标志**。

   1. 取消选择**CloudWatch 日志**。您可能需要展开**高级**。

   1. 选择 “**继续” CodePipeline**。

   1. 选择**下一步**。
**注意**  
该向导会为您的生成项目创建一个名为 **codebuild-service {{build-project-name}}-role** 的 CodeBuild 服务角色。记下此角色名称，因为稍后您要向该角色添加 Amazon ECR 权限。

1. 在 “**步骤 5：添加部署阶段**” 页面上，对于**部署提供商**，选择 **Amazon ECS**。

   1. 对于**集群名称**，请选择在其中运行您的服务的 Amazon ECS 集群。在本教程中，该集群为 **default**。

   1. 对于 **Service name (服务名称)**，选择要更新的服务，然后选择 **Next (下一步)**。在本教程中，服务名称为 **hello-world**。

1. 在 **Step 6: Review** 页面上，审查您的管道配置，然后选择 **Create pipeline** 以创建管道。
**注意**  
既然管道已创建好，它将尝试经历不同的管道阶段。但是，向导创建的默认 CodeBuild 角色没有权限执行`buildspec.yml`文件中包含的所有命令，因此生成阶段将失败。下一部分将为构建阶段添加权限。

## 步骤 3：为角色添加 Amazon ECR 权限 CodeBuild
<a name="code-build-perms"></a>

该 CodePipeline 向导为 CodeBuild 构建项目创建了一个名为 **codebuild-service {{build-project-name}}-** role 的 IAM 角色。在本教程中，名称为 **codebuild-hello-world-service-role。**由于 `buildspec.yml` 文件会调用 Amazon ECR API 操作，因此该角色必须具有授权进行这些 Amazon ECR 调用的策略。以下过程帮助您将适当权限附加到该角色。

**向角色添加 Amazon ECR 权限 CodeBuild**

1. 使用 [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) 打开 IAM 控制台。

1. 在左侧导航窗格中，选择 **角色**。

1. 在搜索框中，键入 **codebuild-**，然后选择 CodePipeline 向导创建的角色。在本教程中，角色名称为 **codebuild-hello-world-service-role**。

1. 在 **Summary (摘要)** 页面上，选择 **Attach policies (附加策略)**。

1. 选中 **Amazon EC2 ContainerRegistryPowerUser** 政策左侧的复选框，然后选择**附加政策**。

## 步骤 4：测试您的管道
<a name="commit-change"></a>

您的管道应该具备运行 end-to-end原生 AWS 持续部署所需的一切。现在，通过将代码更改推送至您的源存储库来测试管道的功能。

**测试您的管道**

1. 对您的已配置源存储库进行代码更改，然后提交并推送更改。

1. 打开 CodePipeline 控制台，网址为[https://console.aws.amazon.com/codepipeline/](https://console.aws.amazon.com/codepipeline/)。

1. 从列表中选择您的管道。

1. 监视管道经历不同阶段的进度。您的管道应完成且您的 Amazon ECS 服务运行通过您的代码更改创建的 Docker 映像。