【GitHub Actions】Fargateへの自動デプロイ時にハマったことと対応まとめ

# 概要
下記記事を参考にGitHub ActionsでのCI/CDを構築した。

- test

https://zenn.dev/ryouzi/articles/cd6857c08e60e7

- deploy

https://qiita.com/hatsu/items/a70d5c49a39561836751

※ubuntuとcheckoutについてはそれぞれ最新バージョンに変更して利用した。
  - ubuntu→latest
  - checkout→v3


テストの方は特に問題なく設定できたが、デプロイではハマる箇所が多かったためまとめ。


# 環境
- アプリ
  - ruby 3.0.2
  - rails 6.1.4
  - mysql 8.0.31
- インフラ
基本的にこちらの記事の通り。

https://qiita.com/hatsu/items/22e11e94a0a981d78efa

HTTPSでアクセスできるようSSL化まで行っている、
ローカル→(HTTPS)→ALB→(HTTP)→Fargate⇄RDS
の状態。

# 発生したエラーと対応

### Error: User: arn:aws:iam::***:user/xx-user is not authorized to perform: ecr:GetAuthorizationToken on resource: * because no identity-based policy allows the ecr:GetAuthorizationToken action

GitHub Actions上でのエラー。
workflows/deploy.ymlが途中で停止してしまう。

#### 原因と対応

権限の設定が無いことが原因とみられる。

https://dev.classmethod.jp/articles/githubactions-ecs-fargate-cicd-beginner/

既存のIAMユーザー（xx-user）に対して、AWS管理のポリシーをアタッチ。

`IAM/ユーザー/xx-user/許可を追加/ポリシーを直接アタッチする`

>ECR用：AmazonEC2ContainerRegistryPowerUser
>ECS用：AmazonECS_FullAccess


### undefined method `[]' for nil:NilClass (NoMethodError)

deploy.ymlの処理は一通り実行でき、指定したタスク定義からタスクが実行されたが、タスク実行中にエラー発生。
ログによると、発生箇所は下記ファイルの９行目。

```ruby:config/initializers/carrierwave.rb
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

CarrierWave.configure do |config|
  if Rails.env.production?
    config.fog_credentials = {
      provider: 'AWS',
      ↓ここでエラーが発生
      aws_access_key_id: Rails.application.credentials.aws[:access_key_id],
      aws_secret_access_key: Rails.application.credentials.aws[:secret_access_key],
      region: 'ap-northeast-1'
    }
    config.fog_public = false
    config.storage = :fog
    config.fog_provider = 'fog/aws'
    config.fog_directory = 'static.my-app.com'
    config.asset_host = 'https://static.my-app.com'
  else
    config.storage :file
    config.enable_processing = false if Rails.env.test?
  end
end
```

※carrierwaveでアップロードする画像の保存先をS3にしているため、ここでAWSへのアクセス情報をcredentialsを利用して渡している。

ローカルでの手動ビルドおよびタスクの手動実行（ローカルにて手動でdockerイメージビルドを行い、ECRへプッシュ、そのイメージをコンテナに指定してタスクを実行）では問題なくデプロイできるため、実行環境の違いに原因があると思われる。


#### 原因と対応
credentialsに設定した環境変数を利用するには、config/master.keyが必要だが、
- dockerイメージビルド時に参照不可（.dockerignoreに記載しているため）
- GitHub上でも参照不可（.gitignoreに記載しているため）
そこで、AWS Systems Managerを利用する。


https://qiita.com/hatsu/items/22e11e94a0a981d78efa#system-manager%E3%81%A7%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%82%B9%E3%83%88%E3%82%A2%E3%81%AE%E4%BD%9C%E6%88%90

AWS Systems Managerで設定したパラメータを利用するには、タスク実行ロールに権限設定が必要。

https://dev.classmethod.jp/articles/ecs-secrets/

https://zoo200.net/ecs-environment-variable-set-secret/

IAM/ロール/ecsTaskExecutionRole/許可を追加/インラインポリシーを作成/JSON/下記貼り付け/ポリシーの確認/任意の名前で新規作成

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ssm:GetParameters",
        "secretsmanager:GetSecretValue",
        "kms:Decrypt"
      ],
      "Resource": "*"
    }
  ]
}
```

ここまで設定できたら、先ほどの箇所を変更。

```diff_ruby
- aws_access_key_id: Rails.application.credentials.aws[:access_key_id],
- aws_secret_access_key: Rails.application.credentials.aws[:secret_access_key],
+ aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
+ aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
```

※その他config/database.yml等も必要に応じて変更する。

### No such file or directory @ rb_sysopen - tmp/pids/server.pid
タスクのログにて、compile完了までは確認できたが、ファイルが無いということで起動がうまくいっていない。

#### 原因と対応
.gitignoreでtmpディレクトリ全体を指定しているため、必要なファイルが参照できていない状態。
```!/tmp/pids```を追加する。
```diff:.gitignore
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
!/tmp/sockets
+ !/tmp/pids
```

尚、
```!/tmp/pids/.keep```
という記述方法では、/tmp/pidsディレクトリをバージョン管理に含めることはできなかったので注意。

# 最後に
より良い方法や間違い等ありましたらご指摘いただけますと幸いです！