Node.jsサーバの構築とReactコードのデプロイの手順

Gitリポジトリの作成からAWS EC2上でのNode.jsサーバの構築、そして提供されたReactコードのデプロイまで、全ての手順を整理しました。

---

## **目次**

1. **前提条件**
2. **開発環境のセットアップ**
   - 2.1 Gitのインストール（必要な場合）
   - 2.2 プロジェクトディレクトリの作成
   - 2.3 Next.jsプロジェクトの初期化
   - 2.4 提供されたコードの配置
   - 2.5 必要なパッケージのインストール
   - 2.6 アプリケーションの起動と確認
   - 2.7 Gitリポジトリの作成とGitHubへのアップロード
3. **AWSアカウントの作成とEC2インスタンスの設定**
   - 3.1 AWSアカウントの作成
   - 3.2 EC2インスタンスの作成
4. **EC2インスタンスへの接続**
5. **EC2上でのサーバ環境の構築**
   - 5.1 Ubuntuの初期設定
   - 5.2 Node.jsとnpmのインストール
   - 5.3 Gitのインストール
6. **アプリケーションのデプロイ**
   - 6.1 GitHubからのソースコードのクローン
   - 6.2 アプリケーションのセットアップ
   - 6.3 アプリケーションのビルドと起動
7. **PM2のインストールと設定**
8. **Nginxのインストールとリバースプロキシの設定**
9. **ファイアウォールの設定（任意）**
10. **ドメイン名とSSLの設定（任意）**
11. **まとめと確認**

---

## **1. 前提条件**

- **パソコン**：インターネットに接続されたパソコン。
- **基本的なコマンドライン操作の知識**：ターミナルやコマンドプロンプトでコマンドを入力できること。
- **AWSアカウント**：持っていない場合はこれから作成します。
- **GitHubアカウント**：持っていない場合はこれから作成します。

---

## **2. 開発環境のセットアップ**

### **2.1 Gitのインストール（必要な場合）**

#### **Windowsの場合**

- **Git for Windows**をダウンロードし、インストールします。
  - ダウンロードリンク：[https://git-scm.com/download/win](https://git-scm.com/download/win)

#### **Macの場合**

- ターミナルで以下のコマンドを実行します。

  ```bash
  xcode-select --install
  ```

#### **Linuxの場合**

- ターミナルで以下のコマンドを実行します。

  ```bash
  sudo apt install -y git
  ```

### **2.2 プロジェクトディレクトリの作成**

1. ターミナルまたはコマンドプロンプトを開きます。

2. プロジェクト用のディレクトリを作成し、移動します。

   ```bash
   mkdir wago-website
   cd wago-website
   ```

### **2.3 Next.jsプロジェクトの初期化**

1. Next.jsアプリケーションを初期化します。

   ```bash
   npx create-next-app@latest
   ```

2. 質問に対して以下のように回答します。

   - **What is your project named?**: `wago-website`（または任意の名前）
   - **Would you like to use TypeScript?**: `Yes`
   - **Would you like to use ESLint?**: `Yes`
   - **Would you like to use Tailwind CSS?**: `Yes`
   - **Would you like to use `src/` directory?**: `Yes`
   - **Would you like to use App Router? (recommended)**: `Yes`
   - **Would you like to customize the default import alias?**: `Yes`（`@/*` と入力）

3. プロジェクトが作成されます。

### **2.4 提供されたコードの配置**

1. `src/components`ディレクトリを作成します。

   ```bash
   mkdir src/components
   ```

2. 以下のコンポーネントファイルを作成し、それぞれに提供されたコードを貼り付けます。

   - `src/components/Navbar.tsx`
   - `src/components/Hero.tsx`
   - `src/components/About.tsx`
   - `src/components/Services.tsx`
   - `src/components/ContactForm.tsx`
   - `src/components/Footer.tsx`

**各コンポーネントのコード**：

---

#### **Navbar.tsx**

```tsx
// src/components/Navbar.tsx
"use client";

import React from 'react';

const Navbar = () => (
  <nav className="bg-white shadow-md">
    <div className="container mx-auto px-6 py-3">
      <div className="flex justify-between items-center">
        <div className="flex items-center">
          <span className="text-xl font-semibold text-gray-800">和合</span>
        </div>
        <div className="flex items-center space-x-4">
          <a href="#home" className="text-gray-800 hover:text-blue-600">ホーム</a>
          <a href="#about" className="text-gray-800 hover:text-blue-600">会社概要</a>
          <a href="#services" className="text-gray-800 hover:text-blue-600">サービス</a>
          <a href="#contact" className="text-gray-800 hover:text-blue-600">お問い合わせ</a>
        </div>
      </div>
    </div>
  </nav>
);

export default Navbar;
```

---

#### **Hero.tsx**

```tsx
// src/components/Hero.tsx
"use client";

import React from 'react';

const Hero = () => (
  <section id="home" className="bg-gradient-to-r from-blue-500 to-purple-600 text-white py-20">
    <div className="container mx-auto px-6 text-center">
      <h1 className="text-4xl md:text-6xl font-bold mb-4">和合</h1>
      <p className="text-xl md:text-2xl mb-8">革新的な投資とテクノロジーの融合</p>
      <p className="text-lg mb-8">IT、NFT金融、投資分野での革新的なソリューションを提供</p>
      <a href="#contact" className="bg-white text-blue-600 px-6 py-3 rounded-full font-semibold text-lg hover:bg-gray-100 transition duration-300">お問い合わせ</a>
    </div>
  </section>
);

export default Hero;
```

---

#### **About.tsx**

```tsx
// src/components/About.tsx
"use client";

import React from 'react';

const About = () => (
  <section id="about" className="py-20 bg-gray-100">
    <div className="container mx-auto px-6">
      <h2 className="text-3xl font-semibold text-center mb-8">会社概要</h2>
      <p className="text-lg text-center mb-8">
        和合は、IT、NFT金融、投資分野において革新的なソリューションを提供する企業です。
        最先端のテクノロジーと伝統的な金融の知見を組み合わせ、クライアントに最適なサービスを提供しています。
      </p>
      <div className="text-center">
        <h3 className="text-xl font-semibold mb-4">ミッション</h3>
        <p className="text-lg">
          テクノロジーと金融の力で、より良い未来を創造し、
          クライアントの成功を支援することで、社会に貢献します。
        </p>
      </div>
    </div>
  </section>
);

export default About;
```

---

#### **Services.tsx**

```tsx
// src/components/Services.tsx
"use client";

import React from 'react';

const Services = () => (
  <section id="services" className="py-20">
    <div className="container mx-auto px-6">
      <h2 className="text-3xl font-semibold text-center mb-12">サービス</h2>
      <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
        <div className="bg-white p-6 rounded-lg shadow-md">
          <h3 className="text-xl font-semibold mb-4">ITソリューション</h3>
          <p>最新のテクノロジーを活用したカスタムソフトウェア開発、クラウドソリューション、AIアプリケーションの提供</p>
        </div>
        <div className="bg-white p-6 rounded-lg shadow-md">
          <h3 className="text-xl font-semibold mb-4">NFT金融サービス</h3>
          <p>NFTを活用した新しい金融商品の開発、NFTマーケットプレイスの構築、NFT担保ローンなどの革新的な金融サービス</p>
        </div>
        <div className="bg-white p-6 rounded-lg shadow-md">
          <h3 className="text-xl font-semibold mb-4">投資アドバイザリー</h3>
          <p>AI駆動の投資分析、ブロックチェーン技術を活用したポートフォリオ管理、カスタマイズされた投資戦略の提案</p>
        </div>
      </div>
    </div>
  </section>
);

export default Services;
```

---

#### **ContactForm.tsx**

```tsx
// src/components/ContactForm.tsx
"use client";

import React, { useState } from 'react';

const ContactForm = () => {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    message: ''
  });

  const handleChange = (e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => {
    setFormData({ ...formData, [e.target.name]: e.target.value });
  };

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // ここでバックエンドにフォームデータを送信する処理を実装します
    console.log('Form submitted:', formData);
    alert('お問い合わせありがとうございます。内容を確認の上、後ほどご連絡いたします。');
    setFormData({ name: '', email: '', message: '' });
  };

  return (
    <section id="contact" className="py-20 bg-gray-100">
      <div className="container mx-auto px-6">
        <h2 className="text-3xl font-semibold text-center mb-8">お問い合わせ</h2>
        <form onSubmit={handleSubmit} className="max-w-lg mx-auto">
          <div className="mb-4">
            <label htmlFor="name" className="block text-gray-700 font-bold mb-2">お名前</label>
            <input
              type="text"
              id="name"
              name="name"
              value={formData.name}
              onChange={handleChange}
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              required
            />
          </div>
          <div className="mb-4">
            <label htmlFor="email" className="block text-gray-700 font-bold mb-2">メールアドレス</label>
            <input
              type="email"
              id="email"
              name="email"
              value={formData.email}
              onChange={handleChange}
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              required
            />
          </div>
          <div className="mb-4">
            <label htmlFor="message" className="block text-gray-700 font-bold mb-2">メッセージ</label>
            <textarea
              id="message"
              name="message"
              value={formData.message}
              onChange={handleChange}
              rows={4}
              className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              required
            ></textarea>
          </div>
          <button type="submit" className="w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 transition duration-300">送信</button>
        </form>
      </div>
    </section>
  );
};

export default ContactForm;
```

---

#### **Footer.tsx**

```tsx
// src/components/Footer.tsx
"use client";

import React from 'react';
import { Mail, Phone, MapPin } from 'lucide-react';

const Footer = () => (
  <footer className="bg-gray-800 text-white py-8">
    <div className="container mx-auto px-6">
      <div className="flex flex-wrap justify-between">
        <div className="w-full md:w-1/3 mb-6 md:mb-0">
          <h3 className="text-lg font-semibold mb-2">和合</h3>
          <p className="text-sm">革新的な投資とテクノロジーの融合</p>
        </div>
        <div className="w-full md:w-1/3 mb-6 md:mb-0">
          <h3 className="text-lg font-semibold mb-2">お問い合わせ</h3>
          <ul className="text-sm">
            <li className="flex items-center mb-2"><Mail className="mr-2" /> info@wagohuaxia.com</li>
            <li className="flex items-center mb-2"><Phone className="mr-2" /> 03-1234-5678</li>
            <li className="flex items-center"><MapPin className="mr-2" /> 東京都千代田区丸の内1-1-1</li>
          </ul>
        </div>
        <div className="w-full md:w-1/3">
          <h3 className="text-lg font-semibold mb-2">リンク</h3>
          <ul className="text-sm">
            <li><a href="#home" className="hover:text-blue-400">ホーム</a></li>
            <li><a href="#about" className="hover:text-blue-400">会社概要</a></li>
            <li><a href="#services" className="hover:text-blue-400">サービス</a></li>
            <li><a href="#contact" className="hover:text-blue-400">お問い合わせ</a></li>
          </ul>
        </div>
      </div>
      <div className="mt-8 border-t border-gray-700 pt-8 text-center text-sm">
        <p>&copy; 2023 華夏. All rights reserved.</p>
      </div>
    </div>
  </footer>
);

export default Footer;
```

---

### **2.5 必要なパッケージのインストール**

ターミナルで以下のコマンドを実行し、必要なパッケージをインストールします。

```bash
npm install framer-motion lucide-react
```

### **2.6 アプリケーションの起動と確認**

#### **2.6.1 メインページの作成**

`src/app/page.tsx`を以下のように編集します。

```tsx
// src/app/page.tsx
"use client";

import React from 'react';
import Navbar from '@/components/Navbar';
import Hero from '@/components/Hero';
import About from '@/components/About';
import Services from '@/components/Services';
import ContactForm from '@/components/ContactForm';
import Footer from '@/components/Footer';

export default function HomePage() {
  return (
    <div className="min-h-screen flex flex-col">
      <Navbar />
      <main className="flex-grow">
        <Hero />
        <About />
        <Services />
        <ContactForm />
      </main>
      <Footer />
    </div>
  );
}
```

#### **2.6.2 グローバルレイアウトの設定**

`src/app/layout.tsx`を以下のように編集します。

```tsx
// src/app/layout.tsx
import '../styles/globals.css';
import React from 'react';

export const metadata = {
  title: '和合',
  description: '革新的な投資とテクノロジーの融合',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
      <body>{children}</body>
    </html>
  );
}
```

#### **2.6.3 アプリケーションの起動**

ターミナルで以下のコマンドを実行します。

```bash
npm run dev
```

ブラウザで`http://localhost:3000`にアクセスし、ウェブサイトが正しく表示されることを確認してください。

### **2.7 Gitリポジトリの作成とGitHubへのアップロード**

#### **2.7.1 GitHubアカウントの作成**

- [GitHub公式サイト](https://github.com/)にアクセスし、アカウントを作成します。

#### **2.7.2 ローカルリポジトリの初期化**

ターミナルで以下のコマンドを実行します。

```bash
git init
```

#### **2.7.3 `.gitignore`ファイルの作成**

プロジェクトルートに`.gitignore`ファイルを作成し、以下の内容を記述します。

```
node_modules
.next
.env
```

#### **2.7.4 ファイルのステージングとコミット**

```bash
git add .
git commit -m "Initial commit"
```

#### **2.7.5 GitHubに新しいリポジトリを作成**

1. GitHubのサイトで、右上の「＋」アイコンをクリックし、「New repository」を選択します。

2. リポジトリ名を入力します（例：`wago-website`）。

3. 「Create repository」をクリックします。

#### **2.7.6 リモートリポジトリの追加とプッシュ**

ターミナルで以下のコマンドを実行します。

```bash
git remote add origin https://github.com/あなたのユーザー名/wago-website.git
git branch -M main
git push -u origin main
```

- **注意**：`あなたのユーザー名`を実際のGitHubユーザー名に置き換えてください。

---

## **3. AWSアカウントの作成とEC2インスタンスの設定**

### **3.1 AWSアカウントの作成**

1. [AWS公式サイト](https://aws.amazon.com/jp/)にアクセスし、「今すぐ無料で始める」をクリックします。

2. 画面の指示に従ってアカウントを作成します。

### **3.2 EC2インスタンスの作成**

#### **3.2.1 EC2ダッシュボードにアクセス**

1. AWSマネジメントコンソールにログインします。

2. サービス一覧から「EC2」を選択します。

#### **3.2.2 インスタンスの起動**

1. 「インスタンス」メニューから「インスタンスを起動」をクリックします。

#### **3.2.3 AMI（Amazon Machine Image）の選択**

1. 「Ubuntu Server 22.04 LTS」を選択します。

#### **3.2.4 インスタンスタイプの選択**

1. 「t2.micro」（無料利用枠対象）を選択します。

#### **3.2.5 キーペアの作成**

1. 「キーペアの作成」をクリックし、新しいキーペアを作成します。

   - キーペア名を入力（例：`wagohuaxia-key`）。

   - キーペアのファイル形式は`.pem`（Mac/Linuxの場合）を選択します。

2. キーペアファイルをダウンロードし、安全な場所に保管します。

#### **3.2.6 ネットワーク設定**

1. 「セキュリティグループを設定」で以下のルールを追加します。

   - **SSH（ポート22）**：自分のIPアドレスからのアクセスを許可します。

   - **HTTP（ポート80）**：全てのIPからのアクセスを許可します。

   - **HTTPS（ポート443）**：全てのIPからのアクセスを許可します。

#### **3.2.7 インスタンスの起動**

1. すべての設定が完了したら、「インスタンスを起動」をクリックします。

---

## **4. EC2インスタンスへの接続**

### **4.1 パブリックIPアドレスの確認**

1. EC2コンソールで、起動したインスタンスを選択します。

2. 「パブリックIPv4アドレス」をメモします。

### **4.2 SSHで接続**

#### **Mac/Linuxの場合**

1. ターミナルで、キーペアファイルが保存されているディレクトリに移動します。

   ```bash
   cd /path/to/your/keypair
   ```

2. キーペアファイルの権限を変更します。

   ```bash
   chmod 400 wagohuaxia-key.pem
   ```

3. SSHで接続します。

   ```bash
   ssh -i "wagohuaxia-key.pem" ubuntu@your-ec2-public-ip
   ```

   - **注意**：`your-ec2-public-ip`を実際のパブリックIPアドレスに置き換えてください。

#### **Windowsの場合**

1. **PuTTY**を使用します。

2. PuTTYgenで`.pem`ファイルを`.ppk`形式に変換します。

3. PuTTYで以下の情報を入力します。

   - **Host Name**：`ubuntu@your-ec2-public-ip`

   - **Port**：`22`

4. 左側のメニューから「SSH」>「Auth」を選択し、変換した`.ppk`ファイルを指定します。

5. 「Open」をクリックして接続します。

---

## **5. EC2上でのサーバ環境の構築**

### **5.1 Ubuntuの初期設定**

```bash
sudo apt update
sudo apt upgrade -y
```

### **5.2 Node.jsとnpmのインストール**

```bash
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
```

インストールの確認：

```bash
node -v
npm -v
```

### **5.3 Gitのインストール**

```bash
sudo apt install -y git
```

---

## **6. アプリケーションのデプロイ**

### **6.1 GitHubからのソースコードのクローン**

1. ホームディレクトリに移動します。

   ```bash
   cd ~
   ```

2. GitHubからリポジトリをクローンします。

   ```bash
   git clone https://github.com/あなたのユーザー名/wago-website.git
   ```

   - **注意**：`あなたのユーザー名`を実際のGitHubユーザー名に置き換えてください。

3. プロジェクトディレクトリに移動します。

   ```bash
   cd wago-website
   ```

### **6.2 アプリケーションのセットアップ**

1. 依存関係をインストールします。

   ```bash
   npm install
   ```

### **6.3 アプリケーションのビルドと起動**

1. アプリケーションをビルドします。

   ```bash
   npm run build
   ```

2. アプリケーションを起動します。

   ```bash
   npm run start
   ```

   - デフォルトでは、ポート`3000`で起動します。

3. 動作確認：

   ```bash
   curl http://localhost:3000
   ```

   - HTMLコードが表示されれば成功です。

---

## **7. PM2のインストールと設定**

### **7.1 PM2のインストール**

```bash
sudo npm install -g pm2
```

### **7.2 PM2でアプリケーションを起動**

```bash
pm2 start npm --name "wagohuaxia" -- start
```

### **7.3 PM2の設定を保存し、再起動時に自動起動**

```bash
pm2 save
pm2 startup
```

- 表示されたコマンドをコピーして実行します。

---

## **8. Nginxのインストールとリバースプロキシの設定**

### **8.1 Nginxのインストール**

```bash
sudo apt install -y nginx
```

### **8.2 Nginxの設定**

1. デフォルトの設定ファイルをバックアップします。

   ```bash
   sudo mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
   ```

2. 新しい設定ファイルを作成します。

   ```bash
   sudo nano /etc/nginx/sites-available/default
   ```

3. 以下の内容を貼り付けます。

   ```nginx
   server {
       listen 80;
       server_name your-domain.com; # またはEC2のパブリックIP

       location / {
           proxy_pass http://localhost:3000;
           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection 'upgrade';
           proxy_set_header Host $host;
           proxy_cache_bypass $http_upgrade;
       }
   }
   ```

   - **注意**：`your-domain.com`を実際のドメイン名またはパブリックIPに置き換えてください。

4. Nginxの設定をテストします。

   ```bash
   sudo nginx -t
   ```

5. Nginxを再起動します。

   ```bash
   sudo systemctl restart nginx
   ```

### **8.3 ブラウザからのアクセス確認**

- ブラウザで`http://your-ec2-public-ip`にアクセスし、ウェブサイトが表示されることを確認します。

---

## **9. ファイアウォールの設定（任意）**

### **9.1 UFWのインストールと設定**

```bash
sudo apt install -y ufw
sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable
```

---

## **10. ドメイン名とSSLの設定（任意）**

### **10.1 ドメイン名の取得と設定**

- ドメインレジストラでドメインを取得します。

- DNS設定で、ドメインのAレコードをEC2のパブリックIPに設定します。

### **10.2 Let's EncryptでのSSL証明書の取得**

1. Certbotのインストール：

   ```bash
   sudo apt install -y certbot python3-certbot-nginx
   ```

2. SSL証明書の取得：

   ```bash
   sudo certbot --nginx -d your-domain.com
   ```

   - 指示に従って設定を完了します。

---

## **11. まとめと確認**

- 以上で、Ubuntuを使用したAWS EC2環境でのNode.jsサーバの構築と、提供されたReactコードのデプロイが完了しました。

- ブラウザでウェブサイトが正しく表示されることを確認してください。

- 何か不明な点や問題が発生した場合は、お気軽にご質問ください。

---

**注意事項**：

- **セキュリティ**：SSHアクセスを許可するIPアドレスは必要最低限に限定し、不正アクセスを防止します。

- **フォームの送信機能**：現在、`ContactForm`コンポーネントのフォーム送信処理は簡易的なものです。実際にメール送信やデータ保存を行うには、バックエンドの実装が必要です。

- **環境変数の管理**：APIキーなどの機密情報は環境変数で管理し、Gitリポジトリに含めないようにします。

- **SSL証明書の有効期限**：Let's EncryptのSSL証明書は90日間有効です。自動更新を設定するか、期限前に手動で更新してください。

---