[Rails] ActiveStorage + Amazon S3のセットアップ手順をざっくり説明!
はじめに
こんばんは、バックエンドエンジニア見習い1年目のkuraoです!
今回は備忘録的に、ActiveStorage + Amazon S3のセットアップ手順をdocker-composeでのRailsアプリケーション構築から、簡単に説明して行きたいと思います!
前提
- Railsアプリケーションの構築にdocker-composeを使用
- 環境
ruby 2.7.0
rails 6.1.3
gem 'aws-sdk-s3'
- 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
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の中身を記述します。
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ファイルの中身を記述します。
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の中身を記述します。
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
ファイルを修正します。
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 build
→docker-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
コマンドを実行します。
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]
それぞれを設定します。これがない場合ホストが見つからないというエラーが出ると思われ。
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_id
やsecret_access_key
などの環境変数設定を記述していきます。
-
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に以下を追記します。
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
コマンドで、web
のDocker 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を抜けます。
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
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) ===============
kurao様、
なぜか、localhost:3001を打ち込んだら、Yay You're on Rails!が表示されました。
”コンテナ内部において、アプリはそれまでと変わらないポート 3000 で稼動していますが、ローカルホスト上から Rails ようこそページにアクセスするのは http://localhost:3001 となります。”との記載もありましたが、意味がまだよくわかっておりません。引き続き勉強してみたいと思います。
コメントありがとうございます🙇♂️
返信の方遅れてしまい申し訳ありません!
そちらですが、
docker-compose.yml
内において、ポートを3001に指定しているためローカルサーバーへアクセスする場合にはlocalhost:3001でのアクセスになります。ちなみにこちらは、
docker-compose up
の際に-d
オプションを付けず実行して、ログを見ていただけたら、localhost:3001でサーバーを立てていることが確認できるかと思います。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の表示は添付画像の遠入でした。
こんにちは。
今日、再度、ゼロからトライしてみたところ、無事、Yay You're on Rails!まで到達することができました。
なぜ、前回は失敗してしまったのか、わからない状況です。
FileNotFoundError: [Errno 2] No such file or directory は、私のパソコンではちょくちょく発生するエラーなので、何度もググって調査しているのですが、どうも、これだという原因がわからない状況です。
今後、一層注意して取り組んでまいります。
kurao様で前回の投稿と本投稿を削除できるならば、削除頂いても大丈夫でございます。
誠に申し訳ございませんでした。