ECS FargateからS3へのアクセス

# はじめに
ECS Fargate上で動作するコンテナからS3などのリソースにアクセスする場合、ECS Fargateに設定されているAWSロールを利用することができます。
AWSクレデンシャルを別途作成してコンテナに記載しても良いのですが、Fargateにロールを持っているのであればそれを利用した方がシンプルかと思います。

# ポイント
ECSタスク定義の**タスクロール**を設定することで、上記が環境変数が実行環境に設定されます。
**タスクロールは、コンテナの中身を実行するときに与えられるロールです。**
下に記載の**タスク実行ロールは、コンテナを実行(起動する)ときに必要なロールです。**
![ecs_def_task.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668866/e9267dd1-71d9-3db9-624f-c7836096ee29.png)

# FargateからS3アクセスの実行
Pythonサンプルスクリプト(sample.py)

```Python
import os
import datetime
import boto3

def main():
    file_name = datetime.datetime.now().strftime('run_%Y%m%d_%H%M_%S.txt')
    # コンテナに与えられた環境変数をファイル出力します。
    sample_env = os.environ
    with open(file_name, 'w')as f:
        f.write("#### Environment variables\n")
        for key,value in sample_env.items():
            f.write(f"{key} : {value}\n")
    
 
    bucket_name = "[対象バケット名]"
    s3 = boto3.resource('s3')
    bucket = s3.Bucket(bucket_name)
    bucket.upload_file(Filename=file_name, Key=file_name)


if __name__ == "__main__":
    main()
```

requirements.txt

```text
boto3
```

Dockerfile

```Dockerfile
FROM python:3.8

USER root

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm
ENV SAMPLE_ENV_TEXT "sample env!!"

RUN mkdir -p /root/python

COPY requirements.txt /root/python
COPY sample.py /root/python
COPY run.sh /root/python

WORKDIR /root/python

RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install --no-cache-dir -r requirements.txt

ENTRYPOINT ["sh","run.sh"]
```

ENTRYPOINTのshell (run.sh)

```shell
#!/bin/bash
# echo "echo AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
# echo $AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
# echo "export AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
# echo 'export $（strings /proc/1/environ | grep AWS_CONTAINER_CREDENTIALS_RELATIVE_URI）' >> /etc/bashrc
python sample.py
```

上のファイルをビルドしてECRにpushし、ECS Fargateに実行させます。
今回はECS Fargateの内容は割愛しますが、今後記事にしてみようと思っています。


# コンテナイメージのビルドからECR登録まで
上記ファイルを１つのディレクトリに格納して、以下を実行します。

```sh
# イメージビルド
$ docker build -t sample-python .
・・・
Successfully built <コンテナイメージID>
Successfully tagged sample-python:latest

# タグ付け
$ docker tag <コンテナイメージID> <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/<リポジトリ名>:latest
# ECRログイン
$ aws ecr get-login-password --profile <AWSプロファイル名> | docker login --username AWS --password-stdin <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/<リポジトリ名>
Login Succeeded #が出力されます。
# ECRへPush
$ docker push <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/<リポジトリ名>:latest
```

# ECS Fargateのタスクロールの設定
以下をお好きな名前でIAMのポリシーに登録します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:GetAuthorizationToken",
                "ecr:BatchCheckLayerAvailability",
                "ecr:GetDownloadUrlForLayer",
                "ecr:BatchGetImage",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "s3:*",
                "s3-object-lambda:*"
            ],
            "Resource": "*"
        }
    ]
}
```

単純にAWS管理のポリシーである

- AmazonECSTaskExecutionRolePolicy
- AmazonS3FullAccess

を組み合わせたポリシーです。

このポリシーを**タスクロール**と**タスク実行ロール**に設定するロールを作成してアタッチしてください。
"タスクロール"と"タスク実行ロール"に作成したロールを設定して下さい。

ECSの管理画面でタスク実行すると、対象のS3に環境変数が記載されたファイルが格納されます。


# さいごに
記事にすれば簡単な内容でしたが、この設定だけで半日費やしてしまいました。
記事内の*ENTRYPOINTのshell (run.sh)*で**"なにか変なコメントが？？"**と思われたかもしれませんが、AWS_CONTAINER_CREDENTIALS_RELATIVE_URIなどのFargateのロール取得方法などを色々調べていました。
というのも、TerraformでECS Fargateを設定していたので"タスクロール"の存在に気づきませんでした。
改めてマネージメントコンソールをみて、"なんかある！？"となり、設定することで難なく動きました。
また、記事を書いているときに、"AWSがわざわざコンテナに環境変数を書かせるような面倒くさいことする？？"と思いまして、Fargateからコンテナに環境変数を記載するスクリプトを消しました(コメントアウトのところ)が無事動きました。

とても簡単な内容となりましたが、少しでもどなたかのお役に立てればと思います。