68
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Systemi(株式会社システムアイ)Advent Calendar 2023

Day 1

とりあえずEC2上でCGI連携のnginx+React+Laravelアプリを動かしてみよう

Last updated at Posted at 2023-11-30

1. 概要

こんな記事のタイトルにしてみましたが、要はCGIでアプリを動かしてみましょうという記事です。
ですので、「CGIなんて知っているよ〜(笑)」というエンジニアの皆さんは、そっと「閉じる」ボタンを押してください。多分、初歩的なことしか書いていないので、、、

で、この記事を読んで、「勉強になった」と思ってもらう想定する読者層は、

  • 開発はしたことあるけど、リリースまではしたことないエンジニア

かなと思っています。

2. 記事作成のきっかけ

開発を中心に対応していた私は「CGI」のことを知らなかったので、
「え、、、フロント側ってnpm serveとかで動いてないの!?」
「Laravelってphp artisan serveで動いてないの!?」みたいな感じでした。

もしかしたら同じ思考のエンジニアの方々がいれば、何かの助けになるかと考え、
このテーマで記事を書いてみようと思いました。

ただ、この記事のタイトル通り「とりあえず動かしてみよう」のレベルで、実際に手を動かして、とりあえず大枠を把握しようというお話です。

ですので、機能や仕組みの詳細は書いていません、、、(強々さん、お願いします:bow_tone1:)。

色々と詳しく知りたいエンジニアの皆さんも、ここでそっと「閉じる」ボタンを押してください。

3. CGIとは?

CGI (Common Gateway Interface)とは、クライアントからのリクエストに応じて、Webサーバが外部のプログラムを起動し、処理結果をクライアントに返す仕組みのことです(...多分)。
まぁ、これは下記リンク先を参考にしてください:bow_tone1:

参考:「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典|CGIとは

そして、その処理速度を高速化および負荷軽減したした仕組みをFastCGIといいます。
これもまた下記リンク先を参考にしてください:bow_tone1:

参考:「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典|FastCGIとは

今回の構成では、FastCGIのPHP版としてphp-fpmというサーバを使います。

4. 構成

この記事で実際に手を動かして作る構成は、AWSのEC2上でnginxサーバを起動させ、Webサーバ側との通信を想定しています。
一応、EC2の起動からアプリ作成、リリースまでをざっくり記載していますので、セキュリティや非機能要件などは考慮していないです。とりあえず動かすことが優先ですので、実際の開発時では気をつけてください。

下記が今回の技術スタックです。

  • React v18.2
  • Laravel v10.33
  • nginx v1.24
  • php-fpm v8.2

次に構成ですが、下図のような感じを想定しています。

image.png

そして、インフラはAWSで下図のような簡単な構成を想定しています。

image.png

OSはAmazon Linux 2023です。

業務でよく使っていた技術スタックなので、この構成にしましたが、
他の技術スタックでも同じことはできるので、
気になる方は色々と試してみてください。

5. 実践

まず前提ですが、下記の通りとなります。

  • AWSのアカウントは取得済み
  • Reactの開発環境は構築済み
  • Laravelの開発環境は構築済み
  • 開発端末はApple M2 Pro
  • ターミナル上の操作(Vim含む)は問題ないこと

5-1. AWSにてインフラ構築

5-1-1. キーペアの作成
  1. 「EC2」→「ネットワーク&セキュリティ」→「キーペア」のフローで「キーペアを作成」画面に移動する
  2. キーペアを作成する
5-1-2. VPCの作成
  1. 「VPC」→「VPCを作成」画面に移動する
  2. 「作成するリソース」は「VPCなど」を選択する
  3. 「名前タグの自動生成」は任意で値を入力する
  4. 「IPv4 CIDR ブロック」は使用するアドレスを入力する
  5. 「IPv6 CIDR ブロック」は「IPv6 CIDR ブロックなし」を選択する
  6. 「アベイラビリティゾーン (AZ) の数」は「1」を選択する
  7. 「パブリックサブネットの数」は「1」を選択する
  8. 「プライベートサブネットの数」は「0」を選択する
  9. 「NAT ゲートウェイ ($)」は「なし」を選択する
  10. 「VPC エンドポイント」は「なし」を選択する
  11. 「DNS オプション」のチェックは、そのままにする
  12. 「VPC」を作成をクリックする

VPCとパブリックサブネットに関連するリソースが一括で作成されます。

5-1-3. EC2インスタンスの作成
  1. 「EC2」→「インスタントを起動」画面に移動する
  2. 「名前」に任意で値を入力する
  3. 「Amazon マシンイメージ (AMI)」は「Amazon Linux 2023 AMI」を選択する
  4. 「インスタンスタイプ」は「t2.micro」を選択する
  5. 「キーペア」は既存もキーペアを選択する
  6. 「VPC」は上記で作成したVPCを選択する
  7. 「サブネット」は上記で作成されたサブネットを選択する
  8. 「パブリック IP の自動割り当て」は「有効化」を選択する
  9. 「セキュリティグループを作成」を選択します
  10. 「セキュリティグループ名」を記入します
  11. 「説明」を記入します
  12. 「インバウンドセキュリティグループのルール」は「ssh」と「HTTP」の2つを作成し、「ソース」は両方とも「0.0.0.0/0」を入力しておく
  13. 「インスタンスを起動する」をクリックする

EC2インスタンスが起動されます。

5-2. Reactにてフロントエンド側の作成(ローカル環境)

  1. npx create-react-app アプリ名コマンドを叩く
  2. cd アプリ名コマンドを叩く
  3. npm install axiosコマンドを叩く
  4. App.jsファイルの内容を下記に変更する
    import axios from "axios"
    import React, { useEffect, useState } from "react"
    
    function App() {
      const [greeting, setGreeting] = useState("")
    
      useEffect(() => {
        (async() => {
          try {
            const response = await axios.get("http://xx.xx.xx.xx/api/greeting")
            setGreeting(response.data.greeting)
          } catch (error) {
            console.error(error)
          }
        })()
      }, [])
    
      return (
        <div className="App">
          <p>{greeting}</p>
        </div>
      )
    }
    
    export default App;
    
    
  5. 10行目のxx.xx.xx.xxは、EC2インスタンス作成時に割り当てられたグローバルIPアドレスを記載する
  6. npm run buildコマンドを叩く
  7. /アプリ名/build/配下にビルドされたhtmlやcssファイルが配置されていることを確認する

/api/greetingにリクエストを送り、レスポンスを展開する簡単な実装です。

5-3. Laravelにてバックエンド側の作成(ローカル環境)

  1. laravel new アプリ名コマンドを叩く
  2. cd アプリ名コマンドを叩く
  3. sudo chmod 777 storage/コマンドを叩き、storage配下のファイルの権限を変更する
  4. /アプリ名/routes/api.phpファイルを下記に変更する
    <?php
    
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Route;
    use App\Http\Controllers\GreetingController;
    
    Route::get('/greeting', 
    [GreetingController::class, 'index']);
    
    
  5. php artisan make:controller GreetingControllerコマンドを叩き、/app/Http/Controllers/GreetingControllerファイルを作成する
  6. /アプリ名/app/Http/Controllers/GreetingControllerファイルを下記に変更する
    <?php
    
    namespace App\Http\Controllers;
    
    class GreetingController extends Controller
    {
        public function index()
        {
        return response()->json(['greeting' => 'Hello SystemI']);
        }
    }
    

/api/greetingのリクエストに対する受け口を作り、{ 'greeting': 'SystemI' }というレスポンスを返す簡単な実装です。

5-4. サーバ構築作業

5-4-1. nginxの導入
  1. 上記で作成したEC2インスタンスにSSH接続でログインする
  2. sudo yum updateコマンドを叩き、アップデートを実行する
  3. sudo yum install nginxコマンドを叩き、nginxをインストールする
  4. sudo vim /etc/nginx/nginx.confコマンドを叩き、serverディレクティブ内にlocation /apiのディレクティブを追記して保存する
     server {
         listen       80;
         listen       [::]:80;
         server_name  _;
         root         /usr/share/nginx/html;
    
         # Load configuration files for the default server block.
         include /etc/nginx/default.d/*.conf;
    
         location /api {
             alias /var/www/laravel/public;       # この後、/var/www配下にlaravelディレクトリを作成する
             fastcgi_pass unix:/var/run/php-fpm/www.sock;
             fastcgi_param SCRIPT_FILENAME $document_root/index.php;
             include fastcgi_params;
         }
    
         error_page 404 /404.html;
         location = /404.html {
         }
    
         error_page 500 502 503 504 /50x.html;
         location = /50x.html {
         }
     }
    
  5. sudo systemctl status nginxコマンドでnginxの起動が確認できれば、sudo systemctl restart nginxコマンドでnginxを再起動、nginxが起動していなければsudo systemctl start nginxコマンドでnginxを起動する
  6. /usr/share/nginx/html配下のファイルを全て削除し、Reactでbuildしたファイル群を/usr/share/nginx/html配下に配置する
    html   # こんな感じに配置する想定です
      ├── asset-manifest.json
      ├── favicon.ico
      ├── index.html
      ├── logo192.png
      ├── logo512.png
      ├── manifest.json
      ├── robots.txt
      └── static
    
5-4-2. php-fpmの導入
  1. sudo yum install phpコマンドを叩き、php-fpmを含むPHP関連のパッケージを導入する
  2. sudo vim /etc/php-fpm.d/www.confコマンドを叩き、php-fpmの設定を下記のように編集する
    a. user = apacheuser = nginxに変更する
    b. group = apachegroup = nginxに変更する
    c. listen = /run/php-fpm/www.sockがコメントアウトであれば、コメントアウトを外す
    d. listen.owner = nginxがコメントアウトであれば、コメントアウトを外す
    e. listen.group = nginxがコメントアウトであれば、コメントアウトを外す
    f. listen.mode = 0660がコメントアウトであれば、コメントアウトを外す
  3. sudo systemctl status php-fpmコマンドでphp-fpmの起動が確認できれば、sudo systemctl restart php-fpmコマンドでphp-fpmを再起動、php-fpmが起動していなければsudo systemctl start php-fpmコマンドでphp-fpmを起動する
5-4-3. Laravelの構成ファイルの配置
  1. sudo mkdir /var/www/laravelコマンドを叩き、Laravekの構成ファイルの配置場所を作成する
  2. ローカル開発環境のLaravel構成ファイルを/var/www/laravel配下に配置する
    laravel  # こんな感じに配置する想定です
      ├── README.md
      ├── app
      ├── artisan
      ├── bootstrap
      ├── composer.json
      ├── composer.lock
      ├── config
      ├── database
      ├── package.json
      ├── phpunit.xml
      ├── public
      ├── resources
      ├── routes
      ├── storage
      ├── tests
      ├── vendor
      └── vite.config.js
    
  3. sudo chown ec2-user:nginx /var/wwwコマンドを叩き、所有者とグループを変更する
  4. ブラウザでhttp://xx.xx.xx.xxと割り振られたIPアドレスを入力し、下イメージの画面が表示されれば成功です

スクリーンショット 2023-11-26 13.54.44.png

6. 最後に

お疲れ様です。
最後まで読んでいただき、ありがとうございます。

この記事を読んで、何となくCGI連携の仕組みというか、構築方法が分かってもらえたかなと思います。
ちなみに通信方法には、UNIXソケットを使う方法とTCP/IPソケットを使う方法がありますが、今回は高速で効率的と言われているUNIXソケット通信で構築しています。

まぁ、記事のレベルは高くないので、ぜひぜひ実践を。
何かご指摘などありましたら、コメントでお知らせください。

よろしくお願いいたします:bow_tone1:

68
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
68
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?