👴

[Rails] ActiveStorage + Amazon S3のセットアップ手順をざっくり説明!

2021/04/11に公開5

はじめに

こんばんは、バックエンドエンジニア見習い1年目のkuraoです!

今回は備忘録的に、ActiveStorage + Amazon S3のセットアップ手順をdocker-composeでのRailsアプリケーション構築から、簡単に説明して行きたいと思います!

前提

  • Railsアプリケーションの構築にdocker-composeを使用
  • 環境
ruby 2.7.0

rails 6.1.3

gem 'aws-sdk-s3'
  • Dockerfile
Dockerfile
FROM ruby:2.7.0
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
        && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
        && apt-get update -qq \
        && apt-get install -y build-essential libpq-dev nodejs yarn          

RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock

RUN gem install bundler
RUN bundle install
ADD . /app
EXPOSE 3001
CMD ["rails", "server", "-b", "0.0.0.0"]
  • docker-compose.yml
docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
    - "3306:3306"

  web:
    build: .
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3001 -b '0.0.0.0'"
    tty: true
    stdin_open: true
    depends_on:
      - db
    ports:
      - "3001:3001"
    volumes:
      - .:/myapp

Railsアプリケーションの雛形を生成

  • まずはRailsアプリ用のディレクトリを作成します。
ターミナル
mkdir myapp
cd myapp
  • 次にmyapp内にDockerfile、docker-compose.yml、Gemfile、Gemfile.lockの各ファイルを作成します
ターミナル
touch {Dockerfile,docker-compose.yml,Gemfile,Gemfile.lock}

ls
# -> Dockerfile docker-compose.yml Gemfile Gemfile.lock
  • 次にDockerfileの中身を記述します。
Dockerfile
FROM ruby:2.7.0

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
        && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
        && apt-get update -qq \
        && apt-get install -y build-essential libpq-dev nodejs yarn          

RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock

RUN gem install bundler
RUN bundle install
ADD . /app
EXPOSE 3001
CMD ["rails", "server", "-b", "0.0.0.0"]
  • 次にdocker-compose.ymlファイルの中身を記述します。
docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
    - "3306:3306"

  web:
    build: .
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3001 -b '0.0.0.0'"
    tty: true
    stdin_open: true
    depends_on:
      - db
    ports:
      - "3001:3001"
    volumes:
      - .:/app
  • 次にGemfileの中身を記述します。
Gemfile
source 'https://rubygems.org'

gem 'rails', '~> 6.1.3'
  • 以上の記述が出来ましたら、docker-compsoe runコマンドを使ってRailsアプリケーションを生成します。
  • 今回はAPIモードでアプリケーションを構築します。
ターミナル
docker-compose run web rails new . --force --database=mysql --skip-bundle --api --webpacker
  • 新たに生成されたdatabase.ymlファイルを修正します。
database.yml
default: &default
    adapter: mysql2
    encoding: utf8
    pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
    username: root
    password: password  # docker-compose.ymlの MYSQL_ROOT_PASSWORD
    host: db    # docker-compose.ymlの service名
  • 以上で設定自体は完了したので、docker-compose buildコマンドでDockerコンテナを実行します。これでRailsの諸々のパッケージもインストールされます。
ターミナル
docker-compose build
  • buildが完了したら、docker-compose upコマンドでコンテナを起動します。
  • -dオプションを付与してデタッチトモードで起動します。(任意なのでなくても大丈夫です)
ターミナル
docker-compose up -d
  • docker-compose builddocker-compose upと来ましたら、RailsのDBの生成と起動を行います。
  • コンテナ外からrailsコマンドを実行する際は、docker-compose run web railsコマンドを使用します。
ターミナル
docker-compose run web rails db:create
docker-compose run web rails db:migrate
  • 起動しているコンテナを停止する場合はdocker-compose downコマンドを使って停止させます。
ターミナル
docker-compose down

ActiveStorageの設定

Gemfileの追加

  • Gemfileにaws-sdk-s3 gemを追加してdocker-compose buildコマンドを実行します。
Gemfile
gem 'aws-sdk-s3'

ストレージ先の設定

  • config/environment/development.rbファイルを開いて、以下の記述を行います。
  • config.active_storage.service:amazonを指定することで、ファイルを保存するためのストレージ先をS3に向けることができます。
    • ActiveStorageではここに設定してあるストレージ先をkeyとしてデータをfetchしています。この設定がないとActiveStorageはS3からデータをfetchしてくれないので注意です。
  • default_url_options[:host]default_url_options[:port]それぞれを設定します。これがない場合ホストが見つからないというエラーが出ると思われ。
config/environment/development.rb
Rails.application.configure do
  # ...
	
  config.active_storage.service = :amazon

  # ...

  Rails.application.routes.default_url_options[:host] = 'localhost'
  Rails.application.routes.default_url_options[:port] = 3001  # puma.rbで設定しているポート番号を指定します。
end

Active Storage関連のテーブルを生成

Active Storageはファイルデータを管理するのに、active_storage_blobsと、active_storage_attachmentsという2つのテーブルを使用します。

  • 上記2つのテーブルを作成するには以下のrails active_storage:installというコマンドを実行します。
ターミナル
docker-compose run web rails active_storage:install

# Copied migration 20210407015521_create_active_storage_tables.active_storage.rb from active_storage
  • 次に上記2つのテーブルのmigrationファイルを作成するために、rails db:migrateを実行します
ターミナル
docker-compose run web rails db:migrate

== 20210404053506 CreateTodos: migrating ======================================
-- create_table(:todos)
   -> 0.0078s
== 20210404053506 CreateTodos: migrated (0.0085s) =============================

== 20210407015521 CreateActiveStorageTables: migrating ========================
-- create_table(:active_storage_blobs, {})
   -> 0.0099s
-- create_table(:active_storage_attachments, {})
   -> 0.0119s
-- create_table(:active_storage_variant_records, {})
   -> 0.0168s
== 20210407015521 CreateActiveStorageTables: migrated (0.0388s) ===============

Amazon S3の設定

Amazon S3をファイルデータのストレージ先として設定するには以下の手順が必要になります。

  • 全権限を所有するIAMユーザーでAWSマネジメントコンソールへのログイン
  • S3管理用のIAMユーザーを作成
  • S3管理用のIAMユーザーでS3バケットを作成
  • S3管理用のIAMユーザーの「access_key_id」「secret_access_key」と、S3の「バケット名」「バケットのリージョン」を用いて、ActiveStorageのストレージをAmazonS3に設定

ので、これら設定を行っていきます。

それからS3用のIAMユーザーを作成する上での前提ですが以下の2つが前提となります。

  • AWSアカウントを既に所有していること
  • 全ての権限を持つIAMユーザーを既に作成していること

※ IAMユーザーでなくとも、ルートユーザーでも出来ます。

ではやっていきましょ。

全権限を所有するIAMユーザーでAWSマネジメントコンソールへログイン

  • IAMユーザーのサインイン画面からログインしてください。

S3管理用のIAMユーザーを作成

  • マネジメントコンソールの検索バーからIAMと打ち込むと「サービス欄」にIAMが出て来るのでクリックします。



  • サイドバーのユーザーを選択して、ユーザーを追加をクリックします。



  • 次にユーザー詳細の設定, AWSアクセスの種類を選択を設定する画面が開くので、必要事項を埋めていきます。

    • ユーザー名:S3管理用のユーザーなので、それっぽいわかりやすい名前でいいかと思います。このユーザー名はログイン時に使用します
    • アクセスの種類:使用するのは主にコンソールですが、プログラムによるアクセス, AWSマネジメントコンソールへのアクセス両方にチェックを入れておきます。
    • コンソールのパスワードカスタムパスワードにチェックを入れ、自身の好きなパスワードを入力してください。このパスワードはログイン時に使用します
    • パスワードのリセットの必要:こちらはチェックを外しておきます。
    • 以上が入力出来たら、次のステップ:アクセス権限をクリックします。

  • 次にアクセス許可の設定を行います。

    • まずユーザーをグループに追加を選択します。
    • 次にグループの作成をクリックします。


  • するとグループの作成というモーダルが開くので、各必要事項を入力していきます。

    • グループ名:S3の権限を持つグループであることがわかるような名前にしておくのがいいかなと思います。例えば、「group-S3」など
    • ポリシー:検索欄から「AmazonS3」と入力するとAmazonS3FullAccessというポリシーが出てくるので、これにチェックを入れます。
    • 上記の入力が終わったらグループを作成をクリックして次へいきます。


  • タグの設定はそのままで、次のステップで大丈夫です

  • 確認画面が開くでのその内容で良ければユーザーを作成をクリックします。


  • すると、S3管理用のIAMユーザーが正常に作成されます。ここではアクセスキーIDシークレットアクセスキーが表示されます。この2つはRailsの設定に使用するので、メモをしておいてください。


S3管理用のIAMユーザーでS3バケットを作成

  • 現在は全権限を持ったIAMユーザーでログインしていると思うので、こちら一旦ログアウトして、上記で作成したIAMユーザーでログインし直してください
  • ユーザー名とパスワードは上記で作成したIAMユーザーのものを使用します。


  • ログインが出来たらマネジメントコンソールからS3を選択します。


  • サイドバーのバケットを選択して、バケット作成画面からバケットを作成をクリックします。


  • バケットを作成画面が開くので、必要事項を記入します。

    • バケット名:任意のバケット名を記述してください。こちらは後でActiveStorageの設定に使用します
    • AWSリージョン:「アジアパシフィック(東京)ap-northeast-1」を選択。こちらも後でActiveStorageの設定に使用します
    • それ以外は何も弄らずにバケットを作成をクリックします。


AWSで行う設定は以上です!

次にRailsのActiveStorageのストレージをS3へ向ける設定を行います!

ActiveStorageのストレージをAmazon S3へ向ける設定

  • config/storage.ymlファイルで、Amazon S3を利用するということを宣言します。
  • amazon部分がコメントアウトされていると思うので、そちらコメントアウトを外して、以下のように記述します。
    • Rails.application.credentials.digという部分では、credentials.yml.encファイルの環境変数を参照します。
      なので、後でcredentials.yml.encファイルにaccess_key_idsecret_access_keyなどの環境変数設定を記述していきます。
config/storage.yml
amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: <%= Rails.application.credentials.dig(:aws, :s3, :region) %>
  bucket: <%= Rails.application.credentials.dig(:aws, :s3, :bucket) %>


  • credentials.yml.encを編集するにはvimを使用するので、Dockerコンテナ内にvimをインストールします。
  • Dockerfileに以下を追記します。
Dockerfile
FROM ruby:2.7.0

RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
        && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
        && apt-get update -qq \
        && apt-get install -y build-essential libpq-dev nodejs yarn          

# 追加 ==================
RUN apt-get update
RUN apt-get install vim
# ======================

RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock

RUN gem install bundler
RUN bundle install
ADD . /app
EXPOSE 3001
CMD ["rails", "server", "-b", "0.0.0.0"]


  • docker-compose buildコマンドで変更を反映させます。
ターミナル
docker-compose build


  • credentials.yml.encを開いて、必要な環境変数を記述します。
  • credentials.yml.encファイルを開くには以下の手順を行います。
    • docker psコマンドで、webDocker container idをコピー。
    • docker execコマンドに加えて、上記でコピーしたDocker containerのidを使用してDocker container内に潜入。
    • EDITOR="vi" bin/rails credentials:editコマンドで、credentials.yml.encファイルを開く。
ターミナル
docker ps

docker exec -it <Docker container id> /bin/bash

EDITOR="vi" bin/rails credentials:edit


  • vimでcredentials.yml.encを開いたら、キーボード「i」を押して編集モードにします。
  • 次に、以下のように環境変数記述します。
  • 間違いなく記述出来たら、キーボードの「esc」キーを押してから、「:wq」を入力後、「Enter」でvimを抜けます。
credentials.yml.enc
aws:
	access_key_id: <S3管理用のユーザー作成時に生成されたアクセスキーID>
	secret_access_key: <S3管理用のユーザー作成時に生成されたシークレットアクセスキー>
	s3:
		region: <S3バケット作成時に選択肢たリージョン>
		bucket: <S3のバケット名>
  • 上記の設定により、config/environment/development.rbファイルに記述した、config.active_storage.service = :amazonの記述が有効になります。


以上で、ActiveStorageのストレージがAmazon S3に向けられました!

最後に

今回は、ActiveStorageの設定から、ストレージをAmazon S3バケットへ向けるところまでというありふれた記事を備忘録的に書き連ねてきました!
次回は、実際にActiveStorageを使用したファイルの保存や参照や、ActiveStorage + FFMpegを使用して、動画を加工する方法などに触れた記事について書こうと思っています。
(というか本記事はそのための前準備みたいなものです)

ちなみにFFMpegとは何ぞやというのを超簡単に説明しておきますと、画像ファイルや動画ファイルなどの加工をしてくれるOSSフレームワークのことです。

FFMpegで出来ることとしては、あまりに多すぎて全て紹介するのは難しいですが、いくつか挙げるとすると「画像・動画ファイルの変換」「動画のスクショを撮る(任意の秒数のスクショ可)」などの他に「動画の上に動画を埋め込む」などができ、結構何でも出来るっぽいです(加工の全てを試したわけではないのです。。。)
それら詳しい説明もその記事で書くつもりです!

ではまた!

Discussion

PaoPao

kurao様、
すばらしい投稿、誠にありがとうございます!
kurao様の投稿無くして、DockerでActiveStorageとS3は自力では絶対に構築できなかったと思います。
”credentials.yml.enc”ファイルに、必要事項をvimで記入後、各コマンドでエラーが無かった為、
localhost:3000をブラウザで打ってみたのですが、Yay You're on Rails!を表示させる
ことができませんでした。
原因がわからなかったので、下記の順番で立ち上げなおしてみたのですが、
やはりサーバーにつながりませんでした。
すみません、もし宜しければ、打開策があるようでしたら、ご教示頂くことできますか?

docker-compose down
docker system prune -a
docker-compose build
docker-comopose up -d
docker-compose run web rails db:create
docker-compose run web rails db:migrate

----下記がrails db:migrate後のターミナル表示結果です----------------------------

$ docker-compose run web rails db:migrate
Creating docker_aws_web_run ... done
== 20210806095329 CreateActiveStorageTables: migrating ======================
-- create_table(:active_storage_blobs, {})
-> 0.0324s
-- create_table(:active_storage_attachments, {})
-> 0.0357s
-- create_table(:active_storage_variant_records, {})
-> 0.0277s
== 20210806095329 CreateActiveStorageTables: migrated (0.0964s) ===============

PaoPao

kurao様、
なぜか、localhost:3001を打ち込んだら、Yay You're on Rails!が表示されました。

https://docs.docker.jp/compose/rails.html

”コンテナ内部において、アプリはそれまでと変わらないポート 3000 で稼動していますが、ローカルホスト上から Rails ようこそページにアクセスするのは http://localhost:3001 となります。”との記載もありましたが、意味がまだよくわかっておりません。引き続き勉強してみたいと思います。

kuraokurao

コメントありがとうございます🙇‍♂️
返信の方遅れてしまい申し訳ありません!
そちらですが、docker-compose.yml内において、ポートを3001に指定しているためローカルサーバーへアクセスする場合にはlocalhost:3001でのアクセスになります。
ちなみにこちらは、docker-compose upの際に-dオプションを付けず実行して、ログを見ていただけたら、localhost:3001でサーバーを立てていることが確認できるかと思います。

PaoPao

kurao 様、
お返事誠にありがとうございます!
docker-compose.yml内で指定していたのですね、私も勉強不足でした。申し訳ありませんでした。

すみません、Dockerfileなどを置くディレクトリ名を、docker_AWS_s3として、新規に作り直し、
docker-compose run web rails new . --force --database=mysql --skip-bundle --api --webpacker
の後、database.ymlを修正し、docker-compose buildを実行したのですが、下記のようなエラーが
でてしまいました。
このエラーがでてしまうと、docker-compose downを実行しても、同じエラーが出続けてしまいます。
申し訳ございません、打開策のようなものがございましたら、ヒントでもかまいませんので、
ご教示いただけますと大変ありがたく存じます。

$ docker-compose build
Traceback (most recent call last):
File "docker-compose", line 3, in <module>
File "compose/cli/main.py", line 81, in main
File "compose/cli/main.py", line 200, in perform_command
File "compose/cli/command.py", line 70, in project_from_options
File "compose/cli/command.py", line 146, in get_project
File "compose/cli/command.py", line 206, in get_project_name
File "posixpath.py", line 383, in abspath
FileNotFoundError: [Errno 2] No such file or directory
[3823] Failed to execute script docker-compose

docker psを確認したところ、dbのSTATUSは、Upでした。

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
6850563ef27d mysql:5.7 "docker-entrypoint.s…" 10 minutes ago Up 10 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp docker_aws_s3_db_1

Docker desktopの表示は添付画像の遠入でした。

PaoPao

こんにちは。
今日、再度、ゼロからトライしてみたところ、無事、Yay You're on Rails!まで到達することができました。
なぜ、前回は失敗してしまったのか、わからない状況です。
FileNotFoundError: [Errno 2] No such file or directory は、私のパソコンではちょくちょく発生するエラーなので、何度もググって調査しているのですが、どうも、これだという原因がわからない状況です。
今後、一層注意して取り組んでまいります。
kurao様で前回の投稿と本投稿を削除できるならば、削除頂いても大丈夫でございます。
誠に申し訳ございませんでした。