

# EC2 インスタンスにウェブサーバーをインストールします
<a name="CHAP_Tutorials.WebServerDB.CreateWebServer"></a>

[EC2 インスタンスを起動して DB インスタンスに接続する](CHAP_Tutorials.WebServerDB.LaunchEC2.md) で作成した EC2 インスタンスにウェブサーバーをインストールします。ウェブサーバーは、[「Amazon RDS DB インスタンスの作成」](CHAP_Tutorials.WebServerDB.CreateDBInstance.md) で作成した Amazon RDS DB インスタンスに接続します。

## PHP と MariaDB を使用する Apache ウェブサーバーのインストール
<a name="CHAP_Tutorials.WebServerDB.CreateWebServer.Apache"></a>

EC2 インスタンスに接続し、ウェブサーバーをインストールします。

**EC2 インスタンスに接続し、PHP を使用して Apache ウェブサーバーをインストールするには**

1. 「*Amazon EC2 ユーザーガイド*」の「[Linux インスタンスに接続する](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstances.html)」のステップに従って、先ほど作成した EC2 インスタンスに接続します。

   SSH を使用して EC2 インスタンスに接続することをお勧めします。SSH クライアントユーティリティが Windows、Linux、または Mac にインストールされている場合は、次のコマンド形式でインスタンスに接続できます。

   ```
   ssh -i location_of_pem_file ec2-user@ec2-instance-public-dns-name
   ```

   例えば、`ec2-database-connect-key-pair.pem` が Linux の `/dir1` に保存されていて、EC2 インスタンスのパブリック IPv4 DNS が `ec2-12-345-678-90.compute-1.amazonaws.com` であるとします。SSH コマンドは次のようになります。

   ```
   ssh -i /dir1/ec2-database-connect-key-pair.pem ec2-user@ec2-12-345-678-90.compute-1.amazonaws.com
   ```

1. EC2 インスタンスのソフトウェアを更新して、最新のバグ修正とセキュリティ更新を入手します。これを行うには、次のコマンドを使用します。
**注記**  
`-y` オプションを指定すると、確認メッセージを表示せずに更新をインストールします。インストール前に更新を確認するには、このオプションを省略します。

   ```
   sudo dnf update -y
   ```

1. 更新が完了した後、次のコマンドを使用して、Apache ウェブサーバー、PHP、および MariaDB または PostgreSQL ソフトウェアをインストールします。このコマンドは、複数のソフトウェアパッケージおよび関連する依存関係を同時にインストールします。

------
#### [ MariaDB & MySQL ]

   ```
   sudo dnf install -y httpd php php-mysqli mariadb105
   ```

------
#### [ PostgreSQL ]

   ```
   sudo dnf install -y httpd php php-pgsql postgresql15
   ```

------

   エラーが表示された場合、インスタンスはおそらく Amazon Linux 2023 AMI で起動していません。代わりに Amazon Linux 2 AMI を使用している可能性があります。次のコマンドを使用して、Amazon Linux のバージョンを表示できます。

   ```
   cat /etc/system-release
   ```

   詳細については、「[インスタンスソフトウェアの更新](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/install-updates.html)」を参照してください。

1. 次に示すコマンドを使用してウェブサーバーを起動します。

   ```
   sudo systemctl start httpd
   ```

   ウェブサーバーが正しくインストールされ、起動されているかどうかをテストできます。これを行うには、ウェブブラウザのアドレスバーに EC2 インスタンスのパブリックドメインネームシステム (DNS) 名を入力します (例: `http://ec2-42-8-168-21.us-west-1.compute.amazonaws.com`)。ウェブサーバーが実行中の場合、Apache テストページが表示されます。

   Apache テストページが表示されない場合は、[チュートリアル: DB インスタンスで使用する VPC を作成する (IPv4 専用)](CHAP_Tutorials.WebServerDB.CreateVPC.md) で作成した VPC セキュリティグループのインバウンドルールを確認してください。インバウンドルールに、ウェブサーバーへの接続に使用する IP アドレスに対する HTTP (ポート 80) アクセスを許可するルールが含まれていることを確認します。
**注記**  
Apache テストページは、ドキュメントのルートディレクトリ `/var/www/html` にコンテンツがないときのみ表示されます。ドキュメントルートディレクトリにコンテンツを追加すると、そのコンテンツが EC2 インスタンスのパブリック DNS アドレスに表示されます。これより前では、Apache のテストページに表示されます。

1. `systemctl` コマンドを使用して、システムがブートするたびにウェブサーバーが起動するように設定します。

   ```
   sudo systemctl enable httpd
   ```

`ec2-user` が Apache ウェブサーバーのデフォルトルートディレクトリにあるファイルを管理できるようにするには、`/var/www` ディレクトリの所有権とアクセス許可を変更します。このタスクを行うには、複数の方法があります。このチュートリアルでは、`ec2-user` を `apache` グループに追加し、`apache` ディレクトリの所有権を `/var/www` グループに付与し、グループへの書き込み権限を割り当てます。

**Apache ウェブサーバーのファイルアクセス許可を設定するには**

1. `ec2-user` ユーザーを `apache` グループに追加します。

   ```
   sudo usermod -a -G apache ec2-user
   ```

1. ログアウトしてアクセス許可を更新して新しい `apache` グループを含めます。

   ```
   exit
   ```

1. 再度ログインし、`apache` コマンドを使用して `groups` グループが存在していることを確認します。

   ```
   groups
   ```

   出力は次のようになります。

   ```
   ec2-user adm wheel apache systemd-journal
   ```

1. `/var/www` ディレクトリとそのコンテンツのグループ所有権を `apache` グループに変更します。

   ```
   sudo chown -R ec2-user:apache /var/www
   ```

1. `/var/www` およびそのサブディレクトリのディレクトリアクセス許可を変更して、グループの書き込みアクセス許可を追加し、後で作成するサブディレクトリのグループ ID を設定します。

   ```
   sudo chmod 2775 /var/www
   find /var/www -type d -exec sudo chmod 2775 {} \;
   ```

1. `/var/www` ディレクトリおよびそのサブディレクトリのファイルごとにアクセス許可を繰り返し変更し、グループの書き込みアクセス許可を追加します。

   ```
   find /var/www -type f -exec sudo chmod 0664 {} \;
   ```

これで、`ec2-user` (および `apache` グループの将来のメンバー) は、Apache ドキュメントルートにファイルを追加、削除、編集できるようになります。これにより、静的ウェブサイトや PHP アプリケーションなどのコンテンツを追加できます。

**注記**  
HTTP プロトコルを実行するウェブサーバーは、送受信したデータのトランスポートセキュリティを提供しません。ウェブブラウザを使用して HTTP サーバーに接続すると、ネットワーク経路上のどこからでも、多くの情報が誰でも閲覧できるようになります。この情報には、アクセスした URL、受信したウェブページのコンテンツ、HTML フォームの内容 (パスワードなど) が含まれます。  
ウェブサーバーを保護するためのベストプラクティスとして、HTTPS (HTTP Secure) のサポートをインストールしてください。このプロトコルでは、SSL/TLS を使用してデータを保護します。詳細については、*Amazon EC2 ユーザーガイド*の「[チュートリアル: Amazon Linux AMI を使用した SSL/TLS の設定](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/SSL-on-amazon-linux-ami.html)」を参照してください。

## Apache ウェブサーバーを DB インスタンスに接続する
<a name="CHAP_Tutorials.WebServerDB.CreateWebServer.PHPContent"></a>

次に、Amazon RDS DB インスタンスに接続する Apache ウェブサーバーへのコンテンツを追加します。

**DB インスタンスに接続する Apache ウェブサーバーにコンテンツを追加するには**

1. EC2 インスタンスに接続したまま、ディレクトリを `/var/www` に変更し、`inc` という名前の新しいサブディレクトリを作成します。

   ```
   cd /var/www
   mkdir inc
   cd inc
   ```

1. `inc` という `dbinfo.inc` ディレクトリに新しいファイルを作成し、nano を呼び出して (または任意のテキストエディタで) ファイルを編集します。

   ```
   >dbinfo.inc
   nano dbinfo.inc
   ```

1. `dbinfo.inc` ファイルに次のコンテンツを追加します。ここで、*db\$1instance\$1endpoint* は、DB インスタンス の、ポートのない、DB インスタンスエンドポイントです。
**注記**  
ユーザー名とパスワード情報は、ウェブサーバーのドキュメントルートに含まれていないフォルダに配置することをお勧めします。これにより、セキュリティ情報が公開される可能性が低くなります。  
アプリケーションで `master password` を適切なパスワードに変更してください。

   ```
   <?php
   
   define('DB_SERVER', 'db_instance_endpoint');
   define('DB_USERNAME', 'tutorial_user');
   define('DB_PASSWORD', 'master password');
   define('DB_DATABASE', 'sample');
   ?>
   ```

1. `dbinfo.inc` ファイルを保存して閉じます。nano を使用している場合は、Ctrl\$1S と Ctrl\$1X を使用してファイルを保存して閉じます。

1. ディレクトリを `/var/www/html` に変更します。

   ```
   cd /var/www/html
   ```

1. `html` という `SamplePage.php` ディレクトリに新しいファイルを作成し、nano を呼び出して (または任意のテキストエディタで) ファイルを編集します。

   ```
   >SamplePage.php
   nano SamplePage.php
   ```

1. `SamplePage.php` ファイルに次のコンテンツを追加します。

------
#### [ MariaDB & MySQL ]

   ```
   <?php include "../inc/dbinfo.inc"; ?>
   <html>
   <body>
   <h1>Sample page</h1>
   <?php
   
     /* Connect to MySQL and select the database. */
     $connection = mysqli_connect(DB_SERVER, DB_USERNAME, DB_PASSWORD);
   
     if (mysqli_connect_errno()) echo "Failed to connect to MySQL: " . mysqli_connect_error();
   
     $database = mysqli_select_db($connection, DB_DATABASE);
   
     /* Ensure that the EMPLOYEES table exists. */
     VerifyEmployeesTable($connection, DB_DATABASE);
   
     /* If input fields are populated, add a row to the EMPLOYEES table. */
     $employee_name = htmlentities($_POST['NAME']);
     $employee_address = htmlentities($_POST['ADDRESS']);
   
     if (strlen($employee_name) || strlen($employee_address)) {
       AddEmployee($connection, $employee_name, $employee_address);
     }
   ?>
   
   <!-- Input form -->
   <form action="<?PHP echo $_SERVER['SCRIPT_NAME'] ?>" method="POST">
     <table border="0">
       <tr>
         <td>NAME</td>
         <td>ADDRESS</td>
       </tr>
       <tr>
         <td>
           <input type="text" name="NAME" maxlength="45" size="30" />
         </td>
         <td>
           <input type="text" name="ADDRESS" maxlength="90" size="60" />
         </td>
         <td>
           <input type="submit" value="Add Data" />
         </td>
       </tr>
     </table>
   </form>
   
   <!-- Display table data. -->
   <table border="1" cellpadding="2" cellspacing="2">
     <tr>
       <td>ID</td>
       <td>NAME</td>
       <td>ADDRESS</td>
     </tr>
   
   <?php
   
   $result = mysqli_query($connection, "SELECT * FROM EMPLOYEES");
   
   while($query_data = mysqli_fetch_row($result)) {
     echo "<tr>";
     echo "<td>",$query_data[0], "</td>",
          "<td>",$query_data[1], "</td>",
          "<td>",$query_data[2], "</td>";
     echo "</tr>";
   }
   ?>
   
   </table>
   
   <!-- Clean up. -->
   <?php
   
     mysqli_free_result($result);
     mysqli_close($connection);
   
   ?>
   
   </body>
   </html>
   
   
   <?php
   
   /* Add an employee to the table. */
   function AddEmployee($connection, $name, $address) {
      $n = mysqli_real_escape_string($connection, $name);
      $a = mysqli_real_escape_string($connection, $address);
   
      $query = "INSERT INTO EMPLOYEES (NAME, ADDRESS) VALUES ('$n', '$a');";
   
      if(!mysqli_query($connection, $query)) echo("<p>Error adding employee data.</p>");
   }
   
   /* Check whether the table exists and, if not, create it. */
   function VerifyEmployeesTable($connection, $dbName) {
     if(!TableExists("EMPLOYEES", $connection, $dbName))
     {
        $query = "CREATE TABLE EMPLOYEES (
            ID int(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
            NAME VARCHAR(45),
            ADDRESS VARCHAR(90)
          )";
   
        if(!mysqli_query($connection, $query)) echo("<p>Error creating table.</p>");
     }
   }
   
   /* Check for the existence of a table. */
   function TableExists($tableName, $connection, $dbName) {
     $t = mysqli_real_escape_string($connection, $tableName);
     $d = mysqli_real_escape_string($connection, $dbName);
   
     $checktable = mysqli_query($connection,
         "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME = '$t' AND TABLE_SCHEMA = '$d'");
   
     if(mysqli_num_rows($checktable) > 0) return true;
   
     return false;
   }
   ?>
   ```

------
#### [ PostgreSQL ]

   ```
   <?php include "../inc/dbinfo.inc"; ?>
   
   <html>
   <body>
   <h1>Sample page</h1>
   <?php
   
   /* Connect to PostgreSQL and select the database. */
   $constring = "host=" . DB_SERVER . " dbname=" . DB_DATABASE . " user=" . DB_USERNAME . " password=" . DB_PASSWORD ;
   $connection = pg_connect($constring);
   
   if (!$connection){
    echo "Failed to connect to PostgreSQL";
    exit;
   }
   
   /* Ensure that the EMPLOYEES table exists. */
   VerifyEmployeesTable($connection, DB_DATABASE);
   
   /* If input fields are populated, add a row to the EMPLOYEES table. */
   $employee_name = htmlentities($_POST['NAME']);
   $employee_address = htmlentities($_POST['ADDRESS']);
   
   if (strlen($employee_name) || strlen($employee_address)) {
     AddEmployee($connection, $employee_name, $employee_address);
   }
   
   ?>
   
   <!-- Input form -->
   <form action="<?PHP echo $_SERVER['SCRIPT_NAME'] ?>" method="POST">
     <table border="0">
       <tr>
         <td>NAME</td>
         <td>ADDRESS</td>
       </tr>
       <tr>
         <td>
       <input type="text" name="NAME" maxlength="45" size="30" />
         </td>
         <td>
       <input type="text" name="ADDRESS" maxlength="90" size="60" />
         </td>
         <td>
       <input type="submit" value="Add Data" />
         </td>
       </tr>
     </table>
   </form>
   <!-- Display table data. -->
   <table border="1" cellpadding="2" cellspacing="2">
     <tr>
       <td>ID</td>
       <td>NAME</td>
       <td>ADDRESS</td>
     </tr>
   
   <?php
   
   $result = pg_query($connection, "SELECT * FROM EMPLOYEES");
   
   while($query_data = pg_fetch_row($result)) {
     echo "<tr>";
     echo "<td>",$query_data[0], "</td>",
          "<td>",$query_data[1], "</td>",
          "<td>",$query_data[2], "</td>";
     echo "</tr>";
   }
   ?>
   </table>
   
   <!-- Clean up. -->
   <?php
   
     pg_free_result($result);
     pg_close($connection);
   ?>
   </body>
   </html>
   
   
   <?php
   
   /* Add an employee to the table. */
   function AddEmployee($connection, $name, $address) {
      $n = pg_escape_string($name);
      $a = pg_escape_string($address);
      echo "Forming Query";
      $query = "INSERT INTO EMPLOYEES (NAME, ADDRESS) VALUES ('$n', '$a');";
   
      if(!pg_query($connection, $query)) echo("<p>Error adding employee data.</p>"); 
   }
   
   /* Check whether the table exists and, if not, create it. */
   function VerifyEmployeesTable($connection, $dbName) {
     if(!TableExists("EMPLOYEES", $connection, $dbName))
     {
        $query = "CREATE TABLE EMPLOYEES (
            ID serial PRIMARY KEY,
            NAME VARCHAR(45),
            ADDRESS VARCHAR(90)
          )";
   
        if(!pg_query($connection, $query)) echo("<p>Error creating table.</p>"); 
     }
   }
   /* Check for the existence of a table. */
   function TableExists($tableName, $connection, $dbName) {
     $t = strtolower(pg_escape_string($tableName)); //table name is case sensitive
     $d = pg_escape_string($dbName); //schema is 'public' instead of 'sample' db name so not using that
   
     $query = "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME = '$t';";
     $checktable = pg_query($connection, $query);
   
     if (pg_num_rows($checktable) >0) return true;
     return false;
   
   }
   ?>
   ```

------

1. `SamplePage.php` ファイルを保存して閉じます。

1. ウェブブラウザを開いて `http://EC2 instance endpoint/SamplePage.php` (例: `http://ec2-12-345-67-890.us-west-2.compute.amazonaws.com/SamplePage.php`) を参照することで、ウェブサーバーが正常に DB インスタンスに接続していることを確認します。

`SamplePage.php` を使用して、DB インスタンスにデータを追加できます。これで、追加したデータがこのページに表示されます。データがテーブルに挿入されたことを確認するには、Amazon EC2 インスタンスに MySQL をインストールします。その後、DB インスタンスに接続し、テーブルにクエリを実行します。

MySQL クライアントをインストールして DB インスタンスに接続する方法については、[MySQL DB インスタンスへの接続](USER_ConnectToInstance.md) を参照してください。

DB インスタンス の安全性を高めるために、VPC の外部にある出典が DB インスタンスに接続できないことを確認します。

ウェブサーバーとデータベースのテストが完了したら、DB インスタンスと Amazon EC2 インスタンスを削除する必要があります。
+ DBインスタンスを削除するには、[DB インスタンスを削除する](USER_DeleteInstance.md)の手順に従います。最終的なスナップショットを作成する必要はありません。
+ Amazon EC2 インスタンスを終了するには、*Amazon EC2 ユーザーガイド*の「[インスタンスの終了](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/terminating-instances.html)」の手順に従います。