lasciva blog

開発して得た知見やwebビジネスのストック

Elastic BeanstalkにRailsアプリケーションをデプロイした

Elastic BeanstalkでRailsアプリケーションを動かしたので、ハマったところ等をまとめました。
用途は少し限定されますが、負荷も大きくないような簡単なアプリケーションを動かすには良い選択肢になるかなと思いました。

特徴/メリット

  • Dockerfileがあるアプリケーションを簡単に構築できる(※ 他の言語もサポートされてる)
  • Nginxなどのwebサーバーの設定がほとんど不要なので、アプリケーションさえあれば動かせる
  • デプロイフローの構築も割と簡単

デメリット

  • 設定等にハマると、普通に構築した方が早いと思った
  • ログがあまり充実してなさそうなので、要確認
  • ガッツリ本番でリクエストを捌くレベルでは、心もとなく感じた

環境

インフラ構成

f:id:hacking15dog:20210124174200p:plain

デプロイ

GitHub Actionsを利用しました。

  1. Github ActionsでDockerのビルド
  2. imageをECRにpush
  3. Elastic Beastalk上で動かすDockerfile等の作成
  4. 作成したDockerfileをElastic Beastalkへデプロイ

※ 事前にAWSでデプロイユーザを作成し、そのクレデンシャルをGitHubのsecretsで設定しています。

name: AWS Elastic Beanstalk Deploy

on:
  push:
    branches:
      - production

env:
  AWS_REGION: ap-northeast-1
  AWS_ECR_REPO_NAME: application-name

jobs:
  delivery:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Checkout the repository
        uses: actions/checkout@v1
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ env.AWS_REGION }}
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
      - name: Build a docker image, and push to Amazon ECR
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        run: |
          docker build -t $ECR_REGISTRY/$AWS_ECR_REPO_NAME:${{ github.sha }} .
          docker push $ECR_REGISTRY/$AWS_ECR_REPO_NAME:${{ github.sha }}
      - name: Prepare for Beanstalk deployment
        env:
          DOCKER_IMAGE_URL: ${{ steps.login-ecr.outputs.registry }}/${{ env.AWS_ECR_REPO_NAME }}:${{ github.sha }}
        run: |
          cd elastic_beanstalk &&
            ./build_dockerfile.sh &&
            zip -r ./app-${{ github.sha }}.zip ./
      - name: Deploy web to EB
        uses: einaregilsson/beanstalk-deploy@v14
        with:
          aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          application_name: beanstalk-application
          environment_name: app-env
          wait_for_environment_recovery: 90
          version_label: app-${{ github.sha }}
          region: ${{ env.AWS_REGION }}
          deployment_package: elastic_beanstalk/app-${{ github.sha }}.zip

Prepare for Beanstalk deploymentのステップでは、以下のようにDockerfileのimageのURLを書き込んだりしています。

FROM {{DOCKER_IMAGE_URL}}

ENV RAILS_ENV=production

EXPOSE 3000

ENTRYPOINT [""]
CMD ["/usr/bin/docker_init.sh"]

インフラ構築

ドメイン

こちらで無料で取得できました。

www.freenom.com

Elastic Beanstalk周りでハマったところ

Nginxの設定

AWSの公式ドキュメントや、その他の記事を見ていると .ebextentions配下に設定ファイルを置けば読み込まれると言った情報が見られましたが、以下のように .platform配下に置く必要がありました。 .ebextentionsでも実行自体はされるみたいでしたが、Elastic Beanstalkのライフサイクルの都合で、更に上書きされてしまうようでした。

10MB以上のファイルをアップロードすると、413エラーが返ってくる状態だったため、 client_max_body_size を設定しました。

$ tree -a elastic_beanstalk
elastic_beanstalk
├── .platform
│   └── nginx
│       └── conf.d
│           └── client-max-body-size.conf
└── Dockerfile

$ cat elastic_beanstalk/.platform/nginx/conf.d/client-max-body-size.conf
client_max_body_size 30m;

他にも、デプロイ時に実行するフックなどを設定できます。

docs.aws.amazon.com

Sidekiq

今回の用途では、そこまで高負荷でもなく、Sidekiq用にコンテナの数を増やすほどでもなかったので、少し力技で同一のコンテナ上で動かしました。

docker_init.sh

#!/bin/sh
rm -f tmp/pids/server.pid && \
  rails db:migrate && \
    rails assets:precompile && \
    bundle exec sidekiq & \
    rails server -b 0.0.0.0