0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Last updated at Posted at 2024-10-18

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の場合

Macの場合

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

    xcode-select --install
    

Linuxの場合

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

    sudo apt install -y git
    

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

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

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

    mkdir wago-website
    cd wago-website
    

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

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

    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ディレクトリを作成します。

    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

// 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

// 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

// 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

// 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

// 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

// 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 必要なパッケージのインストール

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

npm install framer-motion lucide-react

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

2.6.1 メインページの作成

src/app/page.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を以下のように編集します。

// 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 アプリケーションの起動

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

npm run dev

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

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

2.7.1 GitHubアカウントの作成

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

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

git init

2.7.3 .gitignoreファイルの作成

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

node_modules
.next
.env

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

git add .
git commit -m "Initial commit"

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

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

  2. リポジトリ名を入力します(例:wago-website)。

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

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

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

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公式サイトにアクセスし、「今すぐ無料で始める」をクリックします。

  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. ターミナルで、キーペアファイルが保存されているディレクトリに移動します。

    cd /path/to/your/keypair
    
  2. キーペアファイルの権限を変更します。

    chmod 400 wagohuaxia-key.pem
    
  3. SSHで接続します。

    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 Nameubuntu@your-ec2-public-ip

    • Port22

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

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


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

5.1 Ubuntuの初期設定

sudo apt update
sudo apt upgrade -y

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

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

インストールの確認:

node -v
npm -v

5.3 Gitのインストール

sudo apt install -y git

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

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

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

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

    git clone https://github.com/あなたのユーザー名/wago-website.git
    
    • 注意あなたのユーザー名を実際のGitHubユーザー名に置き換えてください。
  3. プロジェクトディレクトリに移動します。

    cd wago-website
    

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

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

    npm install
    

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

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

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

    npm run start
    
    • デフォルトでは、ポート3000で起動します。
  3. 動作確認:

    curl http://localhost:3000
    
    • HTMLコードが表示されれば成功です。

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

7.1 PM2のインストール

sudo npm install -g pm2

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

pm2 start npm --name "wagohuaxia" -- start

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

pm2 save
pm2 startup
  • 表示されたコマンドをコピーして実行します。

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

8.1 Nginxのインストール

sudo apt install -y nginx

8.2 Nginxの設定

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

    sudo mv /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak
    
  2. 新しい設定ファイルを作成します。

    sudo nano /etc/nginx/sites-available/default
    
  3. 以下の内容を貼り付けます。

    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の設定をテストします。

    sudo nginx -t
    
  5. Nginxを再起動します。

    sudo systemctl restart nginx
    

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

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

9. ファイアウォールの設定(任意)

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

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のインストール:

    sudo apt install -y certbot python3-certbot-nginx
    
  2. SSL証明書の取得:

    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日間有効です。自動更新を設定するか、期限前に手動で更新してください。


0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?