0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WSL2で簡単なWebアプリを動かしてみる

0
Posted at

はじめに

仮想環境のお勉強がてら、WSL2で仮想環境を作ってその中で簡単なWebアプリを動かしてみたので、どんなことをしたのか書いていこうと思います。

※筆者のOSはWindowsです。また、WSL2がインストールされているのが前提です。

今回作ったもの

言語を選んでボタンを押すと、その言語の挨拶が表示されるだけのアプリです。

  • WSL2を利用したUbuntuの仮想環境
  • Apache2を利用したWebサーバー
  • Node.js + Expressを利用したAPIサーバー
  • MySQLを利用したデータベース
    構成としては、すべてUbuntu環境の中で完結しています。
[Windowsのブラウザ]
        │ http://localhost
        ▼
┌─────────────────────────────────┐
│ Ubuntu (WSL2)                    │
│                                  │
│  Apache2 (:80)                   │
│   └ /var/www/html/index.html     │
│        │ fetch                   │
│        ▼                         │
│  Express (:3000)                 │
│        │ SQL                     │
│        ▼                         │
│  MySQL (:3306)                   │
└─────────────────────────────────┘

WindowsのブラウザからWSL2内のApacheに http://localhost でアクセスできるのは、WSL2のlocalhostフォワーディング機能のおかげです。特別なポート設定は不要でした。

作業の流れ

  1. WSL2でUbuntuの仮想環境を作成
  2. Apache2をインストール
  3. /var/www/html/index.html を書き換える
  4. /var/www/html/js/greet.js を作成
  5. MySQLをインストール
  6. テーブルを定義する
  7. Node.jsとExpressをインストール
  8. ~/express-app/app.js を作成
  9. localhostからWebアプリを触る

それぞれの作業を詳しく

WSL2でUbuntuの仮想環境を作成

ターミナルを開き、以下のwslコマンドでUbuntu環境を作成します。
インストールの際にデフォルトのユーザーアカウントを作成するので、任意の名前とパスワードを設定します。

wsl --install -d Ubuntu

Apache2をインストール

Ubuntu環境に入れたら、Apache2をインストールします。

sudo apt update
sudo apt install -y apache2

apt update でインストールできるパッケージの最新リストを取得し、apt install -y apache2 でApache2をインストールします。

インストール後、サービスを起動します。

sudo service apache2 start

WSL2ではsystemdが有効になっていない場合があり、その場合 systemctl ではなく service コマンドを使います。また、WSLを再起動するとサービスは停止するので、都度起動が必要です。

この時点で http://localhost にアクセスすると、Apacheのデフォルトページが表示されます。

/var/www/html/index.html を書き換える

デフォルトルートのindex.htmlを今回用に書き換えます。以下のコマンドでvimで開きます。

sudo vi /var/www/html/index.html

内容を以下のように書き換えます。greet.js については次に記載します。

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>挨拶アプリ</title>
  </head>
  <body>
    <h3>挨拶アプリ</h3>
    <select name="greetings" id="greet-select">
      <option value="ja">日本語</option>
      <option value="en">英語</option>
      <option value="ch">中国語</option>
    </select>
    <button id="greet-button" onclick="pushButton(document.getElementById('greet-select').value)">挨拶する</button>
    <br>
    <div id="result"></div>
    <script src="/js/greet.js"></script>
  </body>
</html>

日本語や中国語を表示するので、<meta charset="UTF-8"> の指定を忘れないようにします。これがないと文字化けします。

/var/www/html/js/greet.js を作成

以下のコマンドで js ディレクトリを作成し、greet.js を作成します。

cd /var/www/html && sudo mkdir js
cd js && sudo touch greet.js

vimで開きます。

sudo vi greet.js

以下の内容を記述します。
※後で作成するAPIをfetchしているところがありますが気になさらず……

greet.js
const pushButton = async (lang) => {
    const response = await fetch(`http://localhost:3000/?lang=${lang}`);
    const results = await response.json();
    document.getElementById('result').innerHTML = `<h3>${results[0].word}</h3>`;
};

APIは配列でレコードを返すので、results[0] で先頭のレコードを取り出し、word カラムの値を表示しています。

MySQLをインストール

以下のコマンドでMySQLをインストールし、サービスを起動します。

sudo apt install -y mysql-server
sudo service mysql start

インストールが完了したらrootユーザーでMySQLに入ります。

sudo mysql -u root

テーブルを定義する

以下のコマンドでデータベースとテーブルを作成し、挨拶データを登録します。

CREATE DATABASE greeting_database;
USE greeting_database;
 
CREATE TABLE greetings (
    id INT NOT NULL AUTO_INCREMENT,
    lang VARCHAR(10) NOT NULL,
    word VARCHAR(100) NOT NULL,
    PRIMARY KEY (id)
);
 
INSERT INTO greetings (lang, word) VALUES
  ('ja', 'こんにちは'),
  ('en', 'Hello'),
  ('ch', '你好');

id はAUTO_INCREMENTなので、INSERTの際は指定しなくても自動で採番されます。

続いて、アプリから接続するための専用ユーザーを作成します。

CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT ON greeting_database.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;

UbuntuのMySQLはrootユーザーが auth_socket 認証になっているため、Node.jsからrootで接続しようとすると失敗することがあります。また、アプリからrootで接続するのはセキュリティ的にも避けたいので、専用ユーザーを作るのが確実です。

exit でMySQLを抜けます。

Node.jsとExpressをインストール

まずNode.jsとnpmをインストールします。

sudo apt install -y nodejs npm
node -v
npm -v

次にExpress用のディレクトリを作成し、プロジェクトを初期化して package.json を生成します。

mkdir ~/express-app
cd ~/express-app
npm init -y

sudo を付けずに作成するのがポイントです。sudoで作るとディレクトリの所有者がrootになり、後の npm install が権限エラーになります。

今回使用する expresscorsmysql2 をインストールします。

npm install express cors mysql2

~/express-app/app.js を作成

express-app 配下に app.js を作成し、中身を記述します。

touch app.js
vi app.js

内容は以下です。

app.js
const express = require('express');
const cors = require('cors');
const mysql = require('mysql2');
 
const app = express();
app.use(cors());
 
// コネクションプールを作成
const pool = mysql.createPool({
    host: 'localhost',
    user: 'appuser',
    password: 'password',
    database: 'greeting_database'
});
 
// ルートエンドポイントの設定
app.get('/', (req, res) => {
    pool.query(
        'SELECT * FROM greetings WHERE lang = ?',
        [req.query.lang],
        (error, results) => {
            if (error) {
                res.status(500).json({ error: error.message });
                return;
            }
            res.status(200).json(results);
        }
    );
});
 
// サーバーの起動
const PORT = 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

ポイントは3つあります。

app.use(cors()) はルート定義より前に書く
Webページはポート80(Apache)、APIはポート3000で動いているため、ブラウザからは別オリジン扱いになりCORSエラーになります。corsミドルウェアで許可しますが、ミドルウェアは上から順に適用されるので、app.get() より後ろに書くと効きません。

SQLは値を直接埋め込まない
WHERE lang = ? のようにプレースホルダを使い、値は配列で渡します。文字列連結で組み立てるとSQLインジェクションの原因になります。

コネクションはプールで管理する
リクエストのたびに createConnection すると、接続が閉じられずに溜まっていきます。createPool を使うと接続を使い回してくれるので、この心配がありません。

localhostからWebアプリを触る

あとは動かすだけです。以下のコマンドでNodeサーバーを起動します。

cd ~/express-app
node app.js

Server is running on port 3000 と表示されたら起動成功です。

localhostにアクセスしてみます。

image.png

続いて、言語を選択して挨拶するボタンを押してみます。

image.png

英語であいさつしてくれました!ちゃっちいアプリですが、動いてくれると嬉しいですね。

うまく動かない場合は、ブラウザの開発者ツール(F12)のコンソールとネットワークタブを見ると原因がわかりやすいです。「blocked by CORS policy」ならCORS設定、http://localhost:3000/?lang=ja へのリクエストが失敗しているならNodeサーバーかMySQLの起動状況を確認してみてください。

最後に

Webサーバー、APIサーバー、DBサーバーを仮想環境で動かす基礎的なところが学べた気がします。
次はDockerを使って3コンテナ作って実装してみようと思います。

参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?