【CircleCIによるCI/CD】terraform AWS環境構築 番外

AWS

AWSRails + Nginxな環境をTerraformで構築してみようと思います。

はじめに

本連載で一つずつインフラを構築していきます。

ドメインのhttps化したり、ECS Fargateを使用したコンテナオーケストレーションを用いてアプリケーションをデプロイします。

この記事では、インフラの自動化を行います。

環境は以下です。

OS Cataline 10.15.6
Terraform 0.14.4

 

 

 

基本構文などこちらにまとめてますので、よかったらみてください!
AWS Terraform 基本コード まとめ

連載一覧

やること

以下の導入をします。

  • RSpec の導入
  • CircleCI の導入

インフラの自動化

CircleCI でテスト完了後、自動でデプロイしてくれるように設定します。

RSpec の導入

gem のインストール

Gemfile に以下を追記します。

group :development, :test do
  gem 'rspec-rails', '~> 5.0.0'
end

bundle のインストール

$ bundle install
rspec のインストール

以下のコマンドで rspec をインストールします。

$ rails g rspec:install
簡単なテストの実装

root_path にアクセスして「ステータスコード200」が返ってくるかテストしてみましょう。

spec/requests/home_controller.rb

require 'rails_helper'

RSpec.describe "Homes", type: :request do
  describe "GET /index" do
    it 'responds successfully' do
      get '/'
      expect(response).to have_http_status 200
    end
  end
end

以下のコマンドでテスト実行してみましょう。

$ rails specHomes GET /index  responds successfully Finished in 3.88 seconds (files took 1.78 seconds to load) 1 example, 0 failures

CircleCI の導入

.circleciフォルダとconfig.yml を作成して導入準備をします。

.cricleci/config.yml

version: 2.1
orbs:
  aws-ecr: circleci/aws-ecr@6.15.3
  aws-ecs: circleci/aws-ecs@2.1.0
  aws-cli: circleci/aws-cli@2.0.0
jobs:
  test:
    docker:
      - image: circleci/ruby:2.7.1-node-browsers
        environment:
          RAILS_ENV: test
          MYSQL_HOST: 127.0.0.1
          MYSQL_PORT: 3306
          MYSQL_USER: root
          MYSQL_ROOT_PASSWORD: password
      - image: circleci/mysql:8.0.16
        command: mysqld --default-authentication-plugin=mysql_native_password
        environment:
          MYSQL_HOST: 127.0.0.1
          MYSQL_USER: root
          MYSQL_ROOT_PASSWORD: password
    working_directory: ~/terraform_and_rails/rails_hello
    steps:
      - checkout:
          path: ~/terraform_and_rails
      - restore_cache:
          keys:
            - rails-bundle-v2-{{ checksum "Gemfile.lock" }}
            - rails-bundle-v2-
      - run:
          name: bundle install
          command: bundle check --path vendor/bundle || bundle install --deployment
      - save_cache:
          key: rails-bundle-v2-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle
      - restore_cache:
          keys:
            - rails-yarn-{{ checksum "yarn.lock" }}
            - rails-yarn-
      - run:
          name: yarn install
          command: yarn install --cache-folder ~/.cache/yarn
      - save_cache:
          key: rails-yarn-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache/yarn
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://127.0.0.1:3306 -timeout 3m
      - run:
          name: Confiure Database setting
          command: mv ./config/database.yml.ci ./config/database.yml
      - run:
          name: DB create
          command: bundle exec rake db:create
      - run:
          name: Run rspec
          command: |
            mkdir /tmp/test-results
            TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | \
              circleci tests split --split-by=timings)"
            bundle exec rspec \
              --format progress \
              --out /tmp/test-results/rspec.xml \
              --format documentation \
              $TEST_FILES
      - store_test_results:
          path: /tmp/test-results
      - store_artifacts:
          path: /tmp/test-results
          destination: test-results
workflows:
  version: 2.1
  test:
    jobs:
      - test
      - aws-ecr/build-and-push-image:
          requires:
            - test
          aws-access-key-id: ACCESS_KEY_ID
          aws-secret-access-key: SECRET_ACCESS_KEY
          path: ./rails_hello/
          dockerfile: containers/app/Dockerfile
          account-url: AWS_ECR_ACCOUNT_URL
          repo: '${AWS_RESOURCE_RAILS}'
          region: AWS_DEFAULT_REGION
          tag: latest
          extra-build-args: '--build-arg RAILS_MASTER_KEY=${RAILS_MASTER_KEY}'
      - aws-ecs/deploy-service-update:
          requires:
            - aws-ecr/build-and-push-image
          aws-region: AWS_DEFAULT_REGION
          aws-access-key-id: ACCESS_KEY_ID
          aws-secret-access-key: SECRET_ACCESS_KEY
          family: 'rails_hello'
          cluster-name: 'rails-hello'
          service-name: 'rails_hello-service'
          container-image-name-updates: 'container=rails,tag=latest'

test ジョブにて、gemのインストールやテストDBの用意してテストを実行します。

テストが成功すると、ビルドとECSサービスのアップデートが起動します。

  • aws-ecr/build-and-push-image :ビルドしてECRにプッシュする
    • aws-access-key-id :AWSのアクセスキー
    • aws-secret-access-key:AWSのシークレットキー
    • path:ビルドするディレクトリ
    • dockerfile:ビルドするDockerfile
    • account-url:ECRのURL
    • repo:ECRのレポジトリ名
    • region:リージョン
    • tag:タグ
    • extra-build-args:ビルドする環境変数
  • aws-ecs/deploy-service-update:ECSサービスのアップデート
    • aws-region:リージョン
    • aws-access-key-id :AWSのアクセスキー
    • aws-secret-access-key:AWSのシークレットキー
    • family:タスク名
    • cluster-name:クラスター名
    • service-name:サービス名
    • container-image-name-updates:アップデートするコンテナとタグ

以下の環境変数をCircleCIに設定してします。

  • ACCESS_KEY_ID:<AWSのアクセスキー>
  • SECRET_ACCESS_KEY:<AWSのシークレットキー>
  • AWS_ECR_ACCOUNT_URL:AccountId.dkr.ecr.ap-northeast-1.amazonaws.com
  • AWS_RESOURCE_RAILS:rails_hello
  • AWS_DEFAULT_REGION:ap-northeast-1
  • RAILS_MASTER_KEY:<Rails マスターキー>

これで準備は完了です。

それとアセットプリコンパイルをする必要があるので、Dockerfileの最後に追記しましょう。

rails_hello/containers/app/Dockerfile

FROM ruby:2.7.1-alpine3.12

ENV TZ=Asia/Tokyo \
  RAILS_ENV=production \
  RAILS_SERVE_STATIC_FILES=false

ARG RAILS_MASTER_KEY
ENV RAILS_MASTER_KEY ${RAILS_MASTER_KEY}

RUN apk add --no-cache build-base libxml2-dev libxslt-dev \
  tzdata ca-certificates mysql-dev mysql-client \
  imagemagick imagemagick-dev imagemagick-c++ nodejs yarn && \
  gem install bundler

WORKDIR /rails_hello

RUN mkdir -p tmp/sockets

ADD Gemfile /rails_hello/Gemfile
ADD Gemfile.lock /rails_hello/Gemfile.lock
# RUN bundle config set deployment 'true' && \
RUN bundle config set without 'test development' && \
  bundle install

ADD . /rails_hello

RUN bundle exec rails assets:precompile # 追記

それでは早速、コードを変更後プッシュして変更が適用されるか確認しましょう。

index.html.erb

<h1>rails_hello</h1>
<p>update index.html<p> <!--変更-->

プッシュされるとまずは test が走ります。

成功すると、aws-ecr/build-and-push-image が走ります。

成功すると、aws-ecs/deploy-service-update が走ります。

これも成功すると、新しくタスクが実行されていると思います。

それでは、ドメインにアクセスして更新されているか見てみましょう。

おわり

これで、CircleCIによるCI/CDは完了しました。お疲れさまでした!

インフラの自動化もできたことで、だいたいのインフラリソースはコード化をできるようになりました。

どんどんコード化してインフラ管理ライフ良くしていきましょう!

今後、go + next.js を実装してみようと思います。

コメント

タイトルとURLをコピーしました