scpで.ssh/configに登録しているhostを使う EC2ファイル編
EC2の内のバックアップファイルとかをローカルのコピーしたかったので調べてみました。
ローカルの~/.ssh/config内である一つのEC2インスタンスに接続するための設定があったとします。↓
~/.ssh/config Host sample_key_rsa Hostname xx.xxx.xx.xx Port 22 User hoge IdentityFile ~/.ssh/sample_key_rsa
ssh接続時のコマンド↓
$ ssh sample_key_rsa
scpコマンドでEC2内のファイルをコピーする。
$ scp ホスト名:EC2内のパス ローカルのパス
使うときはこんな感じ↓
$ scp sample_key_rsa:~/test.txt ~/desktop
ローカルのファイルをEC2内のディレクトリにコピーする。
$ scp ローカルのパス ホスト名:EC2内のパス
使うときはこんな感じ↓
$ scp ~/desktop sample_key_rsa:~/test.txt
Rails+PostgreSQL+Docker+AWSで作成したポートフォリオの概要
記事の概要
この記事では、私が作成したポートフォリオの解説をします。
コンテンツ投稿、管理、その他の営業に利用できるサービス機能をつけた、お店の個人ホームページです。
管理者のみ、コンテンツのCRUD機能やその他の機能が使える仕様にしています。
一般閲覧者は、コンテンツの閲覧のみです。
ポートフォリオ本体です。実際に運用しているため、こちらのソース公開や機能を利用することは開発者しかできません。↓
公開用のコピーアプリがこちら。投稿機能が体験できます。ソースも公開しております。↓↓
https://github.com/Ryo10Leo/post_sample_app
自己紹介
岩田 凌(いわたりょう) 1994/05/07生
2019年4月からIT関連の勉強をはじめ、2019年10月から本格的にプログラミングの学習を開始。
取得資格
基本情報技術者試験合格/ Javaプログラミング能力検定二級/ Java SE Programer Ⅰ/ 三級Webデザイン技能士/ 日商簿記検定二級/ 英検二級
学習言語、インフラ関連
Ruby, Ruby on Rails, HTML, CSS, Javascript, AWS, Docker
背景
私の実家で母が美容室を経営しており、独立20周年を迎えようとしています。
それを迎えるに当たって、私はプログラミング初心者ながら今学習していることで「実用的な貢献」ができないかと思っていました。
ヒアリングにより以下のような要望がありました。
- 20周年を迎えるにあたり、改めて自身の美容室の活動やサービスを様々な方に知っていただきたい。
- 美容の専門的な知識を使って、お客様のお役に立つような美容関連の商品を紹介したい。
- 自身のスタイリング写真を見ていただきたい、かつアルバム(資産?)として残したい。
以上のことを踏まえ、美容室の公式ホームページがまだないことから、
コンテンツ投稿、管理機能、その他営業に利用できる機能を備えた公式HPを作成することとなりました。
また、Web系の開発企業のエンジニアになろうと考えていたので、このアプリケーションを転職活動用のポートフォリオとすることにしました。
今回は、作業の一部(写真関係)を駆け出しのエンジニア初学者仲間、SNSで写真活動を行っている方、一般のモデルなどに協力をお願いしています。(協力者の紹介は後述)
皆と連携することで本格的なHPを作成する一つのプロジェクトとして活動しました。
目的
スペック
言語
Ruby 2.6.3
データベース
PostgreSQL 9.2.24
Webサーバ
Nginx 1.16.1
フレームワーク
Ruby on Rails 5.1.6
開発環境
Docker 19.03.5
docker-compose 1.25.2
バージョン管理
Git 2.21.0
本番環境
AWS(VPC, EC2, ALB, Elastic IP, Route53, Cloud Front, S3)
機能一覧 (一部抜粋)
- ログイン機能(Remember me機能付)
ログインすることで「ブログ」,「スタイル」,「商品」の各ページで投稿、編集、削除機能が利用できます。
- 写真などコンテンツ投稿機能(Ajax通信, 画像アップロード先 S3)
ログインすることでコンテンツの投稿ができます。
- 投稿編集機能(Ajax通信)
既存の投稿コンテンツのキャプションなどが編集できます。
- 投稿削除機能
コンテンツの削除。
- 記事投稿機能(Ajax通信, Ckeditor, 画像アップロード先 S3)
記事には、「タイトル」「内容(画像付)」「カテゴリ」が追加できます。「日付」は投稿時間から動的にフォーマットが変換され表示されます。
投稿順に表示されます。
サイドバーに最新記事5件のタイトルを動的表示(個別記事閲覧可)。
本体ポートフォリオの HOMEページでは、最新三件の記事を動的表示。
解説記事↓
ryo10leo.hatenablog.com
- 記事カテゴリー付機能(UI Tag it)
記事にはカテゴリーが追加できます。
カテゴリ別の閲覧が可能です。
サイドバーには記事で使われているカテゴリだけを表示。
使われていないカテゴリーは記事更新時にデータベースか自動削除されます。
管理者のスマホのカレンダーアプリに休日や予約などを追加することで、自動でホームページの営業カレンダーに追加した予定が同期します。
- ページネーション機能(Will_Pagenate)
コンテンツのページネーション機能です。
開発手順
1.要件定義
作成する主な機能
- 管理者ログイン機能
- コンテンツ(記事, スタイル, 商品 )CRUD機能
- コンテンツ一覧表示機能
- 営業スケジュールカレンダー更新機能
必要となるもの
- 「ユーザー (今回は一件のみ)」「記事」「スタイル」「商品」の情報を保存するためのデータベース
- データベースの内容を表示する「動的なビュー」
- 「投稿」「編集」「削除」画面
- 動的な営業カレンダーを表示するための、「ライブラリ」と「 API」
2.環境選定
アプリケーション
言語は学習中の「Ruby」とし、フレームワークは「Ruby on Rails」としました。
フロントエンドはこだわりが強かったので、Bootstrapは使っていません。
検索した美容室さんのサイトやCSSデザインの記事などを参考に、HTMLとCSSをほば手書きで作成しました。
アプリの動きは「JavaScript」で動作させ、「jQuery」などのライブラリも使っています。
開発環境
最初の方はローカル環境で開発していたのですが、途中で「docker」と「docker-compose」の仮想環境に切り替えました。
何やら現場ではよく使われていて、開発効率を上げるものだと教わったので勉強だと思って導入しました。
今後デプロイ時にコンテナを起動する構成にしていくつもりです。
インフラ
本番環境では「AWS」。EC2やRoute53などを使います。
Webサーバーには資料の多い「Nginx」を使用します。結果的にRailsの「Puma」との連携が容易にできたため。
データベースは「PostgreSQL」を選択。(MySQLを使ったことがないので...)
3. データベース設計
使用ソフト cocoo
基本情報技術者を勉強していたおかげで、データベースやSQLの基礎知識は多少ありました。
そのためアプリの機能でどんな情報を保存するか、どんな関連付けを行うと良いかを構想するのはそこまで難しくなかったです。
あとはアプリ作成時のフレームワークでどのようなコードを書いたり、コマンドを打てば、
設計通りに構築できるのか、ビューで取得したいデータを抽出できるのか。
それらを意識することで学びながら構築はできました。
4.ワイヤーフレーム(プロトタイプ)の作成
デザインのイメージがありましたが、いきなりコーディングすると作業効率が悪いと思ったので、「cacoo」というブラウザツールを使うことで「ワイヤーフレーム」を作成し、フロントエンドの作業も円滑に行えるようにしました。
これを行って最もよかった点としては、
「プロトタイプ」があることで、クライアントからデザインの感想をいただき、要望や変更を円滑に反映することができたことです。
5.コーディング
Git管理
コードは「Git」で管理し、こまめに「GitHub」にプッシュしてバージョン管理を行いました。
Gitの扱いに慣れてきたら機能ごとにブランチを切って作業し、Masterブランチにマージするなど、実践を意識したコーディング練習も行いました。
フロントエンド
序盤はワイヤーフレームの内容に沿って、「HTML」「CSS」を利用したコーディングを行いました。
静的なページができたら 「JavaScript」で動きをつけ、視覚的に楽しめるように意識しました。
バックエンドは並行して行っていなかったので、バックエンドの作業に入る際は少し冗長的なコードが多かったと思います。(データベースから抽出やRailsのヘルパーが使えないので仕方ないことなのですが、、、)
バックエンド
Railsプロジェクトを立ち上げ、フロントエンドの作業で完成したビュー(.html)を一つずつ動的なページ(html.erb)に変更していきました。
今回のポートフォリオの主な動的ページは「News」「Style」「Product」「Login」です。
大まかな作業手順としては、
- 「データベース作成(バリデーション付与)」
- 「コントローラーの作成」
- 「ルーティング設定」
- 「Gem」や「ヘルパーメソッド」を適宜追加。
- 「冗長的なビューのコードの削除」です。
取り掛かった順番ですが、
- 「Style」「Product」は画像と文字列のデータを動的表示するだけで、さほど難しくないので序盤に、、、
- 「News」は記事内容に「リッチテキストエディタ」を導入しており、「カテゴリー機能」など複雑なデータベース関連の処理を用いるため中盤に、、、
- 「Login」では「セッション」や「クッキー」などの概念を理解することが難しく、実装に慎重になる必要があったため終盤
となりました。
※ページ作成順 レベル低「Style」→「Product」→「News」→「Login」高
ここまででログインした管理者のみがコンテンツを投稿できるシステムが完成しました。
営業カレンダー
「Google API」と「Full Calendar」の同期後、
各種カレンダーの見た目や動的な表示の設定などは、Javascript,CSSに書き込んで編集。
6.デプロイ
本番環境にはAWSを用いており、全体の構成図は以下の通りです。↓
「EC2インスタンス」を立ち上げ、「Elastic IP」でグローバルIPを固定。
お名前.comでドメインを購入し、「Route53」独自ドメインの設定。
インターネットからの通信は、管理者が投稿送信の際に情報が盗聴、改ざんされないように「ALB」を噛ませることで、HTTPS通信で暗号しています。
画像コンテンツの保存には「S3」を使用して、「Cloud Front」で配信を高速化しています。
EC2内で構成した環境は以下の通りです↓
構成はWeb3層構成です。
Webサーバー層には、「Nginx」
Webブラウザからのアクセス要求を処理する層を示します。必要に応じて、Webアプリケーション層へリクエストを要求します
アプリケーションサーバー層には、「Puma」「Rails」
Webサーバから受けたリクエストをもとに、バックエンドで動作するRubyなどを実行したり、データベースへのアクセスを行ない、処理を行ないます。
データベース層には、「PostgreSQL」
入力したデータや、アプリケーションで参照するデータを保管する役割を持ちます。
今回のデプロイではWeb3層構成を構築する際、EC2にSSHでログインし、必要なソフトウェアをインストールして適宜設定をした流れです。
ryo10leo.hatenablog.com
今後の改善点、追加実装について
フロントエンド
- トップページにアクセスしたときに、おしゃれなローディング画面を作りたいと思います。
- 投稿の送信時間がかかるとき「送信中」だとわかるloading.gifをつけたいです。
投稿コンテンツが増えたときの対策
- 「管理画面」を作ってコンテンツの検索をできるようにして、CRUD機能がより簡単にできるようにする。
構築したインフラ環境の改善
- 一つのEC2インスタンス内にWeb3層構成を構築したので、ベストプラクティスではないと思います。「RDS」を追加してデータベースを切り離すか、または「docker」と「docker-compose」を使ってコンテナで運用するのか、様々なデプロイ方法を検討して取り入れたいと思います。
インフラの障害の対策
データベースのバックアップを定期的にできる仕組みを勉強し、コンテンツデータの紛失を防ぐ。
「追記」 データベースのバックアップを定期的に行う仕組みを作成してみました。↓
EC2で構築したPostgreSQLデータベースを定期的にバックアップ。ローカルにもバックアップファイルをコピーする - りょ〜Blog
ポートフォリオ作成の協力者様をご紹介
今回はホームページ作成ということで、そこに掲載する「写真」も重要なテーマになっております。
そこで写真撮影や編集に関わっていただいた方達をご紹介します。
『写真撮影』 奥出航介(おくでこうすけ)様
独特なセンスが自分の中のポートフォリオのイメージとマッチしているため、今回ご依頼させていただきました。
彼はSNSを中心に写真活動を行っております。
コンセプトは「日常の中で揺れ動いた瞬間」
現在のTwitterフォロワー数は3000人近く。
Twitterアカウント↓
おくで (@photo_okina) | Twitter
『写真編集』 阿部翔次郎(あべしょうじろう)様
私と同じ駆け出しエンジニア仲間です。デザインやフロントエンドを中心に勉強されています。
Photoshopの技術を習得されていたため、今回写真の編集に携わっていただきました。
主な編集は「ぼかし加工」「背景の入れ替え」などです。
ご依頼からの「イメージ共有」「納品」が早く、大変助かりました。
阿部様のポートフォリオサイト↓
For employment 阿部翔次郎
ご紹介したお二人とその他協力していただけたモデルの方々のおかげもあり、当初イメージしていた通りのものが出来上がりました。
大変ありがとうございました!
ポートフォリオに関する実装技術の解説記事(一部抜粋)
多すぎるHTML文... renderメソッドですっきり表示して管理しやすくする。 - りょ〜Blog
htmlタグを削除や表示文字数制限してHPのTOPニュースなどで記事内容の概要を表示する - りょ〜Blog
記事の最初のimgタグを取得してサムネイル画像に使う - りょ〜Blog
created_atのフォーマットを変更して記事の日付に使う - りょ〜Blog
HTML,CSS 美容室HPでよく見かけるメニュー表作成 - りょ〜Blog
rails 基本的なログインシステム Part1 - りょ〜Blog
carrierwaveで画像投稿できるようにする - りょ〜Blog
自作railsアプリをデプロイする Part1 VPC作成編 - りょ〜Blog
その他の解説は追って書いていきます。
参考文献
1冊ですべて身につくHTML & CSSとWebデザイン入門講座
プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで
改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで
プロになるためのWeb技術入門」 ――なぜ、あなたはWebシステムを開発できないのか
Docker + Rails + Puma + Nginx + Postgres - ITNEXT
(デプロイ編①)世界一丁寧なAWS解説。EC2を利用して、RailsアプリをAWSにあげるまで
【jQuery】アコーディオンメニュー 上下にスライドして開閉するメニュー | ティブる!
既存のRailsアプリのローカル開発環境をDockerの仮想環境に切り替える
最近までRailsのアプリの開発はローカル環境で行っていました。
Dockerを学び初めて使ってみたいなと思ったので、開発環境をDockerとdocker-composeで作ってみることにしました。
- 開発環境の完成図
- 前提
- ディレクトリ構成
- Railsアプリコンテナの設定
- Nginxコンテナの設定
- PostgreSQLコンテナの設定
- コンテナを管理するためのdocker-composeの設定
- docker-composeでイメージをビルド、コンテナ起動
- 最後にinitdb.sqlを追加した理由
開発環境の完成図
どういうやつを作ろうか迷ったんですが、、、
Railsアプリをデプロイする際に、AWSで以下のようなWeb3層構成を作りました。↓
Webサーバーには「nginx」、アプリケーションサーバーには「puma」「Rails」、データベースには「PostgreSQL」を使っています。
今回は、これと同じ構成にしようと思います。
ということで簡単な完成図はこんな感じ↓
「Webコンテナ」、「Appコンテナ」、「DBコンテナ」を立ち上げて、それをdocker-composeで管理していく構成で作成していきます。
前提
開発環境の切り替えということを踏まえ、前提は以下となります。
ディレクトリ構成
-my_app -app -db -config -database.yml -puma.rb ... -Docker -app -Dockerfile -web -Dockerfile -nginx.conf -db -Dockerfile -initdb.sql -docker-compose.yml -Gemfile -Gemfile.lock ...
Railsアプリはすでに作成済(ファイル名my_app)だったので、Railsアプリのプロジェクトファイル内に上記のような構成で、Dockerファイルとdocker-compose.yml を追加します。
Dockerファイル内は、それぞれのコンテナのDockerイメージを作成するためのDockerfileと必要な設定ファイル(*.confや*.sql)を追加します。
Railsアプリコンテナの設定
Dockerfile
Docker/app/Dockerfile #バージョンを指定してRubyイメージを取得 FROM ruby:2.6.3 #必要なライブラリを取得 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs ENV RAILS_ROOT /my_app Railsアプリのルートディレクトリ作成 RUN mkdir -p $RAILS_ROOT WORKDIR $RAILS_ROOT #ホストのGemfileとGemfile.lockをRailsコンテナにコピー COPY Gemfile Gemfile COPY Gemfile.lock Gemfile.lock #コピーされたGemfileを参照してbundle install RUN bundle install --jobs 20 --retry 5 --without production #ホストのアプリケーションディレクトリ内をすべてコンテナにコピー COPY . . RUN mkdir -p tmp/sockets
Nginxコンテナの設定
NginxとRailsは「 UNIXソケット通信」を使います。
Dockerfile
Docker/web/Dockerfile FROM nginx # インクルード用のディレクトリ内を削除 RUN rm -f /etc/nginx/conf.d/* # Nginxの設定ファイルをコンテナにコピー COPY /Docker/web/nginx.conf /etc/nginx/conf.d/my_app.conf # ビルド完了後にNginxを起動 CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
Nginx設定ファイル
Docker/web/nginx.conf # プロキシ先の指定 # Nginxが受け取ったリクエストをバックエンドのpumaに送信 upstream myapp { # ソケット通信したいのでpuma.sockを指定 server unix:///my_app/tmp/sockets/puma.sock; } server { listen 80; # ドメインもしくはIPを指定 server_name localhost; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # ドキュメントルートの指定 root /my_app/public; client_max_body_size 100m; error_page 404 /404.html; error_page 505 502 503 504 /500.html; try_files $uri/index.html $uri @my_app; keepalive_timeout 5; # リバースプロキシ関連の設定 location @my_app { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://myapp; } }
puma.rbの設定
confing/puma.rb threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i threads threads_count, threads_count port ENV.fetch("PORT") { 3000 } environment ENV.fetch("RAILS_ENV") { "development" } plugin :tmp_restart app_root = File.expand_path("../..", __FILE__) bind "unix://#{app_root}/tmp/sockets/puma.sock" stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true
PostgreSQLコンテナの設定
Dockerfile
#postgresqlのイメージ取得 FROM postgres #初期化で追加したい処理を書いたファイルを追加 COPY Docker/db/initdb.sql /docker-entrypoint-initdb.d/.
initdb.sqlの設定
Docker/db/initdb.sql ALTER ROLE postgres WITH PASSWORD 'password'; CREATE DATABASE sample_app;
initdb.sqlを必ず初期化で追加する必要なのかはわかりません。笑
なぜ追加したのかは後述。
database.ymlの設定
・ ・ development: <<: *default adapter: postgresql encoding: unicode pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> host: db database: sample_app username: postgres password: password ・ ・
コンテナを管理するためのdocker-composeの設定
version: '3' volumes: postgres_data: public_data: tmp_data: log_data: services: app: build: context: . dockerfile: ./Docker/app/Dockerfile command: bundle exec puma -C config/puma.rb volumes: - .:/my_app - public_data:/my_app/public - tmp_data:/my_app/tmp - log_data:/my_app/log depends_on: - db db: build: context: . dockerfile: ./Docker/db/Dockerfile environment: - POSTGRES_PASSWORD=password volumes: - postgres_data:/var/lib/postgresql/data web: build: context: . dockerfile: ./Docker/web/Dockerfile volumes: - public_data:/my_app/public - tmp_data:/my_app/tmp ports: - 80:80 depends_on: - app
volumesではappの場合、ホスト側のソースコードの変更を即時に反映させるために、ホストのファイルをマウントしています。
dbではデータを永続化するためのマウントです。
「depends_on」はコンテナの作成順序と依存関係を決めるものです。
webコンテナはappコンテナ、appコンテナはdbコンテナって感じです。
docker-composeでイメージをビルド、コンテナ起動
必要な物が揃ったのでコンテナを動かして見ます。
my_app $ docker-compose build
コンテナのイメージをビルドします。
my_app $ docker-compose up -d
コンテナをデタッチで起動
my_app $ docker-compose exec app bin/rails db:migrate
マイグレーションファイルをコンテナ内のRailsアプリに適用させる
これでブラウザでlocalhostに接続するとアプリが表示されました!
最後にinitdb.sqlを追加した理由
initdb.sqlにはCREATE文のみ追加していたんですが、
Docker/db/initdb.sql
CREATE DATABASE sample_app;
その状態でコンテナを起動させてrails db:migrateなどを行おうとすると以下のようなエラーが出ました。
PG::ConnectionBad: FATAL: password authentication failed for user "postgres"
どうやらデフォルトユーザのpostgreにパスワードを与えれば解決できるようだったので、
DBの初期化時にパスワードを与える処理を実行することでうまくRails側でDBを操作することができました。
Docker/db/initdb.sql ALTER ROLE postgres WITH PASSWORD 'password'; CREATE DATABASE sample_app;
こうすることでいちいちDBコンテナに入って設定しなくても、すぐにrailsアプリにマイグレーションファイルを反映させることができます。
ってだけのことでした。
Docker簡単なようで難しいな、、、
まだ始めたばっかだし、ゆっくり勉強してこう
dockerコマンドオプションの「-it」を理解する
dockerを学び始めてオプションのところでつまづきました。
dockerのrunコマンドを打つときに、よく「-it」オプションを入力しているのをよく見かけるので今回はこの意味を理解して行こうと思います。
オプションを分割して理解する
「 -i」とは
iは「interactive」の略で、これは簡単に説明すると「双方向のやりとりができるようになること」
「ホストのターミナルからの入力がコンテナの標準入力につなげる役割」なのだそう。
この動作を方向でイメージすると。
ホスト(ターミナルとか) → コンテナ
かな?
「-it」をふわりと理解する
まとめると、-iでターミナルからの入力をコンテナが受け付けて、-tでコンテナの標準出力をホストのターミナルでつなげることで、ホストターミナルからコンテナ内部の操作かができますよーってことでいいのかな?
え?違う?
本番環境でのrails db:migrate:reset
ローカルでDBをリセットするとき
$ rails db:migrate:reset $ rails db:seed
などの手順を行ってきた。
しかしAWSでデプロイするなどしたときに、本番環境ではやり方が違うらしいです。
今回はそれを調べて試していきます。
参考にさせていただいた記事↓
本番環境でのDBのリセットを実践
railsサーバーは停止させた方が良さそうです。
[ec2-user| ~]$ ps ax | grep rails [ec2-user| ~]$ kill -9 ~~~~
[ec2-user| ~]$ cd /var/www/rails/myapp [ec2-user| myapp]$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop
[ec2-user| myapp]$ rake db:create RAILS_ENV=production [ec2-user| myapp]$ rake db:migrate RAILS_ENV=production [ec2-user| myapp]$ rake db:seed RAILS_ENV=production
成功です!めんどいですね笑
自作railsアプリをデプロイする 番外編 サイトをHTTPS化して通信を暗号化する
上の記事を通して、以下のようなインフラを作成しました。↓
EC2の中身はこんな感じです。↓
今回はRailsアプリケーションをHTTPSで通信ができるようにして、セキュリティ面を向上させていきたいと思います。
HTTPS通信を軽く理解する
概要
HTTPS(Hypertext Transfer Protocol Secure)通信とは、ホームページなどの閲覧や、クライアントとサーバーと間でのデータをやりとりの際に「通信内容を暗号化して第三者からの盗聴や漏洩、改ざんを防止すること」です。
HTTPとは何が違うの?
HTTPは簡単にいうと、封がされていない手紙のような状態です。そのため誰でも閲覧することができ、改ざんも行えてしまう可能性があります。
HTTPと HTTPSの違いを図で理解する
HTTP通信だと通信の内容が筒抜けなのに対して、、、
HTTPS通信を使うことで「封がされた手紙のような状態」になり、内容を見られたり改ざんされる可能性が極めて低くなります。
AWSでの実現方法
HTTPS通信の実現方法としては以下の記事を参考にさせていただくと、いくつかパターンがあります。↓
このなかで以下の方法が一番手軽にできるパターンなようです。↓
簡単に説明すると、クライアントからHTTPS通信でWebサーバーのあるEC2インスタンスに通信しようとするとします。
そうすると、まずクライアントとALB(後述)間では「HTTPS通信」になります。
そして、ALBが「HTTP通信」に変換してからEC2インスタンスに通信内容を送るという動き(その逆も)です。
どうやら「ALB」というサービスを使えばHTTPS通信が実現できるようです。
これが手軽に実現できる理由としては、HTTPS通信に必要なリソースが全部 AWSで手に入れることができるからです。これは便利です。
今回はこちらのパターン使って実現して行こうと思います。
しかし実際にこの環境を作っていく前に、ある程度これから使うAWSサービスや用語などを理解してから作業に移っていきます。
ALBを軽く理解する
AWS Certificate Managerを軽く理解する
概要
AWS Certificate Manager(以下、ACM)とは、AWS上でSSLを利用することのできるサービスです。
普通だとSSLを利用するために、外部からSSL証明書を発行しようとすると手間やコストがかかります。
しかし AWSでは、ACMを利用することで無料で手軽にSSL証明書が発行できるため簡単に暗号化通信を実現することができます。
え?ということは、、、
「それならALB使わなくてEC2インスタンスのセキュリティグループをHTTPSにすればいいんじゃ...?」
しかしそうはいかないようです。↓
ELB,CloudFrontでのみ利用可
ACMの証明書の利用範囲は、ELB,CloudFrontでのみだそうです。
CloudFrontだと以下の記事でSSL証明書を利用しています。↓
ryo10leo.hatenablog.com
したがって、EC2インスタンスやオンプレミスサーバーに紐づけることもできません。
なるほど、、、もう一度、実現パターンの図を見ると、、、
この構成なのも納得しました!
作成するものを図で理解する
実現パターンの紹介のところで何度か図を見たのでだいたいわかっていますが、インフラを全体的に見てに作るもの想像しておきます。↓
ALBを設置してクライアントとの暗号化通信を担ってもらい、さらにHTTP通信に変換して、インスタンスに通信を送るのでした。
実際にHTTPS通信の設定をしてみる
前提
1. SSL証明書の発行手順は省略
SSL証明書の発行方法については、以前の「Cloud Front」の記事で取りあげたので今回は書略します。
SSL証明書については以下が参考になります。↓
blog.serverworks.co.jp
2.ドメイン取得済
今回はRoute53でドメインの設定も今回行っていきますが、ドメインも取得済でサイトとの紐付けも済んでいるので省略します。
こちらの記事のようにドメインは設定しました。↓
ryo10leo.hatenablog.com
3.VPC内にアベイラビリティーゾーンが異なるサブネットが2つ以上あること
ALBの設定で必須なので、1つしかない場合は作成しておきましょう。
ALBの設定
ダッシュボードから「ロードバランサー」→「ロードバランサーの作成」を選択。
ALBの方の「作成」を選択。
ALBの名前を入力。
リスナーは「HTTPS」にします。ポート番号は自動で切り替わります。
アベイラビリティーゾーンで2つ以上のサブネットを選択して、次へ
証明書タイプは「ACM から証明書を選択する (推奨)」にして、
証明書の名前で「ACMで発行した証明書」を選択します。
セキュリティグループは、「HTTPS」通信を許可します。
ターゲットグループの名前を入力して次へ。
ターゲットに作成したEC2インスタンスを登録します。
登録するインスタンスにチェックを入れて「登録済みに追加」
次の確認画面で問題なければ「作成」をクリック。
作成完了です。
自作railsアプリをデプロイする 番外編 Cloud Frontを使って画像を高速配信する
ryo10leo.hatenablog.com
ryo10leo.hatenablog.com
上の記事を通して、以下のようなインフラを作成しました。↓
EC2の中身はこんな感じです。↓
Railsアプリケーションから投稿した画像を「S3」のバケットに保存することができました。
今回は「Cloud Front」を使って、画像配信をより効率的にしていこうと思います。
Cloud Frontを軽く理解する
概要
Cloud Frontとは、高速にコンテンツを配信するサービス。(CDNサービス)
オリジンサーバー( 配信元のサーバー、ここでいうS3)上にあるコンテンツを世界100カ国以上あるエッジロケーションにコピーして、そこから配信する。
簡単にいうと、配信に関する遅延は少ない状態にすることができます。
特徴
・高速
ユーザー(クライアント)から最も近いエッジサーバーからコンテンツを配信するため速い。
・効率的
エッジサーバーで配信をするため、オリジンサーバーへの負荷をかけることなく配信できる。
導入事例
Amazon Prime Video、Huluなど
作成するものを図で理解する
全体から見た設置図はこんな感じ↓
動作としては以下のような仕組みで動いています。↓
Cloud Frontがキャッシュからコンテンツを配信することで「高速」になり、コンテンツをS3から取得しておくことでクライアントからのリクエストによる「S3の負荷を軽減」することができます。
CloudFrontを設定する
ディストリビューションの作成
コンソールから「 Cloud Front」を選択。
「Create Distribution」を選択。
Webの方で「Get Started」を選択。
ディストリビューションの各種設定をしていきます。
Origin Domain Name
S3で作成したキャッシュさせたいバケットを選択。
Origin Path
指定したディレクトリのみキャッシュさせたい場合は指定。
今回は空。
Origin ID
今回はこのまま
Cloud Frontのみにアクセスさせたい場合は「Yes」を選択。
Origin Custom Headers
今回は空
下の「Default Cache Behavior Settings」はいじりません。
さらに下の「Distribution Settings」は、
「Price Class」が「Use All Edge Locations(Best Performance)」であればOK。
設定が終わったら「Create Distribution」
作成完了です。
この時点でS3に保存されているコンテンツはCloudFrontから配信されるようになります。
しかし、Cloud Frontから配信を行う場合、画像のURLのドメインが「Cloud Frontのドメイン」になります。
上記の画像のように「~~~.cloudfront.net」がドメインになります。
今回は独自のドメインをCloud Frontに紐付けて配信ができるようにしていきます。
例えばドメインを「static.myapp.com」としたら、そのドメインで「~~~.cloudfront.net」に接続して画像を配信できます。
ドメイン設定のための準備
独自ドメインを紐付けるためには、「SSL証明書」を発行する必要があります。(ここでは詳しく書きません)
なのでSSL証明書をまずは発行していきます。
「CloudFront Distributions」の画面から、先ほど作成したディストリビューションの「ID」をクリック。
その先の画面で「Edit」を選択します。
移動した画面で「Request or Import a Certificate With ACM」を選択。
ドメインを追加していきます。↓
「*.myapp.com」「myapp.com」などのように、サブドメイン全てを許容するものとドメイン本体を追加しておきましょう。↓
「次へ」を選択。
「DNS」の検証にチェックして「次へ」
「タグ」は何もしません。
設定を確認します。↓
間違いがなければ「確定とリクエスト」
続いて検証作業をやっていきます。↓
「Route 53でのレコード作成」を選択して、出た画面でさらに「作成」をクリック。
以下の画面が出たら「続行」を選択。
「SSL証明書」が発行されるまで待ちます。
発行された準備は完了です。
Cloud Frontの独自ドメインの設定
発行されたらEdit Distributionの画面に戻ります。↓
以下のように設定していきます。
Alternate Domain Names
Cloud Frontで使われる独自のドメインを入力します。
「myapp.com」がドメインの本体だった場合、「static.myapp.com」や「image.myapp.com」などの名前を入力します。(写真ではstatic.~~~にしています)
SSL Certificate
SSLが発行されると、「Custom SSL Certificate」が選択可能になるのでそちらを選択します。
写真の赤丸内の空欄のところをクリックし、表示されたものを選択します。
残りの設定はいじらずに、「Yes,Edit」を選択。
ディストリビューションの設定が完了しました。
これで「static.~~~.com」のドメイン名も、Cloud Frontのドメイン名として使えるよ。という段階まできました。
しかしあとやることが以下のように2つあります。
終わらせます。
Route 53で独自ドメインとCloud Frontの紐付け
まずはRoute 53の設定です。
「static.~~~.com」の接続先はCloud Frontの「~~~cloudfront.net」だという認識をRoute53で設定します。
「Route 53」の「ホストゾーン」を選択して、使っているドメインをクリックします。
「レコードセットの作成」を選択。
名前
ディストリビューションで設定した独自ドメイン名にします。
タイプ
CNAME -正規名
値
ディストリビューション作成時に、発行されたCloud Frontのドメイン名
ルーティングポリシー
シンプル
「作成」を選択。
AWS側の設定はこれにて終了です。
Rails側のCarrierWaveの設定
RailsでCarrierWaveを使用していれば、設定ファイルは以下のようになっているはずです。↓
config/carrier_wave.rb CarrierWave.configure do |config| config.fog_credentials = { # Amazon S3用の設定 :provider => 'AWS', :region => ENV['S3_REGION'], :aws_access_key_id => ENV['S3_ACCESS_KEY'], :aws_secret_access_key => ENV['S3_SECRET_KEY'] } config.fog_directory = ENV['S3_BUCKET'] end
ここにAWS側で設定したドメインでコンテンツのURLを表示するように設定します。
以下のように追加すれば完了です。
config/carrier_wave.rb CarrierWave.configure do |config| config.fog_credentials = { # Amazon S3用の設定 :provider => 'AWS', :region => ENV['S3_REGION'], :aws_access_key_id => ENV['S3_ACCESS_KEY'], :aws_secret_access_key => ENV['S3_SECRET_KEY'] } config.fog_directory = ENV['S3_BUCKET'] #以下を追加↓ config.asset_host = 'https://static.~~~.com' end