S3アップロードをCircleCIで自動化して簡単Webサイト運用

ポートフォリオサイトを作りたいなと思い、S3のWebサイトホスティングで作りました。


折角なので、CircleCiを活用して、GitHubにコードやファイルをpushするとS3へ自動デプロイされる構成としました。以下にその流れを書いていきます。

<img width="716" alt="全体構成.png" src="https://qiita-image-store.s3.amazonaws.com/0/79258/9e59341b-55b6-8031-261a-d5d9606f0c08.png">


##  1. IAMの設定
CircleCIの環境に設定する、IAMユーザーを作成します。

先ずは、IAMの画面からS3へのアクセスポリシーを作成します。
今回はIAMの画面の「ポリシー」の画面から `s3-auth` という名前のポリシーを作成しました。ポリシーは以下の通り記載します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::YOUR_BUCKET_NAME",
                "arn:aws:s3:::YOUR_BUCKET_NAME/*"
            ]
        }
    ]
}
```

ポリシーの作成が完了したら、ユーザーの追加を行います。アクセスの種類は「プログラムによるアクセス」のみを選択、アクセス権限は「既存のポリシーを直接アタッチ」の画面から先程作成した「s3-auth」を選択します。

## 2. S3アクセスポリシーの設定
次に、S3バケットのアクセスポリシーを設定します。
今回は以下3つのアクセス権限を記載しました。

1. 管理者アカウント：バケット操作に対する全権限を付与する。
2. パブリック（サイト訪問者）：S3へのGetObjectのみを許可。
3. CircleCI用権限：PutObject, ListBucket, DeleteObjectのみを許可。

バケットを作成したら、[アクセス権限]>[バケットポリシー]からS3へのアクセスポリシーを設定します。

```json

{
    "Version": "2012-10-17",
    "Id": "YOUR_ID",
    "Statement": [
        {
            "Sid": "Admin",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxxx:user/xxxxxx（管理者ユーザーのarn）"
            },
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        },
        {
            "Sid": "forPublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        },
        {
            "Sid": "forCircleCi",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::xxxxxx:user/xxxxxx(先程作成したCircleCI用IAMユーザーのarn)"
            },
            "Action": [
                "s3:PutObject",
                "s3:ListBucket",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::YOUR_BUCKET_NAME",
                "arn:aws:s3:::YOUR_BUCKET_NAME/*"
            ]
        }
    ]
}
```

この際、[パブリックアクセス設定]の項目内の「新規のパブリックバケットポリシーをブロックする」にチェックが入っているとバケットポリシーを更新できないため、ご注意ください。

## 3. GitHubのリポジトリ作成
今回のプロジェクト用のリポジトリを作成します。

## 4. CircleCIの設定
CircleCIのユーザー登録とGitHub連携の設定を行います。設定が完了すると、管理画面の[AddProjects]を選択した際に、GitHubリポジトリ名の一覧が表示されるかと思います。今回作成したリポジトリ名の隣に表示されている[SetUp Project]ボタンを押します。

次に、該当のプロジェクトのSettingsの画面で、[Environment Variables]のメニューから、[Add Variable]で、CircleCI用に作成したIAMユーザーの `AWS_ACCESS_KEY_ID` と　`AWS_SECRET_ACCESS_KEY` を登録します。

CircleCIのコンテナ上で、AWS CLIによるコマンドが走るようにするために、環境変数を設定しておく必要があります。

<img width="1177" alt="CircleCI.png" src="https://qiita-image-store.s3.amazonaws.com/0/79258/48a75a8b-6b76-1e8e-ad31-ed62678793a7.png">


以上の作業が完了したところで、CircleCIでの自動デプロイ内容を記載したymlファイルを作成します。今回は、現在のプロジェクトのディレクトリ配下の `.circleci/config.yml` に以下の内容を記載しました。

```yml:config.yml
version: 2
 jobs:
   build:
        working_directory: ~/repo
     environment:
            - AWS_S3_BUCKET_NAME: YOUR_BUCKET_NAME
     docker:
       - image: innovatorjapan/awscli:latest
     steps:
       - checkout
       - run:
           name: Deploy to S3 if branch is Master.
           command: |
             if [ "${CIRCLE_BRANCH}" == "master" ]; then
               aws s3 sync ~/repo s3://${AWS_S3_BUCKET_NAME}/ --exact-timestamps --delete
             fi
```
引用：https://qiita.com/fkymnbkz/items/55998497620498f1a59d

## 5. GitHubのMasterへpush

ここまで準備が完了したら、後はGitHubのMasterへコードをPushするだけです。

これで自動デプロイ環境が完成したかと思います。デプロイが成功した場合、CicleCIの管理画面でSuccessと表示されます。