Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
471
Help us understand the problem. What are the problem?

posted at

updated at

Organization

AWS, Docker, CircleCI, Laravelでポートフォリオを作成してみた【参考リンク付き】

初めに

今回はDocker, CircleCI, AWS等、人気の高まっているインフラ技術を一から学んで、Webアプリを作成してみました。
バックエンドはLaravel、フロントエンドにVue.js等といった構成です。

この記事では、アプリ開発にあたって苦労した点や、
各機能実装の際に参考にした記事や教材についてもご紹介していければと思います。

アプリの概要

朝活をテーマをしたSNSアプリです。

  • 朝活仲間を作り、「コツコツ」継続できる
  • 朝活習慣の「コツ」を共有して、朝活の挫折を防ぐ

ことをコンセプトに、「朝活」を文字って「AsaKotsu」というサービスを開発しました。
URLはこちら↓です。 よければ、ご自由に動かしてみてください

アプリのURL: https://pf.asakotsu.com/
(※まだスマホ対応が完了していないので、PCでの閲覧推奨です^^;)

GitHubのURL:https://github.com/ngsw877/asakotsu

使用画面のイメージ

トップページ(投稿一覧とランキング等)
スクリーンショット 2020-11-16 8.00.00.png

タグ毎の投稿一覧
スクリーンショット 2020-11-22 20.10.06.png

投稿詳細と、コメント一覧
スクリーンショット 2020-11-22 20.05.41.png

Zoomミーティング一覧
スクリーンショット 2020-11-16 22.44.58 2.png

ユーザー詳細画面
スクリーンショット 2020-11-16 23.06.16.png

早起き達成時(1日1回まで)
スクリーンショット 2020-11-22 20.03.34.png

無限スクロール
infinitscroll.gif

このアプリの特徴

基本的にはtwitterのような投稿、コメント、いいね、フォロー機能のあるSNSですが、
その他に以下のような特徴のあるアプリです。

  • アプリから、朝活Zoomミーティングを作成、編集、削除できる(ZoomAPI連携)
  • 目標起床時間を設定して、早起き達成日数を記録することができる
  • 早起き達成日数のランキング機能(1ヶ月ごとに集計)
  • 投稿にタグ付けし(カテゴリ)、「朝コツ」タグ等で朝活のコツを共有することができる

使用技術

  • フロントエンド

    • Vue.js 2.6.11
    • jQuery 3.4.1
    • HTML / CSS / Sass / MDBootstrap
  • バックエンド

    • PHP 7.4.9
    • Laravel 6.18.36
    • PHPUnit 8.5.8
    • ZoomAPI (guzzlehttp/guzzle 7.0.1)
  • インフラ

    • CircleCi
    • Docker 19.03.12 / docker-compose 1.26.2
    • nginx 1.18
    • mysql 5.7.31 / PHPMyAdmin
    • AWS ( EC2, ALB, ACM, S3, RDS, CodeDeploy, SNS, Chatbot, CloudFormation, Route53, VPC, EIP, IAM )

サーバーサイドのロジックはPHP/Laravelでプログラミングし、
フロントエンドの細かいデザインはSassで整え、動きを付けたい時はVue.jsやjQueryで実装しました。
開発環境にDocker/docker-composeを使用し、
CI/CDパイプラインに関しては、CircleCIで自動テスト・ビルドを行い、
AWSのCodeDeployで自動デプロイを実現するようにしています。

インフラ構成図

AWS_Diagram.png

開発環境、本番環境について

開発環境にDocker / docker-composeを使用しており、以下の4つの用途のコンテナを使用しています。

  1. Webサーバーのコンテナ: Nginx
  2. アプリケーションのコンテナ: PHP / Laravel / Vue.js
  3. DBのコンテナ: MySQL
  4. DB管理用のコンテナ: PHPMyAdmin

参考リンク:

本番環境のAWS上ではECSでデプロイしたかったのですが、
難易度が高く断念・・
ひとまずEC2でのデプロイ経験にも慣れるため、今回はEC2上で環境構築していく形で進めていきました。

SSL証明書の発行

SSL証明書を発行してHTTPS化も実現したかったため、ACM(AWS Certificate Manager)を使用しています。

ACMを使用するためには、EC2に加えて、ALB(ELB)CloudFrontも必要になってくるため、今回はALBを導入することにしました。
なお、ALBを使用しているものの、節約のため現状では負荷分散やスケールアウトする程のアクセスが見込まれないため、EC2インスタンスは1つのみ用意しています。
なお、アドレスバーに鍵マークがついても、Laravel側のプロキシ設定をしないとcssやjsファイルが読み込まれなかったり、ルーティングがhttps化されなくなるので要注意な印象。。

参考リンク:
- AWS:無料でSSL証明書を取得する方法
- 信用するプロキシの設定

S3バケットへのアップロード

S3は、以下の2つの用途別に用意しています。

  1. CircleCIでビルドしたソースを格納

  2. EC2上のアプリでアップロードした画像データを格納

2に関しては、S3のバケットポリシーの設定や、Laravel側でS3用パッケージのインストールが必要だったりと意外にやるべきことがありました。

参考リンク:

Slackへの通知設定

CodeDeploySNSChatbotを連携して、自動デプロイの開始と終了のタイミングでSlackアカウントに通知が飛んでくるようにしています。なかなか便利。

機能一覧

  • ユーザー登録関連

  • ZoomAPI連携

    • 朝活Zoomミーティング機能(CRUD)
      • ミーティングの新規作成、一覧表示、編集、削除機能
  • 早起き達成の判定機能

    • ユーザー毎に目標起床時刻を設定可能(4:00〜10:00まで)
    • 目標起床時間より前に投稿をすることができれば、早起き達成記録が1日分増えます。
    • ※深夜過ぎ等に投稿した場合も早起き成功とならぬよう、
        目標起床時間より3時間前に投稿しても無効になるよう対処しています。
      (例)目標起床時間を07:00に設定した場合、04:00~07:00に投稿できたら早起き達成
  • ユーザーの早起き達成日数のランキング機能(1ヶ月毎)

  • 無限スクロール機能 (jQuery / inview.js / ajax)

  • ユーザー投稿関連(CRUD)

  • コメント機能

  • タグ機能 (Vue.js / Vue Tags Input)

  • いいね機能 (Vue.js / ajax)

  • フォロー機能

    • フォロー中/フォロワー一覧(ページネーション)
  • フラッシュメッセージ表示機能 (jQuery/ Toastr)

    • 投稿、編集、削除、ログイン、ログアウト時にフラッシュメッセージを表示
  • 画像アップロード機能 (AWS S3バケット)

  • PHPUnitテスト

  • レスポンシブWebデザイン(※徐々に追加しています)

    • ハンバーガーメニュー(jQuery)

DB設計

ER図

AsaKotsu_ERD.png

各テーブルについて

テーブル名 説明
users 登録ユーザー情報
follows フォロー中/フォロワーのユーザー情報
achievement_days ユーザーが早起き達成した日付を、履歴として管理
meetings ユーザーが作成したZoomミーティング情報
articles ユーザー投稿の情報
tags ユーザー投稿のタグ情報
article_tags articleとtagsの中間テーブル
likes 投稿への、いいねの情報
comments ユーザー投稿への、コメントの情報

早起き達成機能 関連のポイント

usersテーブルwake_up_timeはユーザーの目標起床時間を意味しています。
この時間よりも早い時間にユーザーが投稿をできれば、その日の早起きが達成となります。
なお、
「目標起床時間が07:00で、深夜1:00に投稿した」
というように、早過ぎる時間にユーザーが投稿した
場合にも早起き達成とならないように設定しています。
その仕組みとして、usersテーブルrange_of_successの値が利用されています。
これは、
「目標起床時間より何時間前までに投稿すれば早起き達成となるのか、その範囲を表す整数値」
です。
デフォルトは3で、例えば目標起床時間を07:00に設定している場合は、その3時間前の
04:00 〜 07:00 の間に投稿できれば早起き達成となります。

こうして早起き達成をすることができたら、achievement_daysテーブルdateに達成日の日付が履歴として記録されていきます。
例) 2020-11-22
この日付データを利用して、以下の機能を実現しています。

①  1ヶ月毎の早起き達成日数を算出
② ①の日数を利用したランキング機能

当初は、早起き継続日数のランキングにしようかとも考えていましたが、
ユーザーのモチベーション維持等の観点から1ヶ月毎の早起き達成日数を採用することにしました。

※朝活アプリなので、もともとは目標起床時間04:00~10:00の間しか設定できない仕様ですが、
現在は「早起き達成判定」機能を好きな時間にお試しいただけるよう、時間設定を自由にできるようにしています。

苦労したこと

開発からデプロイまで、どの工程でももれなくエラーで苦戦しましたがw、
ここでは特に印象に残っている点をまとめます。

CircleCIで苦労したこと

  • CircleCIの設定ファイルである、config.ymlの設定
  • 自動ビルド、自動テストの流れの理解

config.ymlの設定においては、だいぶエラーに悩まされました。。
特に、コマンドやパスを指定する時は、パスのルートはどこが起点になっているのかを理解することが重要な印象。
テスト失敗時の対策としては、ビルドされたコンテナにSSHログインしてエラーログを確認し、原因を解消していくようにしていました。

参考リンク: SSH を使用したデバッグ

AWSデプロイで苦労したこと

  • ACMでのSSL証明書発行
  • Laravelで画像をS3にアップロードする設定
  • CodeDeployでの、自動デプロイ設定(特にappspec.yml)
  • EC2インスタンスのセットアップ

上述した、
SSL証明書の発行
S3バケットへのアップロード
周りでエラーにハマりがちでした。
また、今回はECSでなくEC2でデプロイすることとしましたが、EC2にSSHログインしてから
インストールしたり設定するファイルが多く、その辺りの作業も大変でした。
この工程を考えると、ますますECSを扱えるようになりたく思いましたね^^;

フロントエンドで苦労したこと

  • UI/UXの調整(Sass)
  • Ajax全般

バックエンドでの苦労

  • DB設計
  • DBリレーション関連の処理
  • PHPUnitでのテスト全般

リレーション周りについては当初なかなか苦戦しました。
どのテーブルとどのテーブルを関連付けるのか、そして関連付けた情報をどうやって取得すれば良いのか?
また、

  • $article->user()
  • $article->user

例えばこの2つの違いについても重要なポイントと感じました。

PHPUnitのテストコードについては、体系的に学べる情報がなかなか見つからなかったので、情報収集に苦労しましたね。

ZoomAPI連携で苦労したこと

  • Guzzleの理解
  • ZoomAPIの理解

アプリ上からZoomミーティングを作成したり編集できる機能をつけることにしましたが、
これまで外部APIを利用したことがなかったこともあり、文法的なものや、API通信の仕組みについて理解するまでが難しく感じました。

実装にあたり、まずLaravelでZoomAPIと通信を行うために、PHPのHTTPクライアントである
Guzzleをインストールしました。

参考リンク:

次に、Zoomアプリマーケットプレイスでアプリを登録し、公式ドキュメントを読んでみるも、英語な上初めはどこのページの何を見れば良いのかわからず苦戦しました。。^^;

しかし、Laravelで、ZoomAPIと通信を行う処理のサンプルコードを紹介している
海外の記事を参考にしたり試行錯誤しているうちに、次第に公式ドキュメントから必要な情報を探せるようにもなってきました。

参考リンク:

ただ、今回Laravel6系でアプリを開発していたため、通常Laravel7系で使用できるGuzzleラッパーが使えず、ややコードを書き換えないといけない点にも苦労しました。

参考にした学習教材等

基本的には、UdemyTechpitで学習してきました。
この2つはとてもわかりやすいです。
個人的には、Udemyで基礎を学んでから、応用編としてTechpitで手を動かしながら学ぶのが良いと感じました。

Docker / docker-compose

AWS

PHPUnit / CircleCI / AWS

PHP

Laravel

Laravel / Vue.js

Sass

今後の課題

  • レスポンシブWebデザイン(スマホ対応)
  • デザイン面の改善
  • 無限スクロールの不具合修正(読み込まれた投稿のいいねボタンが消える)
  • ALBにAuto Scalingを追加し、EC2を冗長化
  • ECS(EKS)でのデプロイ
  • RDSの冗長化
  • インフラのコード化
  • テストコードの充実
  • 投稿時に別画面へ遷移するのではなく、入力フォームをモーダルで表示させるようにする
  • 開始前のZoomミーティング、終了ミーティングのソート機能

まだ課題も多いですが、一つずつ改善してよりブラッシュアップしていきたく思います。

だいぶ長い記事になってしまいましたが、ここまで読んでくださりありがとうございました!^^

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
471
Help us understand the problem. What are the problem?