1. 概要
こんな記事のタイトルにしてみましたが、要はCGIでアプリを動かしてみましょうという記事です。
ですので、「CGIなんて知っているよ〜(笑)」というエンジニアの皆さんは、そっと「閉じる」ボタンを押してください。多分、初歩的なことしか書いていないので、、、
で、この記事を読んで、「勉強になった」と思ってもらう想定する読者層は、
- 開発はしたことあるけど、リリースまではしたことないエンジニア
かなと思っています。
2. 記事作成のきっかけ
開発を中心に対応していた私は「CGI」のことを知らなかったので、
「え、、、フロント側ってnpm serve
とかで動いてないの!?」
「Laravelってphp artisan serve
で動いてないの!?」みたいな感じでした。
もしかしたら同じ思考のエンジニアの方々がいれば、何かの助けになるかと考え、
このテーマで記事を書いてみようと思いました。
ただ、この記事のタイトル通り「とりあえず動かしてみよう」のレベルで、実際に手を動かして、とりあえず大枠を把握しようというお話です。
ですので、機能や仕組みの詳細は書いていません、、、(強々さん、お願いします)。
色々と詳しく知りたいエンジニアの皆さんも、ここでそっと「閉じる」ボタンを押してください。
3. CGIとは?
CGI (Common Gateway Interface)とは、クライアントからのリクエストに応じて、Webサーバが外部のプログラムを起動し、処理結果をクライアントに返す仕組みのことです(...多分)。
まぁ、これは下記リンク先を参考にしてください
そして、その処理速度を高速化および負荷軽減したした仕組みをFastCGI
といいます。
これもまた下記リンク先を参考にしてください
今回の構成では、FastCGIのPHP版としてphp-fpm
というサーバを使います。
4. 構成
この記事で実際に手を動かして作る構成は、AWSのEC2上でnginxサーバを起動させ、Webサーバ側との通信を想定しています。
一応、EC2の起動からアプリ作成、リリースまでをざっくり記載していますので、セキュリティや非機能要件などは考慮していないです。とりあえず動かすことが優先ですので、実際の開発時では気をつけてください。
下記が今回の技術スタックです。
- React v18.2
- Laravel v10.33
- nginx v1.24
- php-fpm v8.2
そして、インフラはAWSで下図のような簡単な構成を想定しています。
OSはAmazon Linux 2023
です。
業務でよく使っていた技術スタックなので、この構成にしましたが、
他の技術スタックでも同じことはできるので、
気になる方は色々と試してみてください。
5. 実践
まず前提ですが、下記の通りとなります。
- AWSのアカウントは取得済み
- Reactの開発環境は構築済み
- Laravelの開発環境は構築済み
- 開発端末はApple M2 Pro
- ターミナル上の操作(Vim含む)は問題ないこと
5-1. AWSにてインフラ構築
5-1-1. キーペアの作成
- 「EC2」→「ネットワーク&セキュリティ」→「キーペア」のフローで「キーペアを作成」画面に移動する
- キーペアを作成する
5-1-2. VPCの作成
- 「VPC」→「VPCを作成」画面に移動する
- 「作成するリソース」は「VPCなど」を選択する
- 「名前タグの自動生成」は任意で値を入力する
- 「IPv4 CIDR ブロック」は使用するアドレスを入力する
- 「IPv6 CIDR ブロック」は「IPv6 CIDR ブロックなし」を選択する
- 「アベイラビリティゾーン (AZ) の数」は「1」を選択する
- 「パブリックサブネットの数」は「1」を選択する
- 「プライベートサブネットの数」は「0」を選択する
- 「NAT ゲートウェイ ($)」は「なし」を選択する
- 「VPC エンドポイント」は「なし」を選択する
- 「DNS オプション」のチェックは、そのままにする
- 「VPC」を作成をクリックする
VPCとパブリックサブネットに関連するリソースが一括で作成されます。
5-1-3. EC2インスタンスの作成
- 「EC2」→「インスタントを起動」画面に移動する
- 「名前」に任意で値を入力する
- 「Amazon マシンイメージ (AMI)」は「Amazon Linux 2023 AMI」を選択する
- 「インスタンスタイプ」は「t2.micro」を選択する
- 「キーペア」は既存もキーペアを選択する
- 「VPC」は上記で作成したVPCを選択する
- 「サブネット」は上記で作成されたサブネットを選択する
- 「パブリック IP の自動割り当て」は「有効化」を選択する
- 「セキュリティグループを作成」を選択します
- 「セキュリティグループ名」を記入します
- 「説明」を記入します
- 「インバウンドセキュリティグループのルール」は「ssh」と「HTTP」の2つを作成し、「ソース」は両方とも「0.0.0.0/0」を入力しておく
- 「インスタンスを起動する」をクリックする
EC2インスタンスが起動されます。
5-2. Reactにてフロントエンド側の作成(ローカル環境)
-
npx create-react-app アプリ名
コマンドを叩く -
cd アプリ名
コマンドを叩く -
npm install axios
コマンドを叩く -
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;
- 10行目の
xx.xx.xx.xx
は、EC2インスタンス作成時に割り当てられたグローバルIPアドレスを記載する -
npm run build
コマンドを叩く -
/アプリ名/build/
配下にビルドされたhtmlやcssファイルが配置されていることを確認する
/api/greeting
にリクエストを送り、レスポンスを展開する簡単な実装です。
5-3. Laravelにてバックエンド側の作成(ローカル環境)
-
laravel new アプリ名
コマンドを叩く -
cd アプリ名
コマンドを叩く -
sudo chmod 777 storage/
コマンドを叩き、storage配下のファイルの権限を変更する -
/アプリ名/routes/api.php
ファイルを下記に変更する<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; use App\Http\Controllers\GreetingController; Route::get('/greeting', [GreetingController::class, 'index']);
-
php artisan make:controller GreetingController
コマンドを叩き、/app/Http/Controllers/GreetingController
ファイルを作成する -
/アプリ名/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の導入
- 上記で作成したEC2インスタンスにSSH接続でログインする
-
sudo yum update
コマンドを叩き、アップデートを実行する -
sudo yum install nginx
コマンドを叩き、nginxをインストールする -
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 { } }
-
sudo systemctl status nginx
コマンドでnginxの起動が確認できれば、sudo systemctl restart nginx
コマンドでnginxを再起動、nginxが起動していなければsudo systemctl start nginx
コマンドでnginxを起動する -
/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の導入
-
sudo yum install php
コマンドを叩き、php-fpmを含むPHP関連のパッケージを導入する -
sudo vim /etc/php-fpm.d/www.conf
コマンドを叩き、php-fpmの設定を下記のように編集する
a.user = apache
をuser = nginx
に変更する
b.group = apache
をgroup = nginx
に変更する
c.listen = /run/php-fpm/www.sock
がコメントアウトであれば、コメントアウトを外す
d.listen.owner = nginx
がコメントアウトであれば、コメントアウトを外す
e.listen.group = nginx
がコメントアウトであれば、コメントアウトを外す
f.listen.mode = 0660
がコメントアウトであれば、コメントアウトを外す -
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の構成ファイルの配置
-
sudo mkdir /var/www/laravel
コマンドを叩き、Laravekの構成ファイルの配置場所を作成する - ローカル開発環境の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
-
sudo chown ec2-user:nginx /var/www
コマンドを叩き、所有者とグループを変更する - ブラウザで
http://xx.xx.xx.xx
と割り振られたIPアドレスを入力し、下イメージの画面が表示されれば成功です
6. 最後に
お疲れ様です。
最後まで読んでいただき、ありがとうございます。
この記事を読んで、何となくCGI連携の仕組みというか、構築方法が分かってもらえたかなと思います。
ちなみに通信方法には、UNIXソケットを使う方法とTCP/IPソケットを使う方法がありますが、今回は高速で効率的と言われているUNIXソケット通信で構築しています。
まぁ、記事のレベルは高くないので、ぜひぜひ実践を。
何かご指摘などありましたら、コメントでお知らせください。
よろしくお願いいたします