

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

# 如何自定义 Docker 镜像
<a name="docker-custom-images-steps"></a>

请按照以下步骤为 Amazon EMR on EKS 自定义 Docker 映像。这些步骤展示了如何获取基础映像、自定义和发布映像，以及如何使用映像提交工作负载。
+ [先决条件](#docker-custom-images-prereq)
+ [步骤 1：从 Amazon Elastic Container Registry（Amazon ECR）中检索基础镜像](#docker-custom-images-retrieve)
+ [步骤 2：自定义基础镜像](#docker-custom-images-customize)
+ [步骤 3：（可选但建议）验证自定义镜像](#docker-custom-images-validate)
+ [步骤 4：发布自定义镜像](#docker-custom-images-publish)
+ [步骤 5：使用自定义镜像在 Amazon EMR 中提交 Spark 工作负载](#docker-custom-images-submit)

**注意**  
在自定义 Docker 映像时，可能要考虑的其他选项包括为交互式端点进行自定义（以确保拥有所需的依赖项），或使用多架构容器映像：  
[为交互式端点自定义 Docker 映像](docker-custom-images-managed-endpoint.md)
[使用多架构镜像](docker-custom-images-multi-architecture.md)

## 先决条件
<a name="docker-custom-images-prereq"></a>
+ 请完成 Amazon EMR on EKS 的[设置 Amazon EMR on EKS](setting-up.md)步骤。
+ 在您的环境中安装 Docker。有关更多信息，请参阅[获取 Docker](https://docs.docker.com/get-docker/)。

## 步骤 1：从 Amazon Elastic Container Registry（Amazon ECR）中检索基础镜像
<a name="docker-custom-images-retrieve"></a>

基础映像包含用于访问其他 AWS 服务的 Amazon EMR 运行时系统和连接器。对于 Amazon EMR 6.9.0 及更高版本，您可以从 Amazon ECR Public Gallery 获取基础映像。浏览图库以找到映像链接，然后将映像拉到本地工作区。例如，对于 Amazon EMR 7.12.0 版本，以下`docker pull`命令将为您提供最新的标准基础映像。您可以将 `emr-7.12.0:latest` 替换为 `emr-7.12.0-spark-rapids:latest`，检索带 Nvidia RAPIDS Accelerator 的映像。您也可以将 `emr-7.12.0:latest` 替换为 `emr-7.12.0-java11:latest`，使用 Java 11 运行时系统检索映像。

```
docker pull public.ecr.aws/emr-on-eks/spark/emr-7.12.0:latest
```

如果您想检索 Amazon EMR 6.9.0 或更早版本的基础映像，或者如果您希望从每个区域中的 Amazon ECR 注册账户中检索，请使用以下步骤：

1. 选择基础镜像 URI。镜像 URI 遵循格式（`ECR-registry-account.dkr.ecr.Region.amazonaws.com/spark/container-image-tag`），示例如下。

   ```
   895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest
   ```

   要选择您所在区域的基础镜像，请参阅[如何选择基础映像 URI 的详细信息](docker-custom-images-tag.md)。

1. 登录存储基础镜像的 Amazon ECR 存储库。用 Amazon ECR 注册账户和您选择的 AWS 地区替换*895885662937*和。*us-west-2*

   ```
   aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin 895885662937.dkr.ecr.us-west-2.amazonaws.com
   ```

1. 将基础镜像拉入本地 Workspace。*emr-6.6.0:latest*替换为您选择的容器镜像标签。

   ```
   docker pull 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest
   ```

## 步骤 2：自定义基础镜像
<a name="docker-custom-images-customize"></a>

请按照以下步骤自定义您从 Amazon ECR 中拉取的基础映像。

1. 在您的本地 Workspace 上创建新的 `Dockerfile`。

1. 编辑您刚刚创建的 `Dockerfile` 并添加以下内容。该 `Dockerfile` 使用您从 `895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest` 中提取的容器镜像。

   ```
   FROM 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest
   USER root
   ### Add customization commands here ####
   USER hadoop:hadoop
   ```

1. 将命令添加到 `Dockerfile` 以自定义基础镜像。例如，添加命令来安装 Python 库，如以下 `Dockerfile` 所示。

   ```
   FROM 895885662937.dkr.ecr.us-west-2.amazonaws.com/spark/emr-6.6.0:latest
   USER root
   RUN pip3 install --upgrade boto3 pandas numpy // For python 3
   USER hadoop:hadoop
   ```

1. 在创建 `Dockerfile` 的同一目录中，请运行以下命令构建 Docker 镜像。提供 Docker 镜像的名称，*emr6.6\$1custom*例如。

   ```
   docker build -t emr6.6_custom .
   ```

## 步骤 3：（可选但建议）验证自定义镜像
<a name="docker-custom-images-validate"></a>

我们建议您在发布自定义镜像之前测试它的兼容性。您可以使用 [Amazon EMR on EKS 自定义镜像 CLI ](https://github.com/awslabs/amazon-emr-on-eks-custom-image-cli)检查您的镜像是否具有在 Amazon EMR on EKS 上运行所需要的文件结构和正确配置。

**注意**  
Amazon EMR on EKS 的自定义镜像 CLI 无法确认您的镜像没有错误。在删除基础镜像的依赖项时要格外小心。

可以执行以下步骤，验证您的自定义镜像。

1. 下载并安装 Amazon EMR on EKS 自定义镜像 CLI。有关更多信息，请参阅 [Amazon EMR on EKS 自定义镜像 CLI 安装指南](https://github.com/awslabs/amazon-emr-on-eks-custom-image-cli/blob/main/installer/assets/INSTALLATION_GUIDE.md)。

1. 运行以下命令以测试安装。

   ```
   emr-on-eks-custom-image --version
   ```

   下面是此类输出的示例。

   ```
   Amazon EMR on EKS Custom Image CLI
   Version: x.xx
   ```

1. 运行以下命令以验证您的自定义镜像。

   ```
   emr-on-eks-custom-image validate-image -i image_name -r release_version [-t image_type]
   ```
   + `-i` 指定需要验证的本地镜像 URI。它可以是镜像 URI，也可以是为镜像定义的任何名称或标签。
   + `-r` 为基础镜像指定确切的发布版本，例如 `emr-6.6.0-latest`。
   + `-t` 指定镜像类型。如果这是 Spark 镜像，请输入 `spark`。默认值为 `spark`。当前 Amazon EMR on EKS 自定义镜像 CLI 版本仅支持 Spark 运行时镜像。

   如果您成功运行命令并且自定义镜像满足所有必需的配置和文件结构，则返回的输出会显示所有测试结果，如以下示例所示。

   ```
   Amazon EMR on EKS Custom Image Test
   Version: x.xx
   ... Checking if docker cli is installed
   ... Checking Image Manifest
   [INFO] Image ID: xxx
   [INFO] Created On: 2021-05-17T20:50:07.986662904Z
   [INFO] Default User Set to hadoop:hadoop : PASS
   [INFO] Working Directory Set to /home/hadoop : PASS
   [INFO] Entrypoint Set to /usr/bin/entrypoint.sh : PASS
   [INFO] SPARK_HOME is set with value: /usr/lib/spark : PASS
   [INFO] JAVA_HOME is set with value: /etc/alternatives/jre : PASS
   [INFO] File Structure Test for spark-jars in /usr/lib/spark/jars: PASS
   [INFO] File Structure Test for hadoop-files in /usr/lib/hadoop: PASS
   [INFO] File Structure Test for hadoop-jars in /usr/lib/hadoop/lib: PASS
   [INFO] File Structure Test for bin-files in /usr/bin: PASS
   ... Start Running Sample Spark Job
   [INFO] Sample Spark Job Test with local:///usr/lib/spark/examples/jars/spark-examples.jar : PASS
   -----------------------------------------------------------------
   Overall Custom Image Validation Succeeded.
   -----------------------------------------------------------------
   ```

   如果自定义镜像不满足所需的配置或文件结构，则会出现错误消息。返回的输出提供了错误配置或文件结构相关信息。

## 步骤 4：发布自定义镜像
<a name="docker-custom-images-publish"></a>

将新的 Docker 镜像发布到您的 Amazon ECR 注册表。

1. 运行以下命令创建用于存储 Docker 镜像的 Amazon ECR 存储库。为仓库提供一个名称，例如*emr6.6\$1custom\$1repo*。将 *us-west-2* 替换为您的区域。

   ```
   aws ecr create-repository \
       --repository-name emr6.6_custom_repo \
       --image-scanning-configuration scanOnPush=true \
       --region us-west-2
   ```

   有关更多信息，请参阅《Amazon ECR 用户指南》**中的[创建存储库](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html#cli-create-repository)。

1. 运行以下命令对您的默认注册表进行身份验证。

   ```
   aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin aws_account_id.dkr.ecr.us-west-2.amazonaws.com
   ```

   有关更多信息，请参阅《Amazon ECR 用户指南》**中的[对您的默认注册表进行身份验证](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html#cli-authenticate-registry)。

1. 标记镜像并将其发布到您创建的 Amazon ECR 存储库。

   标记镜像。

   ```
   docker tag emr6.6_custom aws_account_id.dkr.ecr.us-west-2.amazonaws.com/emr6.6_custom_repo
   ```

   推送镜像。

   ```
   docker push aws_account_id.dkr.ecr.us-west-2.amazonaws.com/emr6.6_custom_repo
   ```

   有关更多信息，请参阅*《Amazon ECR 用户指南》*中的[将镜像推送到 Amazon ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html#cli-push-image)。

## 步骤 5：使用自定义镜像在 Amazon EMR 中提交 Spark 工作负载
<a name="docker-custom-images-submit"></a>

构建和发布自定义镜像后，您可以使用自定义镜像提交 Amazon EMR on EKS 任务。

首先，创建一个 start-job-run-request .json 文件并指定引用自定义图像的`spark.kubernetes.container.image`参数，如以下示例 JSON 文件所示。

**注意**  
您可以使用 `local://` 方案来引用自定义镜像中的可用文件，如下面所示的 JSON 片段中的 `entryPoint` 参数。您也可以使用 `local://` 方案来引用应用程序依赖项。使用 `local://` 方案引用的所有文件和依赖项必须已存在于自定义镜像的指定路径。

```
{
    "name": "spark-custom-image", 
    "virtualClusterId": "virtual-cluster-id", 
    "executionRoleArn": "execution-role-arn", 
    "releaseLabel": "emr-6.6.0-latest", 
    "jobDriver": {
      "sparkSubmitJobDriver": {
        "entryPoint": "local:///usr/lib/spark/examples/jars/spark-examples.jar", 
        "entryPointArguments": [
                  "10"
              ],
         "sparkSubmitParameters": "--class org.apache.spark.examples.SparkPi --conf spark.kubernetes.container.image=123456789012.dkr.ecr.us-west-2.amazonaws.com/emr6.6_custom_repo"
       }
    }
}
```

您还可以使用 `applicationConfiguration` 属性来引用自定义映像，如以下示例所示。

```
{
    "name": "spark-custom-image", 
    "virtualClusterId": "virtual-cluster-id", 
    "executionRoleArn": "execution-role-arn", 
    "releaseLabel": "emr-6.6.0-latest", 
    "jobDriver": {
      "sparkSubmitJobDriver": {
        "entryPoint": "local:///usr/lib/spark/examples/jars/spark-examples.jar", 
        "entryPointArguments": [
                  "10"
              ],
         "sparkSubmitParameters": "--class org.apache.spark.examples.SparkPi"
       }
    },
    "configurationOverrides": {
        "applicationConfiguration": [
            {
                "classification": "spark-defaults",
                "properties": {
                    "spark.kubernetes.container.image": "123456789012.dkr.ecr.us-west-2.amazonaws.com/emr6.6_custom_repo"
                }
            }
        ]
    }
}
```

然后运行 `start-job-run` 命令提交任务。

```
aws emr-containers start-job-run --cli-input-json file://./start-job-run-request.json
```

在上面的 JSON 示例中，*emr-6.6.0-latest*替换为您的 Amazon EMR 发行版。我们强烈建议您使用 `-latest` 发布版本，以确保所选版本包含最新的安全更新。有关 Amazon EMR 发行版本和相应映像标签的更多信息，请参阅 [如何选择基础映像 URI 的详细信息](docker-custom-images-tag.md)。

**注意**  
您可以使用 `spark.kubernetes.driver.container.image` 和 `spark.kubernetes.executor.container.image` 为驱动程序和执行程序 Pod 指定不同的镜像。