20201028のNode.jsに関する記事は12件です。

アレクサでライトやエアコンをコントロールしましょう(まだできない)

モチベーション

最近、プロトアウトでIoTに関する授業を受けました。メインはObnizで、いくつかセンサーやアクチュエータを試しました。授業の内容を復習のため、何か面白いことを作ろうと思いました。
みんなさんは眠いのに、ライトのリモコンを見つけられなかったことがありますか。その時、拍手でライトをオンにできると、いいじゃないですか。それで、今回、obnizでリモコンの信号を模倣してライトやエアコンをコントロールする制作を作りたいと思います。

概要

そんな制作を作るために、2つ部分が必要です。1番目はデバイス(エアコンやライト)のコントロールする部分です。
2番目は人間のコマンドを認識する部分です。

リモコンのしくみ

リモコンは赤外線もしくはラジオで動いています。うちのリモコンは赤外線(以下はIRとする)のほうです。
IRリモコン(送信機)は、特定のバイナリコードを表す赤外線のパルスを送信します。 これらのバイナリコードは、電源オン/オフや音量アップなどのコマンドに対応しています。 TV、ステレオ、またはその他のデバイスのIRレシーバーは、光のパルスをデバイスのマイクロプロセッサーが理解できるバイナリデータ(1と0)にデコードします。 次に、マイクロプロセッサは対応するコマンドを実行します。(ソース)
リモコン側はIR LEDがあって、デバイスのほうはIRレシーバー(IRセンサー)があります。

image.png

リモコンの種類ごとに異なる種類のバイナリコードを使用するため、まず、IRレシーバーでリモコンのバイナリコードを検出しないといけません。それから、そのバイナリコードをコピーしてobnizでデバイスに通信します。

人間のインプット

obnizは音センサー(CN07)で回りの音を聞いて、もし音の大きさはある値より大きく場合は拍手と判定します。

image.png

ただ、センサーを購入した時、音声センサーが忘れてしまいました。もちろん再購入するのは問題ないですが、家にアマゾンエコーがあるので、「アレクサ、エアコンをつけて」や「アレクサ、僕はねたい」などの音声でコントロールするのはもっと面白いじゃないですね。

だから、やりたいことは少し変更しました。人間のコマンドは拍手でなく、音声です。
image.png

必要もの:
+ obniz
+ アレクサ(アマゾンエコーもしくはスマートフォン)
+ AWSアカウント
+ IR センサー(OSRB38C9AA)
+ IR LED(OSI5FU5111C)

実装

計画:
1. IRセンサーでリモコンの信号を受けて信号のバイナリコードを分析する
2. 受けたバイナリコードを記入する(例えば:ライトオン:[1,1,0,....], ライトオフ:[1,0,0,...], エアコンオン:[1,1,1,...])
3. obnizをコントロールするアレクサのスキルを作成する
4. コマンドによってobnizがIRLEDで2番のバイナリコードをデバイスに送る

IRセンサーのバイナリコード

iOS の画像.jpg
IRセンサーをobnizに接続してみて、バイナリコードを読み込みました。

var sensor = obniz.wired('IRSensor', {vcc:0, gnd:1, output: 2});
sensor.duration = 130;
sensor.start(function (arr) {
  console.log(JSON.stringify(arr));
})

バイナリコードはarrにあります。例えば:

[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

ただ、問題が発生しました。同じボータンを押したのに、結果は毎回違います。バイナリコードをコピーしてIR LEDを送ってみたが、ライトは受けられないみたいです。

image.png

赤外線リモコンの種類

赤外線リモコンは、900nm帯の赤外線をキャリアとして利用した無線制御システムで、家電製品には当たり前のように使われています。よく利用される通信フォーマットには主に、NEC/家製協/SONYフォーマットがあり、これら3種類で日本国内の殆どの家電をカバーします(ソース)。その3種類の中、実際の結果に比べて一番近くパータンは家製協(AEHA)フォーマットです。
image.png

ただ、そのパータンを適用しても、結果はまだパラパラです。

ノイズ

今回はビット単位で送受信信号を使用しているので、ノイズの影響を受けやすいです。残念ながら、今の状態はどうやってこのノイズを対応するのかわからないです。
今後、解決できると、ぜひ記事をアップデートします。

================================================================================================================

アップデート:解決できました

↑の問題はやはりノイズです。実際の環境は完璧ではないので、ノイズ避けられないです。ただ、ライトやエアコンのセンサーはノイズがあっても信号を受けてコマンドを理解できます。
だとすれば、なぜテストした時、受けられないですか?それは間隔の問題です。IR LEDについて具体的に話しましょう。

IR LED

irled.JPG

以上の写真はうちのライトリモコンのIR LEDです。活躍範囲は5mぐらいです。

ただ、買ったIR LEDの活躍範囲は10~20㎝ぐらのため、ライトのセンサーに近く持って行かないと動かないです。一つ解決方法はオペアンプ(増幅器。例えば:2n2222)で発動範囲を拡張します。いったん、オペアンプがない状態で進めます。
ObnizとIR Led参考:https://obniz.com/sdk/parts/InfraredLED/README.md

アレクサスキル

image.png

アレクサとObnizと連携

結果

残念のため、最初のステップはまだできていない状態です。
実装するのは難しいですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Computeインスタンス上にNode.jsのWebアプリケーション環境を構成して、MySQL Database ServiceのDBシステムにアクセスしてみた

はじめに

Computeインスタンス上に構成したNode.jsのWebアプリケーションから、MySQL Database ServiceのDBシステムにアクセスしてみた時の手順です。
(2020年10月現在)

構築イメージ

スクリーンショット 2020-10-28 19.50.40.png

作業の流れ

1.VCNの構成
2.ネットワーク・セキュリティ・グループの作成
3.MySQL DBシステムの作成
4.Computeインスタンス(APサーバ)の作成
5.パブリックIPの作成
6.ComputeインスタンスへのパブリックIPの割り当て
7.MySQLクライアントのインストールと設定
8.Node.jsのインストールと設定
9.firewalldの設定
10.SELinuxの設定
11.MySQL DBシステムの接続情報の確認
12.アプリケーションで使用するDBの準備
13.Node.jsアプリケーションの作成
14.Node.jsアプリケーションの動作確認

1.VCNの構成

こちらの記事を参考に、仮想クラウド・ネットワークを構成します。

OCIのネットワークを構成する際に手戻りの少ない手順を考えてみる(初心者向け)

ここでは、以下の理由からMySQL DBシステムを独立したプライベート・サブネットに配置します。
・MySQL DBシステムはプライベート・エンドポイントのみを持つ。
・MySQL DBシステムにはネットワーク・セキュリティ・グループを適用できない。

そのため、参考記事のネットワーク構成に対して、以下の部分を変更します。

・Subnet2のセキュリティ・リスト(Security List for Subnet2)
APサーバを配置するサブネット(Subnet1:10.0.1.0/24)からのみ、MySQLへの接続で使用するTCP 3306、33060へのアクセスを許可します。

「コンソールメニュー」 → 「ネットワーキング」 → 「仮想クラウド・ネットワーク」 
 → 「仮想クラウドネットワークの詳細」 → 「セキュリティ・リスト」

「セキュリティ・リストの作成」をクリック
 ・ 名前:Security List for Subnet2
 ・コンパートメントに作成:「Compartment1」を選択
  ・「+追加のイングレス・ルール」をクリック
   ・ステートレス:チェックをオフ(デフォルト)
   ・ソース・タイプ:「CIDR」を選択
   ・ソースCIDR:10.0.1.0/24
   ・IPプロトコル:「TCP」を選択
   ・ソース・ポート範囲:入力しない
   ・宛先ポート範囲:3306
  ・「+追加のイングレス・ルール」をクリック
   ・ステートレス:チェックをオフ(デフォルト)
   ・ソース・タイプ:「CIDR」を選択
   ・ソースCIDR:10.0.1.0/24
   ・IPプロトコル:「TCP」を選択
   ・ソース・ポート範囲:入力しない
   ・宛先ポート範囲:33060
  ・「+追加のエグレス・ルール」をクリック
   ・ステートレス:チェックをオフ(デフォルト)
   ・宛先タイプ:「CIDR」を選択
   ・宛先CIDR:0.0.0.0/0
   ・IPプロトコル:「全てのプロトコル」を選択」
 ・「セキュリティ・リストの作成」をクリック

2.ネットワーク・セキュリティ・グループの作成

今回作成するNode.jsアプリケーションでTCP 8080でリクエストを受けるので、すべての場所からTCP 8080へのアクセスを許可するネットワーク・セキュリティ・グループを作成します。

「コンソールメニュー」 → 「ネットワーキング」 → 「仮想クラウド・ネットワーク」 → 「仮想クラウドネットワークの詳細」 → 「ネットワーク・セキュリティ・グループ」

「ネットワーク・セキュリティ・グループの作成」をクリック
 ・名前:Network Security Group for AP
 ・コンパートメントに作成:「Compartment1」を選択
 ・「次」をクリック
 ・セキュリティ・ルールの追加
  ルール
   ステートレス:チェックをオフ(デフォルト)
   方向:「イングレス」を選択
   ソースタイプ:「CIDR」を選択
   ソース:0.0.0.0/0
   IPプロトコル:「TCP」を選択
   ソース・ポート範囲:デフォルトのまま(入力しない)
   宛先ポート範囲:8080
  説明:Security Rule for TCP 8080 **
 ・
「作成」をクリック**

3.MySQL DBシステムの作成

「コンソールメニュー」 → 「MySQL」 → 「DBシステム」

・「MySQL DBシステムの作成」をクリック

 DBシステムの基本情報情報
 ・コンパートメントの選択:「Compartment1」を選択
 ・DBシステムの名前の指定:MySQL1
 ・可用性ドメインの選択:任意の可用性ドメインを選択
 ・フォルト・ドメインの選択:任意のフォルト・ドメインを選択
 ・シェイプの選択:任意のシェイプを選択
 ・データ・ストレージ・サイズ(GB):任意のサイズを入力
 ・メンテナンス・ウィンドウの開始時間:入力しない
 ・「次」をクリック

 データベースの基本情報の指定
 ・管理者資格証明の作成
  ・ユーザー名:admin
  ・パスワード:Demo#1Demo#1
  ・パスワードの確認:Demo#1Demo#1
 ・ネットワーク情報の指定
  ・仮想クラウドネットワーク:「VCN1」を選択
  ・サブネット:「Subnet2」を選択
  ・ホスト名:mysql1
  ・MySQLポート:3306(デフォルト)
  ・MYSQL Xプロトコル・ポート:33060(デフォルト)
  ・「次」をクリック

 DBシステム・バックアップの基本情報の指定
 ・バックアップの構成
  ・自動バックアップの有効化:チェックをオン(デフォルト)
  ・バックアップ保持期間:7(デフォルト)
  ・バックアップ・ウィンドウの開始時間:デフォルト・バックアップ・ウィンドウ(デフォルト)
 
  ・「作成」をクリック

4.Computeインスタンス(APサーバ)の作成

「コンソールメニュー」 → 「コンピュート」 → 「インスタンス」

・「インスタンスの作成」をクリック
 ・名前:AP1
 ・コンパートメントに作成:「Compartment1」を選択

 ・配置とハードウェアの構成
  ・可用性ドメイン:任意のADを選択
  ・イメージ:「Oracle Linux 7.8」を選択
  ・シェイプ:任意のシェイプを選択

 ・ネットワーキングの構成 
  ・ネットワーク:「既存の仮想クラウド・ネットワークを選択」を選択し、「VCN1」を選択
  ・サブネット:「既存のサブネット」を選択し、「Subnet 1」を選択
  ・ネットワーク・セキュリティ・グループを使用してトラフィックを制御:チェックをオン
  ・ネットワーク・セキュリティ・グループ:「Network Security Group for AP」を選択
  ・パブリックIPアドレス:「パブリックIPアドレスを割り当てないでください」を選択
 
 ・SSHキーの追加
  ・「公開キー・ファイルの選択」を選択し、「または場所を参照します」をクリックして公開キー・ファイルをアップロードします
 
 ・ブートボリュームの構成
  ・全てデフォルトのまま

 ・「拡張オプションの表示」をクリック
  ・「管理」タブ
   ・全てデフォルトのまま
  ・「ネットワーキング」タブ
   ・プライベートIPアドレス:10.0.1.100
   ・ホスト名:ap1
   ・起動オプション:デフォルトのまま
  ・「イメージ」タブ
   ・デフォルトのまま
  ・「配置」タブ
   ・デフォルトのまま
「作成」をクリック

5.パブリックIPの作成

「コンソールメニュー」 → 「ネットワーキング」 → 「IP Management」

「パブリックIPアドレスの予約」をクリック

 ・予約済パブリックIPアドレス名:PublicIP1
 ・コンパートメントに作成:「Compartment1」を選択
 ・IPアドレスのソース:「Oracle」を選択

 ・「パブリックIPアドレスの予約」をクリック

6.ComputeインスタンスへのパブリックIPの割り当て

「コンソールメニュー」 → 「コンピュート」 → 「インスタンス」 → 「インスタンスの詳細」

・リソース欄の「アタッチされたVNIC」をクリック
VNIC名(AP1)をクリック
・リソース欄の「IPアドレス」をクリック
IPアドレスの欄の「:」をクリックし、「編集」をクリック
 ・パブリックIPタイプ:「予約済パブリックIP」を選択
 ・「既存の予約済パブリックIPの選択」を選択
 ・RESERVED IP ADDRESS:「PublicIP1」を選択
「更新」をクリック

7.MySQLクライアントのインストールと設定

秘密鍵を使って、SSHクライアントからComputeインスタンス(AP1)にopcユーザでログインします。

タイムゾーンとロケールを設定します。

sudo timedatectl set-timezone Asia/Tokyo
sudo localectl set-locale LANG=ja_JP.utf8

yumコマンドでMySQLクライアントをインストールします。

sudo yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
sudo yum install -y mysql-community-client

8.Node.jsのインストールと設定

yumコマンドでNode.jsインストールをインストールします。

sudo yum install -y oracle-release-el7 oracle-nodejs-release-el7
sudo yum install -y --disablerepo=ol7_developer_EPEL nodejs

npmコマンドで使用するNode.jsモジュール(expressフレームワーク、ejs)をインストールします。

sudo npm install -g --save express-generator
sudo npm install -g --save ejs

9.firewalldの設定

firewall-cmdコマンドでfirewalldにTCP8080の通信を許可する設定を追加します。

sudo firewall-cmd --add-port 8080/tcp --zone=public --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-all --zone=public

10.SELinuxの設定

SELinuxの設定を変更します。

sudo setenforce 0

再起動後にSELinuxが有効にならないように設定ファイルを変更します。

sudo vi /etc/selinux/config
/etc/selinux/config
SELINUX=enforcing

の部分を以下のように変更して保存します。

/etc/selinux/config
SELINUX=permissive

11.MySQL DBシステムの接続情報の確認

「コンソール」 → 「MySQL DBシステム」 → 「MySQL DBシステム」

リソース欄の「エンドポイント」をクリックし、MySQL DBシステムのエンドポイント(ホスト、ポート)を確認します。
スクリーンショット 2020-10-28 21.00.05.png

12.アプリケーションで使用するDBの準備

DB接続情報を含む、MySQLクライアントの設定ファイルを作成します。

vi /home/opc/.my.cnf
/home/opc/.my.cnf
[client]
user=admin
password="Demo#1Demo#1"
host="mysql1.subnet2.vcn1.oraclevcn.com"

mysqlコマンドででMySQLに接続に接続します。

mysql

アプリケーションで使用するDBを作成します。

mysql> CREATE DATABASE testdb;

アプリケーションで使用するDBユーザを作成します。

mysql> CREATE USER 'test' IDENTIFIED BY 'Demo#1Demo#1';

アプリケーションで使用するDBユーザに権限を付与します。

mysql> GRANT ALL ON testdb.* TO 'test';

アプリケーションで使用するDBに接続します。

mysql> USE testdb

アプリケーションで使用するテーブルを作成します。

mysql> CREATE TABLE dept (
    -> deptno INT ,
    -> dname VARCHAR(14),
    -> loc VARCHAR(13) ,
    -> PRIMARY KEY  (deptno) 
    -> );

アプリケーションで使用するテーブルにデータを挿入します。

mysql> INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK');
mysql> INSERT INTO dept VALUES (20,'RESEARCH','DALLAS');
mysql> INSERT INTO dept VALUES (30,'SALES','CHICAGO');
mysql> INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON');
mysql> COMMIT;

アプリケーションで使用するテーブルのデータを確認します。

mysql> SELECT * FROM dept;
+--------+------------+----------+
| deptno | dname      | loc      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

mysqlコマンドを終了します。

mysql> exit

13.Node.jsアプリケーションの作成

今回はexpressフレームワークを使用してNode.jsアプリケーションを作成します。

opcユーザのホームディレクトリ直下に、expressコマンドでNode.jsアプリケーション環境を作成します。

cd /home/opc
express --view=ejs app

アプリケーション環境のディレクトリに移動し、npmコマンドで依存関係のあるモジュールをインストールします。

cd app
npm install

npmコマンドでMySQLにアクセスするために使用する@mysql/xdevapiモジュールをインストールします。

npm install --save @mysql/xdevapi 

app.jsを編集します。

vi /home/opc/app/app.js

末尾に以下の内容を追加します。

/home/opc/app/app.js
app.listen(8080);

routes/index.jsを編集します。

vi /home/opc/app/routes/index.js

以下の内容に書き換えます。

/home/opc/app/routes/index.js
var express = require('express');
var mysqlx = require('@mysql/xdevapi');
var router = express.Router();
var os = require('os');

mysqlx
  .getSession({
   user: 'test',
   password: 'Demo#1Demo#1',
   host: 'mysql1.subnet2.vcn1.oraclevcn.com',
   port: '33060'
   })
    .then(function (session) {
      var db = session.getSchema('testdb');
      var myTable = db.getTable('dept');
      var rows =  myTable
         .select()
         .execute()
         .then(res => {
           dept = res.fetchAll();
           hostname = os.hostname();
           console.log(dept);
           console.log(hostname);
         });
      router.get('/', function(req, res, next) {
        res.render('index',{dept: dept, hostname: hostname});
      });
    })
    .catch(function (err) {
       console.log('error: ' + err.stack);
            return;
    });

module.exports = router;

views/index.ejsを編集します。

vi /home/opc/app/views/index.ejs

以下の内容に書き換えます。

/home/opc/app/views/index.ejs
<html>
<head>
<meta charset="UTF-8">
<title>Node.js to MySQL DS Connection Test</title>
</head>
<body>
<table border='1'>
<caption>DEPT Table</caption>
<tr><th>Dept No.</th><th>Dept Name</th><th>Location</th></tr>
  <% dept.forEach(function(deptItem) { %>
    <tr>
    <td><%- deptItem[0] %></td>
    <td><%- deptItem[1] %></td>
    <td><%- deptItem[2] %></td>
    </tr>
  <% }); %>
</table><br>
Response from <%- hostname %>
</body>
</html>

14.Node.jsアプリケーションの動作確認

nodeコマンドでアプリケーションを実行します。

cd /home/opc/app
node app.js

PCのブラウザからアクセスして、アプリケーションの動作を確認します。

http://<AP1のグローバルIP>:8080

スクリーンショット 2020-10-28 21.21.13.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Computeインスタンス上にNode.jaのWebアプリケーション環境を構成して、MySQL Database ServiceのDBシステムにアクセスしてみた

はじめに

Computeインスタンス上に構成したNode.jsのWebアプリケーションから、MySQL Database ServiceのDBシステムにアクセスしてみた時の手順です。
(2020年10月現在)

構築イメージ

スクリーンショット 2020-10-28 19.50.40.png

作業の流れ

1.VCNの構成
2.ネットワーク・セキュリティ・グループの作成
3.MySQL DBシステムの作成
4.Computeインスタンス(APサーバ)の作成
5.パブリックIPの作成
6.ComputeインスタンスへのパブリックIPの割り当て
7.MySQLクライアントのインストールと設定
8.Node.jsのインストールと設定
9.firewalldの設定
10.SELinuxの設定
11.MySQL DBシステムの接続情報の確認
12.アプリケーションで使用するDBの準備
13.Node.jsアプリケーションの作成
14.Node.jsアプリケーションの動作確認

1.VCNの構成

こちらの記事を参考に、仮想クラウド・ネットワークを構成します。

OCIのネットワークを構成する際に手戻りの少ない手順を考えてみる(初心者向け)

ここでは、以下の理由からMySQL DBシステムを独立したプライベート・サブネットに配置します。
・MySQL DBシステムはプライベート・エンドポイントのみを持つ。
・MySQL DBシステムにはネットワーク・セキュリティ・グループを適用できない。

そのため、参考記事のネットワーク構成に対して、以下の部分を変更します。

・Subnet2のセキュリティ・リスト(Security List for Subnet2)
APサーバを配置するサブネット(Subnet1:10.0.1.0/24)からのみ、MySQLへの接続で使用するTCP 3306、33060へのアクセスを許可します。

「コンソールメニュー」 → 「ネットワーキング」 → 「仮想クラウド・ネットワーク」 
 → 「仮想クラウドネットワークの詳細」 → 「セキュリティ・リスト」

「セキュリティ・リストの作成」をクリック
 ・ 名前:Security List for Subnet2
 ・コンパートメントに作成:「Compartment1」を選択
  ・「+追加のイングレス・ルール」をクリック
   ・ステートレス:チェックをオフ(デフォルト)
   ・ソース・タイプ:「CIDR」を選択
   ・ソースCIDR:10.0.1.0/24
   ・IPプロトコル:「TCP」を選択
   ・ソース・ポート範囲:入力しない
   ・宛先ポート範囲:3306
  ・「+追加のイングレス・ルール」をクリック
   ・ステートレス:チェックをオフ(デフォルト)
   ・ソース・タイプ:「CIDR」を選択
   ・ソースCIDR:10.0.1.0/24
   ・IPプロトコル:「TCP」を選択
   ・ソース・ポート範囲:入力しない
   ・宛先ポート範囲:33060
  ・「+追加のエグレス・ルール」をクリック
   ・ステートレス:チェックをオフ(デフォルト)
   ・宛先タイプ:「CIDR」を選択
   ・宛先CIDR:0.0.0.0/0
   ・IPプロトコル:「全てのプロトコル」を選択」
 ・「セキュリティ・リストの作成」をクリック

2.ネットワーク・セキュリティ・グループの作成

今回作成するNode.jsアプリケーションでTCP 8080でリクエストを受けるので、すべての場所からTCP 8080へのアクセスを許可するネットワーク・セキュリティ・グループを作成します。

「コンソールメニュー」 → 「ネットワーキング」 → 「仮想クラウド・ネットワーク」 → 「仮想クラウドネットワークの詳細」 → 「ネットワーク・セキュリティ・グループ」

「ネットワーク・セキュリティ・グループの作成」をクリック
 ・名前:Network Security Group for AP
 ・コンパートメントに作成:「Compartment1」を選択
 ・「次」をクリック
 ・セキュリティ・ルールの追加
  ルール
   ステートレス:チェックをオフ(デフォルト)
   方向:「イングレス」を選択
   ソースタイプ:「CIDR」を選択
   ソース:0.0.0.0/0
   IPプロトコル:「TCP」を選択
   ソース・ポート範囲:デフォルトのまま(入力しない)
   宛先ポート範囲:8080
  説明:Security Rule for TCP 8080 **
 ・
「作成」をクリック**

3.MySQL DBシステムの作成

「コンソールメニュー」 → 「MySQL」 → 「DBシステム」

・「MySQL DBシステムの作成」をクリック

 DBシステムの基本情報情報
 ・コンパートメントの選択:「Compartment1」を選択
 ・DBシステムの名前の指定:MySQL1
 ・可用性ドメインの選択:任意の可用性ドメインを選択
 ・フォルト・ドメインの選択:任意のフォルト・ドメインを選択
 ・シェイプの選択:任意のシェイプを選択
 ・データ・ストレージ・サイズ(GB):任意のサイズを入力
 ・メンテナンス・ウィンドウの開始時間:入力しない
 ・「次」をクリック

 データベースの基本情報の指定
 ・管理者資格証明の作成
  ・ユーザー名:admin
  ・パスワード:Demo#1Demo#1
  ・パスワードの確認:Demo#1Demo#1
 ・ネットワーク情報の指定
  ・仮想クラウドネットワーク:「VCN1」を選択
  ・サブネット:「Subnet2」を選択
  ・ホスト名:mysql1
  ・MySQLポート:3306(デフォルト)
  ・MYSQL Xプロトコル・ポート:33060(デフォルト)
  ・「次」をクリック

 DBシステム・バックアップの基本情報の指定
 ・バックアップの構成
  ・自動バックアップの有効化:チェックをオン(デフォルト)
  ・バックアップ保持期間:7(デフォルト)
  ・バックアップ・ウィンドウの開始時間:デフォルト・バックアップ・ウィンドウ(デフォルト)
 
  ・「作成」をクリック

4.Computeインスタンス(APサーバ)の作成

「コンソールメニュー」 → 「コンピュート」 → 「インスタンス」

・「インスタンスの作成」をクリック
 ・名前:AP1
 ・コンパートメントに作成:「Compartment1」を選択

 ・配置とハードウェアの構成
  ・可用性ドメイン:任意のADを選択
  ・イメージ:「Oracle Linux 7.8」を選択
  ・シェイプ:任意のシェイプを選択

 ・ネットワーキングの構成 
  ・ネットワーク:「既存の仮想クラウド・ネットワークを選択」を選択し、「VCN1」を選択
  ・サブネット:「既存のサブネット」を選択し、「Subnet 1」を選択
  ・ネットワーク・セキュリティ・グループを使用してトラフィックを制御:チェックをオン
  ・ネットワーク・セキュリティ・グループ:「Network Security Group for AP」を選択
  ・パブリックIPアドレス:「パブリックIPアドレスを割り当てないでください」を選択
 
 ・SSHキーの追加
  ・「公開キー・ファイルの選択」を選択し、「または場所を参照します」をクリックして公開キー・ファイルをアップロードします
 
 ・ブートボリュームの構成
  ・全てデフォルトのまま

 ・「拡張オプションの表示」をクリック
  ・「管理」タブ
   ・全てデフォルトのまま
  ・「ネットワーキング」タブ
   ・プライベートIPアドレス:10.0.1.100
   ・ホスト名:ap1
   ・起動オプション:デフォルトのまま
  ・「イメージ」タブ
   ・デフォルトのまま
  ・「配置」タブ
   ・デフォルトのまま
「作成」をクリック

5.パブリックIPの作成

「コンソールメニュー」 → 「ネットワーキング」 → 「IP Management」

「パブリックIPアドレスの予約」をクリック

 ・予約済パブリックIPアドレス名:PublicIP1
 ・コンパートメントに作成:「Compartment1」を選択
 ・IPアドレスのソース:「Oracle」を選択

 ・「パブリックIPアドレスの予約」をクリック

6.ComputeインスタンスへのパブリックIPの割り当て

「コンソールメニュー」 → 「コンピュート」 → 「インスタンス」 → 「インスタンスの詳細」

・リソース欄の「アタッチされたVNIC」をクリック
VNIC名(AP1)をクリック
・リソース欄の「IPアドレス」をクリック
IPアドレスの欄の「:」をクリックし、「編集」をクリック
 ・パブリックIPタイプ:「予約済パブリックIP」を選択
 ・「既存の予約済パブリックIPの選択」を選択
 ・RESERVED IP ADDRESS:「PublicIP1」を選択
「更新」をクリック

7.MySQLクライアントのインストールと設定

秘密鍵を使って、SSHクライアントからComputeインスタンス(AP1)にopcユーザでログインします。

タイムゾーンとロケールを設定します。

sudo timedatectl set-timezone Asia/Tokyo
sudo localectl set-locale LANG=ja_JP.utf8

yumコマンドでMySQLクライアントをインストールします。

sudo yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
sudo yum install -y mysql-community-client

8.Node.jsのインストールと設定

yumコマンドでNode.jsインストールをインストールします。

sudo yum install -y oracle-release-el7 oracle-nodejs-release-el7
sudo yum install -y --disablerepo=ol7_developer_EPEL nodejs

npmコマンドで使用するNode.jsモジュール(expressフレームワーク、ejs)をインストールします。

sudo npm install -g --save express-generator
sudo npm install -g --save ejs

9.firewalldの設定

firewall-cmdコマンドでfirewalldにTCP8080の通信を許可する設定を追加します。

sudo firewall-cmd --add-port 8080/tcp --zone=public --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-all --zone=public

10.SELinuxの設定

SELinuxの設定を変更します。

sudo setenforce 0

再起動後にSELinuxが有効にならないように設定ファイルを変更します。

sudo vi /etc/selinux/config
/etc/selinux/config
SELINUX=enforcing

の部分を以下のように変更して保存します。

/etc/selinux/config
SELINUX=permissive

11.MySQL DBシステムの接続情報の確認

「コンソール」 → 「MySQL DBシステム」 → 「MySQL DBシステム」

リソース欄の「エンドポイント」をクリックし、MySQL DBシステムのエンドポイント(ホスト、ポート)を確認します。
スクリーンショット 2020-10-28 21.00.05.png

12.アプリケーションで使用するDBの準備

DB接続情報を含む、MySQLクライアントの設定ファイルを作成します。

vi /home/opc/.my.cnf
/home/opc/.my.cnf
[client]
user=admin
password="Demo#1Demo#1"
host="mysql1.subnet2.vcn1.oraclevcn.com"

mysqlコマンドででMySQLに接続に接続します。

mysql

アプリケーションで使用するDBを作成します。

mysql> CREATE DATABASE testdb;

アプリケーションで使用するDBユーザを作成します。

mysql> CREATE USER 'test' IDENTIFIED BY 'Demo#1Demo#1';

アプリケーションで使用するDBユーザに権限を付与します。

mysql> GRANT ALL ON testdb.* TO 'test';

アプリケーションで使用するDBに接続します。

mysql> USE testdb

アプリケーションで使用するテーブルを作成します。

mysql> CREATE TABLE dept (
    -> deptno INT ,
    -> dname VARCHAR(14),
    -> loc VARCHAR(13) ,
    -> PRIMARY KEY  (deptno) 
    -> );

アプリケーションで使用するテーブルにデータを挿入します。

mysql> INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK');
mysql> INSERT INTO dept VALUES (20,'RESEARCH','DALLAS');
mysql> INSERT INTO dept VALUES (30,'SALES','CHICAGO');
mysql> INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON');
mysql> COMMIT;

アプリケーションで使用するテーブルのデータを確認します。

mysql> SELECT * FROM dept;
+--------+------------+----------+
| deptno | dname      | loc      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

mysqlコマンドを終了します。

mysql> exit

13.Node.jsアプリケーションの作成

今回はexpressフレームワークを使用してNode.jsアプリケーションを作成します。

opcユーザのホームディレクトリ直下に、expressコマンドでNode.jsアプリケーション環境を作成します。

cd /home/opc
express --view=ejs app

アプリケーション環境のディレクトリに移動し、npmコマンドで依存関係のあるモジュールをインストールします。

cd app
npm install

npmコマンドでMySQLにアクセスするために使用する@mysql/xdevapiモジュールをインストールします。

npm install --save @mysql/xdevapi 

app.jsを編集します。

vi /home/opc/app/app.js

末尾に以下の内容を追加します。

/home/opc/app/app.js
app.listen(8080);

routes/index.jsを編集します。

vi /home/opc/app/routes/index.js

以下の内容に書き換えます。

/home/opc/app/routes/index.js
var express = require('express');
var mysqlx = require('@mysql/xdevapi');
var router = express.Router();
var os = require('os');

mysqlx
  .getSession({
   user: 'test',
   password: 'Demo#1Demo#1',
   host: 'mysql1.subnet2.vcn1.oraclevcn.com',
   port: '33060'
   })
    .then(function (session) {
      var db = session.getSchema('testdb');
      var myTable = db.getTable('dept');
      var rows =  myTable
         .select()
         .execute()
         .then(res => {
           dept = res.fetchAll();
           hostname = os.hostname();
           console.log(dept);
           console.log(hostname);
         });
      router.get('/', function(req, res, next) {
        res.render('index',{dept: dept, hostname: hostname});
      });
    })
    .catch(function (err) {
       console.log('error: ' + err.stack);
            return;
    });

module.exports = router;

views/index.ejsを編集します。

vi /home/opc/app/views/index.ejs

以下の内容に書き換えます。

/home/opc/app/views/index.ejs
<html>
<head>
<meta charset="UTF-8">
<title>Node.js to MySQL DS Connection Test</title>
</head>
<body>
<table border='1'>
<caption>DEPT Table</caption>
<tr><th>Dept No.</th><th>Dept Name</th><th>Location</th></tr>
  <% dept.forEach(function(deptItem) { %>
    <tr>
    <td><%- deptItem[0] %></td>
    <td><%- deptItem[1] %></td>
    <td><%- deptItem[2] %></td>
    </tr>
  <% }); %>
</table><br>
Response from <%- hostname %>
</body>
</html>

14.Node.jsアプリケーションの動作確認

nodeコマンドでアプリケーションを実行します。

cd /home/opc/app
node app.js

PCのブラウザからアクセスして、アプリケーションの動作を確認します。

http://<AP1のグローバルIP>:8080

スクリーンショット 2020-10-28 21.21.13.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[OCI] Computeインスタンス上にNode.jsのWebアプリケーション環境を構成して、MySQL Database ServiceのDBシステムにアクセスしてみた

はじめに

Computeインスタンス上に構成したNode.jsのWebアプリケーションから、MySQL Database ServiceのDBシステムにアクセスしてみた時の手順です。
(2020年10月現在)

構築イメージ

スクリーンショット 2020-10-28 19.50.40.png

作業の流れ

1.VCNの構成
2.ネットワーク・セキュリティ・グループの作成
3.MySQL DBシステムの作成
4.Computeインスタンス(APサーバ)の作成
5.パブリックIPの作成
6.ComputeインスタンスへのパブリックIPの割り当て
7.MySQLクライアントのインストールと設定
8.Node.jsのインストールと設定
9.firewalldの設定
10.SELinuxの設定
11.MySQL DBシステムの接続情報の確認
12.アプリケーションで使用するDBの準備
13.Node.jsアプリケーションの作成
14.Node.jsアプリケーションの動作確認

1.VCNの構成

こちらの記事を参考に、仮想クラウド・ネットワークを構成します。

OCIのネットワークを構成する際に手戻りの少ない手順を考えてみる(初心者向け)

ここでは、以下の理由からMySQL DBシステムを独立したプライベート・サブネットに配置します。
・MySQL DBシステムはプライベート・エンドポイントのみを持つ。
・MySQL DBシステムにはネットワーク・セキュリティ・グループを適用できない。

そのため、参考記事のネットワーク構成に対して、以下の部分を変更します。

・Subnet2のセキュリティ・リスト(Security List for Subnet2)
APサーバを配置するサブネット(Subnet1:10.0.1.0/24)からのみ、MySQLへの接続で使用するTCP 3306、33060へのアクセスを許可します。

「コンソールメニュー」 → 「ネットワーキング」 → 「仮想クラウド・ネットワーク」 
 → 「仮想クラウドネットワークの詳細」 → 「セキュリティ・リスト」

「セキュリティ・リストの作成」をクリック
 ・ 名前:Security List for Subnet2
 ・コンパートメントに作成:「Compartment1」を選択
  ・「+追加のイングレス・ルール」をクリック
   ・ステートレス:チェックをオフ(デフォルト)
   ・ソース・タイプ:「CIDR」を選択
   ・ソースCIDR:10.0.1.0/24
   ・IPプロトコル:「TCP」を選択
   ・ソース・ポート範囲:入力しない
   ・宛先ポート範囲:3306
  ・「+追加のイングレス・ルール」をクリック
   ・ステートレス:チェックをオフ(デフォルト)
   ・ソース・タイプ:「CIDR」を選択
   ・ソースCIDR:10.0.1.0/24
   ・IPプロトコル:「TCP」を選択
   ・ソース・ポート範囲:入力しない
   ・宛先ポート範囲:33060
  ・「+追加のエグレス・ルール」をクリック
   ・ステートレス:チェックをオフ(デフォルト)
   ・宛先タイプ:「CIDR」を選択
   ・宛先CIDR:0.0.0.0/0
   ・IPプロトコル:「全てのプロトコル」を選択」
 ・「セキュリティ・リストの作成」をクリック

2.ネットワーク・セキュリティ・グループの作成

今回作成するNode.jsアプリケーションでTCP 8080でリクエストを受けるので、すべての場所からTCP 8080へのアクセスを許可するネットワーク・セキュリティ・グループを作成します。

「コンソールメニュー」 → 「ネットワーキング」 → 「仮想クラウド・ネットワーク」 → 「仮想クラウドネットワークの詳細」 → 「ネットワーク・セキュリティ・グループ」

「ネットワーク・セキュリティ・グループの作成」をクリック
 ・名前:Network Security Group for AP
 ・コンパートメントに作成:「Compartment1」を選択
 ・「次」をクリック
 ・セキュリティ・ルールの追加
  ルール
   ステートレス:チェックをオフ(デフォルト)
   方向:「イングレス」を選択
   ソースタイプ:「CIDR」を選択
   ソース:0.0.0.0/0
   IPプロトコル:「TCP」を選択
   ソース・ポート範囲:デフォルトのまま(入力しない)
   宛先ポート範囲:8080
  説明:Security Rule for TCP 8080 **
 ・
「作成」をクリック**

3.MySQL DBシステムの作成

「コンソールメニュー」 → 「MySQL」 → 「DBシステム」

・「MySQL DBシステムの作成」をクリック

 DBシステムの基本情報情報
 ・コンパートメントの選択:「Compartment1」を選択
 ・DBシステムの名前の指定:MySQL1
 ・可用性ドメインの選択:任意の可用性ドメインを選択
 ・フォルト・ドメインの選択:任意のフォルト・ドメインを選択
 ・シェイプの選択:任意のシェイプを選択
 ・データ・ストレージ・サイズ(GB):任意のサイズを入力
 ・メンテナンス・ウィンドウの開始時間:入力しない
 ・「次」をクリック

 データベースの基本情報の指定
 ・管理者資格証明の作成
  ・ユーザー名:admin
  ・パスワード:Demo#1Demo#1
  ・パスワードの確認:Demo#1Demo#1
 ・ネットワーク情報の指定
  ・仮想クラウドネットワーク:「VCN1」を選択
  ・サブネット:「Subnet2」を選択
  ・ホスト名:mysql1
  ・MySQLポート:3306(デフォルト)
  ・MYSQL Xプロトコル・ポート:33060(デフォルト)
  ・「次」をクリック

 DBシステム・バックアップの基本情報の指定
 ・バックアップの構成
  ・自動バックアップの有効化:チェックをオン(デフォルト)
  ・バックアップ保持期間:7(デフォルト)
  ・バックアップ・ウィンドウの開始時間:デフォルト・バックアップ・ウィンドウ(デフォルト)
 
  ・「作成」をクリック

4.Computeインスタンス(APサーバ)の作成

「コンソールメニュー」 → 「コンピュート」 → 「インスタンス」

・「インスタンスの作成」をクリック
 ・名前:AP1
 ・コンパートメントに作成:「Compartment1」を選択

 ・配置とハードウェアの構成
  ・可用性ドメイン:任意のADを選択
  ・イメージ:「Oracle Linux 7.8」を選択
  ・シェイプ:任意のシェイプを選択

 ・ネットワーキングの構成 
  ・ネットワーク:「既存の仮想クラウド・ネットワークを選択」を選択し、「VCN1」を選択
  ・サブネット:「既存のサブネット」を選択し、「Subnet 1」を選択
  ・ネットワーク・セキュリティ・グループを使用してトラフィックを制御:チェックをオン
  ・ネットワーク・セキュリティ・グループ:「Network Security Group for AP」を選択
  ・パブリックIPアドレス:「パブリックIPアドレスを割り当てないでください」を選択
 
 ・SSHキーの追加
  ・「公開キー・ファイルの選択」を選択し、「または場所を参照します」をクリックして公開キー・ファイルをアップロードします
 
 ・ブートボリュームの構成
  ・全てデフォルトのまま

 ・「拡張オプションの表示」をクリック
  ・「管理」タブ
   ・全てデフォルトのまま
  ・「ネットワーキング」タブ
   ・プライベートIPアドレス:10.0.1.100
   ・ホスト名:ap1
   ・起動オプション:デフォルトのまま
  ・「イメージ」タブ
   ・デフォルトのまま
  ・「配置」タブ
   ・デフォルトのまま
「作成」をクリック

5.パブリックIPの作成

「コンソールメニュー」 → 「ネットワーキング」 → 「IP Management」

「パブリックIPアドレスの予約」をクリック

 ・予約済パブリックIPアドレス名:PublicIP1
 ・コンパートメントに作成:「Compartment1」を選択
 ・IPアドレスのソース:「Oracle」を選択

 ・「パブリックIPアドレスの予約」をクリック

6.ComputeインスタンスへのパブリックIPの割り当て

「コンソールメニュー」 → 「コンピュート」 → 「インスタンス」 → 「インスタンスの詳細」

・リソース欄の「アタッチされたVNIC」をクリック
VNIC名(AP1)をクリック
・リソース欄の「IPアドレス」をクリック
IPアドレスの欄の「:」をクリックし、「編集」をクリック
 ・パブリックIPタイプ:「予約済パブリックIP」を選択
 ・「既存の予約済パブリックIPの選択」を選択
 ・RESERVED IP ADDRESS:「PublicIP1」を選択
「更新」をクリック

7.MySQLクライアントのインストールと設定

秘密鍵を使って、SSHクライアントからComputeインスタンス(AP1)にopcユーザでログインします。

タイムゾーンとロケールを設定します。

sudo timedatectl set-timezone Asia/Tokyo
sudo localectl set-locale LANG=ja_JP.utf8

yumコマンドでMySQLクライアントをインストールします。

sudo yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
sudo yum install -y mysql-community-client

8.Node.jsのインストールと設定

yumコマンドでNode.jsインストールをインストールします。

sudo yum install -y oracle-release-el7 oracle-nodejs-release-el7
sudo yum install -y --disablerepo=ol7_developer_EPEL nodejs

npmコマンドで使用するNode.jsモジュール(expressフレームワーク、ejs)をインストールします。

sudo npm install -g --save express-generator
sudo npm install -g --save ejs

9.firewalldの設定

firewall-cmdコマンドでfirewalldにTCP8080の通信を許可する設定を追加します。

sudo firewall-cmd --add-port 8080/tcp --zone=public --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-all --zone=public

10.SELinuxの設定

SELinuxの設定を変更します。

sudo setenforce 0

再起動後にSELinuxが有効にならないように設定ファイルを変更します。

sudo vi /etc/selinux/config
/etc/selinux/config
SELINUX=enforcing

の部分を以下のように変更して保存します。

/etc/selinux/config
SELINUX=permissive

11.MySQL DBシステムの接続情報の確認

「コンソール」 → 「MySQL DBシステム」 → 「MySQL DBシステム」

リソース欄の「エンドポイント」をクリックし、MySQL DBシステムのエンドポイント(ホスト、ポート)を確認します。
スクリーンショット 2020-10-28 21.00.05.png

12.アプリケーションで使用するDBの準備

DB接続情報を含む、MySQLクライアントの設定ファイルを作成します。

vi /home/opc/.my.cnf
/home/opc/.my.cnf
[client]
user=admin
password="Demo#1Demo#1"
host="mysql1.subnet2.vcn1.oraclevcn.com"

mysqlコマンドででMySQLに接続に接続します。

mysql

アプリケーションで使用するDBを作成します。

mysql> CREATE DATABASE testdb;

アプリケーションで使用するDBユーザを作成します。

mysql> CREATE USER 'test' IDENTIFIED BY 'Demo#1Demo#1';

アプリケーションで使用するDBユーザに権限を付与します。

mysql> GRANT ALL ON testdb.* TO 'test';

アプリケーションで使用するDBに接続します。

mysql> USE testdb

アプリケーションで使用するテーブルを作成します。

mysql> CREATE TABLE dept (
    -> deptno INT ,
    -> dname VARCHAR(14),
    -> loc VARCHAR(13) ,
    -> PRIMARY KEY  (deptno) 
    -> );

アプリケーションで使用するテーブルにデータを挿入します。

mysql> INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK');
mysql> INSERT INTO dept VALUES (20,'RESEARCH','DALLAS');
mysql> INSERT INTO dept VALUES (30,'SALES','CHICAGO');
mysql> INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON');
mysql> COMMIT;

アプリケーションで使用するテーブルのデータを確認します。

mysql> SELECT * FROM dept;
+--------+------------+----------+
| deptno | dname      | loc      |
+--------+------------+----------+
|     10 | ACCOUNTING | NEW YORK |
|     20 | RESEARCH   | DALLAS   |
|     30 | SALES      | CHICAGO  |
|     40 | OPERATIONS | BOSTON   |
+--------+------------+----------+

mysqlコマンドを終了します。

mysql> exit

13.Node.jsアプリケーションの作成

今回はexpressフレームワークを使用してNode.jsアプリケーションを作成します。

opcユーザのホームディレクトリ直下に、expressコマンドでNode.jsアプリケーション環境を作成します。

cd /home/opc
express --view=ejs app

アプリケーション環境のディレクトリに移動し、npmコマンドで依存関係のあるモジュールをインストールします。

cd app
npm install

npmコマンドでMySQLにアクセスするために使用する@mysql/xdevapiモジュールをインストールします。

npm install --save @mysql/xdevapi 

app.jsを編集します。

vi /home/opc/app/app.js

末尾に以下の内容を追加します。

/home/opc/app/app.js
app.listen(8080);

routes/index.jsを編集します。

vi /home/opc/app/routes/index.js

以下の内容に書き換えます。

/home/opc/app/routes/index.js
var express = require('express');
var mysqlx = require('@mysql/xdevapi');
var router = express.Router();
var os = require('os');

mysqlx
  .getSession({
   user: 'test',
   password: 'Demo#1Demo#1',
   host: 'mysql1.subnet2.vcn1.oraclevcn.com',
   port: '33060'
   })
    .then(function (session) {
      var db = session.getSchema('testdb');
      var myTable = db.getTable('dept');
      var rows =  myTable
         .select()
         .execute()
         .then(res => {
           dept = res.fetchAll();
           hostname = os.hostname();
           console.log(dept);
           console.log(hostname);
         });
      router.get('/', function(req, res, next) {
        res.render('index',{dept: dept, hostname: hostname});
      });
    })
    .catch(function (err) {
       console.log('error: ' + err.stack);
            return;
    });

module.exports = router;

views/index.ejsを編集します。

vi /home/opc/app/views/index.ejs

以下の内容に書き換えます。

/home/opc/app/views/index.ejs
<html>
<head>
<meta charset="UTF-8">
<title>Node.js to MySQL DS Connection Test</title>
</head>
<body>
<table border='1'>
<caption>DEPT Table</caption>
<tr><th>Dept No.</th><th>Dept Name</th><th>Location</th></tr>
  <% dept.forEach(function(deptItem) { %>
    <tr>
    <td><%- deptItem[0] %></td>
    <td><%- deptItem[1] %></td>
    <td><%- deptItem[2] %></td>
    </tr>
  <% }); %>
</table><br>
Response from <%- hostname %>
</body>
</html>

14.Node.jsアプリケーションの動作確認

nodeコマンドでアプリケーションを実行します。

cd /home/opc/app
node app.js

PCのブラウザからアクセスして、アプリケーションの動作を確認します。

http://<AP1のグローバルIP>:8080

スクリーンショット 2020-10-28 21.21.13.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

〇〇env系ツールをanyenvで一括管理する

はじめに

この記事は フューチャーAdvent Calendar 2020 の20日目の記事です。

環境構築に便利な〇〇env系ツールを、もっと便利に扱える anyenv に感動したので、ブログ化しました。

開発言語のバージョン管理

複数プロジェクトに関わる場合、開発言語のバージョン管理は必須スキルです。
他の開発メンバーと利用バージョンを一致させなければ、フォーマッタ適用 → PRでの差分爆発が生じてレビュアーに袋叩きにされます。

なので、各エンジニアはそれぞれの創意工夫により、開発言語のバージョン管理問題を解決しています。

私の場合、環境構築ポリシーとして
- ローカル環境への直ダウンロードは厳禁
- 環境構築は基本的にDockerを使う

という方針を、ずっと貫いています。

...

スミマセン。強がりです。
貫けていませんでした。

〇〇env の多用

コロナ影響で在宅勤務へ移行した結果、NWの問題によりDockerがうまく使えない状況が増え、仕方なく〇〇env系ツールの利用を開始しました。

インストールした〇〇env系ツールは
- PJ開発はメインでgoを使う → goenv
- 環境Aはpythonのみ動く → pyenv
- 環境Bはrubyのみ動く → rbenv
- AWSのMFA(多要素認証)でet-otpを使う → jenv

というもので、開発作業で新しい言語が必要になるたびに、対応するツール1つ1つ追加していました。

これらは同じコマンド操作で設定可能なため、ストレスになるのはパッケージのダウンロード時間くらいだと思っていましたが、知らぬ間に開発環境汚染が進んでいました。

bash_profileが汚れていた

担当業務で Vue.js のコードに触れる機会があり、新たに nodenv をインストールしようとしたところ
- 〇〇env系ツールの環境構築って、いっつも同じような環境変数を追加しているな
- bash_profileのメンテしてたっけ?

ということに気づき、cat ~/.bash_profile すると、↓こんな感じになっていました

...
# goenv
export GOENV_ROOT=$HOME/.goenv
export PATH=$GOENV_ROOT/bin:$PATH
eval "$(goenv init -)"

# pyenv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

# jenv
export JENV_ROOT=$HOME/.jenv
export PATH="$HOME/.jenv/bin:$PATH"
eval "$(jenv init -)"

(rbenv, nodenv などの設定が続く...)
...

あれ?

開発環境が汚れないよう注意していたはずなのに
所々で微妙な違いがあり、綺麗な状態とは言い難い...

〇〇env系ツールが増えるごとに
bash_profileに追記し続けるのを止めたい

...

anyenv が便利そう!

anyenvを使って綺麗にする

anyenv自体の説明前に、このツールを使うと何が綺麗になるか?から説明します。

すでにインストール済みのgoenv, pyenvなどはanyenv経由での再設定が必要になりますが、それを乗り越えれば、bash_profile に必要な 〇〇env系ツールの記述 は、以下のみで十分となります。将来的に新しい 〇〇env が必要になった場合でも、bash_profile への追記は不要です。

...
# anyenv
eval "$(anyenv init -)"
...

goenv, jenvごとにPATHを設定 & initする煩わしい記述から解放され、かつ、操作方法は従来の〇〇env系コマンドを利用可能なので、開発環境汚染を少しでも減らしたいエンジニアであれば、このツールを使わない理由は無いと思います。

anyenvとは?

anyenv - All in one for **env

This is a simple wrapper for rbenv style environment managers. You don't have to git clone or modify your shell profile for each **env anymore if you install anyenv.

https://github.com/anyenv/anyenv#anyenv---all-in-one-for-env

端的に言うと、複数の〇〇envを一括管理できる便利ツールです。

執筆時点(2020.12.10)では、以下〇〇envパッケージがanyenvでは利用可能です。
有名どころは網羅しているので、多くの開発プロジェクトで導入可能だと思います。

$ anyenv install -l
  Renv       #R
  crenv      #Crystal
  denv       #D
  erlenv     #Erlang
  exenv      #Elixir
  goenv      #Go
  hsenv      #Haskell
  jenv       #Java
  jlenv      #Julia
  luaenv     #Lua
  nodenv     #Node.js
  phpenv     #PHP
  plenv      #Perl
  pyenv      #Python
  rbenv      #Ruby
  sbtenv     #Sbt
  scalaenv   #Scala
  swiftenv   #Swift
  tfenv      #terraform

上記から欲しい言語をインストールすれば、あとはいつも通りの〇〇env操作コマンドで環境構築可能です。

anyenvのインストール手順

macの場合

Homebrewを利用します。

$ brew install anyenv
$ echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

$ anyenv install --init # enter "y"

Linux環境の場合

GitHubから直接引っ張ってきます。

$ git clone https://github.com/anyenv/anyenv ~/.anyenv
$ echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(anyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

$ anyenv install --init # enter "y"

最後に $ anyenv install 〇〇env で欲しいパッケージを取得すれば、これまで通りの〇〇envコマンドが利用できます。

ex) node.jsのv15.0.1が欲しい場合

anyenvを利用し、nodenvを取得します。

$ anyenv install nodenv
$ exec $SHELL -l

$ anyenv versions
nodenv:
Warning: no Node detected on the system

次は、nodenvでv15.0.1を取得します。

$ nodenv install 15.0.1
$ nodenv global(local) 15.0.1

$ node -v
v15.0.1

以上により、Node.js:v15.0.1 が利用可能となりました。

私の開発では goenv, pyenv, jenv, nodenv が必須なので、以下の設定を入れています。
$ anyenv versions により、各envの設定状況が一覧できます。

$ anyenv versions
goenv:
  system
  1.XX.0
* 1.YY.0 (set by /Users/<username>/.anyenv/envs/goenv/version)
jenv:
  system
* XX.0 (set by /Users/<username>/.anyenv/envs/jenv/version)
nodenv:
  system
* XX.0 (set by /Users/<username>/.anyenv/envs/nodenv/version)
pyenv:
  system
  XX.0
* YY.0 (set by /Users/<username>/.anyenv/envs/pyenv/version)

anyenvインストール以前に設定したgoenvやpyenvの環境変数が残っている場合は、bash_profileから削除することも忘れないようご注意ください。

まとめ

  • 環境変数、echo 'export hogehoge"' >> ~/.bash_profileで追加したまま放置していませんか
  • 複数の〇〇env系ツールを使っているなら、anyenvの利用がオススメ
  • anyenvでbash_profileがスッキリ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.js + socket.io の簡易チャットアプリをコンテナ化したメモ

背景

Node.js + socket.io の簡易チャットアプリをコンテナ化した時のメモ

リンク集

Node.js Web アプリケーションを Docker 化する

Hello Worldを返す簡易Node.jsサーバーを作ってコンテナ化するドキュメント。ほぼ忘れかけているNode.jsの記憶を取り戻すことができた。

Socket.io#Get Started

socket.ioを使って簡易的なアプリを作ることができる

サンプルコード

package.json
{
  "name": "docker_web_app",
  "version": "1.0.0",
  "description": "Node.js on Docker",
  "author": "shogo suzuki",
  "main": "socket_server.ts",
  "scripts": {
    "start": "node socket_server.js"
  },
  "dependencies": {
    "express": "*",
    "socket.io": "^2.3.0"
  }
}
Dockerfile
FROM node:14.13
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD [ "node", "socket_server.ts" ]
index.html
<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: 0.5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <script src="/socket.io/socket.io.js"></script>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  <script>
    $(function () {
      var socket = io();
      $('form').submit(function(e){
        e.preventDefault(); // prevents page reloading
        socket.emit('chat message', $('#m').val());
        $('#m').val('');
        return false;
      });
      socket.on('chat message', function(msg){
        $('#messages').append($('<li>').text(msg));
      });
    });
  </script>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
  </body>
</html>
socket_server.ts
var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
  console.log('a user connected');
  socket.on('chat message', (msg) => {
    io.emit('chat message', msg);
  });
});

http.listen(3000, () => {
  console.log('listening on *:3000');
});

実行

docker build -t socket-example:1.0 .
docker run -p 3000:3000 -d socket-example:1.0
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerfile、docker-compose.ymlを作ってwindows10、Linux、ラズパイでnodejsを動かす

以前書いた下記、記事の続きでDockerfileとdocker-compose.ymlを作って、動かす手順まで今回記載します。
https://qiita.com/MCYamamoto/items/4d424af9573fa90edf61

最終的なフォルダ構成

まず、最終的なフォルダ構成です。
下記のようになります。

baseフォルダ
+docker-compose.yml
+cont
 +env
  +Dockerfile
   +deploy //デプロイ対象のソースコード(今回はnodejs)
    +package.json
    +package-lock.json
    +build
     +jsファイルたち
  +share //ホストとコンテナの共有フォルダ

Dockerfileをつくる

[参考URL]
https://qiita.com/pottava/items/452bf80e334bc1fee69a

全体的な流れとしては、上記を参考にした。
インストール必要なものをインストールしながらコマンドをメモして、最終的なDockerfileを作るというもの。

1. Dockerイメージを決める。

ラズパイはARMのため、ARMに対応したイメージとしてDebianにした。
[参考URL]
https://qiita.com/koduki/items/0ed303dac5d32646194f

2. bashのコンテナを起動する。

$ sudo docker run -it -v $(pwd):/tmp/share debian:buster /bin/bash
-it:ターミナルで操作可能に
-v:コンテナとのフォルダ共有

3. 必要なものをインストールする。

動かしたいプログラムによって必要なパッケージをインストールする。

apt-get install パッケージ名

といった感じです。

なお、注意点としては、Dockerfileに書く場合はインストールを止めないため"-y"オプションが必要です。

最終的にはnodeとsqliteしか必要なかったので、コンテナイメージをnodeにしてしまう方が良いのですが、
過程を残すということで、最終的にできたのは下記になります。

やっていることとしては、下記になります。
- deploy対象のコードをコピー
- 必要なものをOSにインストール
- deployフォルダ配下のnodeに必要なパッケージを「npm install」でインストール

#Dockerfile

FROM debian:buster

COPY deploy/ /home/deploy
WORKDIR /home/deploy

RUN apt-get update
RUN apt-get install -y cmake
RUN apt-get install -y libssl-dev
RUN apt install curl
RUN apt-get install -y sqlite3 libsqlite3-dev
RUN apt-get install -y nodejs npm && npm install n -g && n 12.18.4
RUN npm install

docker-compose.ymlをつくる

先ほど作ったDockerfileをコンテナイメージとして、最終的にdeployフォルダ配下のnodeが自動起動するものにしました。
<補足>

version: "3.8"
services:
  cont:
    build:
      context: ./cont/env
      dockerfile: Dockerfile
    container_name: CONT-1
    tty: true
    volumes:
      - "./cont/env/share:/tmp/share"
      - ".:/workspace"
      - "./cont/env/deploy/build:/home/deploy/build"
    working_dir: /home/deploy/build
    command: npm run start

<補足>
package.jsonに下記記載して、buildフォルダ配下のプログラムが動くようにしています。

  "scripts": {
    "start": "node ./build/main.js",
  },

docker-compose起動

作成したフォルダ環境一式を各OS(Windows10、Linux、Raspi)の任意のフォルダに配置して下記実行すると、すべて同じ動きします。

sudo docker-compose up --build

(おまけ)Vscodeでのデバッグ環境作る

[参考URL]
https://tech-lab.sios.jp/archives/21675
https://qiita.com/Yuki_Oshima/items/d3b52c553387685460b0

Visual Studio Code 上でf1メニューまたは左下に現れる緑色のアイコンをクリックして「Remote-Containers: Open Folder in Container...」を選択し、docker-compose.ymlがあるフォルダを選択すると
しばらくするとコンテナが実行され、コンソールでデバッグ操作できます。

vscode、docker便利、、

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【node+Vue】ストア+APIを経由してサーバで作ったバイナリファイル受け取りダウンロードさせる

リアクティブでSPAでなければ、サーバサイドにPOSTしてファイルをダウンロードさせれば簡単だけど
v-router とか使うと簡単には行かず、困ったのだけれど、
以下の方法で受け渡しできたので備忘録として記載しておく。

【仕様】
・ダウンロードボタンを押すと、サーバ側で作成されたファイルをダウンロードする。

【前提】
・vue から直接サーバ側へはPOSTできない。(ルーターが邪魔する。)
・ストア+API経由でサーバ側とのデータのやり取りはできる。

【サーバ側実装】
今回は、API経由でデータが渡されると、サーバ側でファイルを作成し、base64エンコードした内容を
json形式で { DATA: xxxx } として返すようにした。

【クライアント側実装】
こんな感じ
今回の肝は以下の2箇所。
・base64 をデコードする部分
・blobファイルをダウンロードさせる部分。

methods: {
  /**
   * ダウンロード
   */
  async download() {
    let info = { // api に渡す引数があれば、こんな感じで受け渡す。
      name: "download.csv"
    };
    let data = await this.$store.dispatch("download", { info });

    // base64をデコードする。
    let base64 = data["DATA"];
    let bin = atob(base64.replace(/^.*,/, ''));
    let buffer = new Uint8Array(bin.length);
    for (var i = 0; i < bin.length; i++) {
      buffer[i] = bin.charCodeAt(i);
    }

    // 以下のコードが実行されると、勝手にファイルがダウンロードされる。
    const blob = new Blob([buffer.buffer], { type: 'application/csv'});
    let link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = 'download.csv';
    link.click();
  }
},

download() を呼び出すボタンはこんな感じ。

<v-btn text @click="download" v-bind="attrs" v-on="on">
<v-icon>mdi-download</v-icon>
</v-btn>

直接、サーバサイドにPOSTできれば簡単だったけれど、そうすると他とセオリーが異なってしまう。
ボタンが押されると、すぐ遷移してそちらで処理されるのとは異なり、
ボタンが押されると非同期で axios 通信が行われ、データを受け取った後にダウンロードされることになる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WindowsのNode.jsのバージョンマネージャー

メモ。

Nodistでやってみたが、JetBrains製品で上手く認識されなかった。
nvm-windowsというのがあり、Googleも推奨してるらしいので、それを入れたら上手く行った。

https://github.com/coreybutler/nvm-windows

インストール

https://github.com/coreybutler/nvm-windows/releases
ここから、nvm-setup.zipなやつを落としてくる

あとはウィザードに従ってインストール。

動作確認

バージョンの確認

nvm version

インストール済みのバージョンの確認、初期では当然ない。

nvm list

インストール出来るバージョンの確認

nvm list available

nodeのインストール

コマンドプロンプトとかは管理者権限で立ち上げるみたい。

14.15.0のインストール

nvm install 14.15.0

14.15.0を使用する。これをやるとC:\Program Filesにリンクを作ってくれるので、nodeが利用できるようになるみたい。ちなみにインストール時にどこにこれを作るのか聞かれたので、別の場所を指定したらそこになるんだろう。

nvm use 14.15.0

node -v

12.19.0を使用してみる

nvm install 12.19.0
nvm use 12.19.0
node -v
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Module

ES6のモジュールシステム

1. 概要

あるファイルから別のファイルの関数や変数を参照したいときに、モジュールシステムを利用する。参照元では、importコマンドを使って外部のファイルを指定し、参照先では、exportコマンドを使って関数や変数を外部に公開する。

公開の方法として、大きく分けて、Named ExportsとDefault Exportsがある。両者はimport/exportコマンドの使い方が異なるので、章を分けて説明していく。

2. Named Exports

基本的には、以下のように、公開したいものの頭にexportを付ける。

// car.js
export const MAX_SPEED = 200;

export function getSpeed() {
  retrun speed;
}

export function setSpeed(x) {
  speed = x;
}

あるいは、以下のように、ファイルの最後にまとめて書くこともできる。

// car.js
const MAX_SPEED = 200;

function getSpeed() {
  retrun speed;
}

function setSpeed(x) {
  speed = x;
}

export {
  MAX_SPEED,
  getSpeed,
  setSpeed,
};

外部に対して別名を見せたいときには、次のようにasを指定できる。

// car.js
const MAX_SPEED = 200;

function getSpeed() {
  retrun speed;
}

function setSpeed(x) {
  speed = x;
}

export {
  MAX_SPEED as CAR_MAX_SPEED, // 外部のファイルからはCAR_MAX_SPEEDという名前で見える
  getSpeed,
  setSpeed,
};

上で作ったファイル「car.js」を参照するためには、importコマンドを用いる。

// main.js
import { CAR_MAX_SPEED, getSpeed, setSpeed } from 'car';

setSpeed(100);

{ CAR_MAX_SPEED, getSpeed, setSpeed }のところは、必ずしもすべてを指定する必要はなく、必要なものだけを指定してよい。

指定が面倒な場合には、次のように* asを付けて、すべてを読み込むこともできる。

// main.js
import * as Car from 'car';

Car.setSpeed(100);

3. Default Exports

上で説明したNamed Exportsでは、importの際に、読み込むものを列挙したり、* asを指定する必要があった。これに対して Default Exportsでは、よりシンプルに、次のように書くことができる。

// main.js
import Car from 'car';

Car.setSpeed(100);

これに対応するには、以下のように、export defaultを指定する。

// car.js
const MAX_SPEED = 200;

function getSpeed() {
  retrun speed;
}

function setSpeed(x) {
  speed = x;
}

// Objectにまとめて公開する
export default {
  MAX_SPEED: MAX_SPEED,
  getSpeed: getSpeed,
  setSpeed: setSpeed,
};

この例ではObjectを公開しているが、変数でも関数でもクラスでも、何でもよい。ただし、export defaultは、ファイルの中で1箇所しか書くことはできない。

なお、ES6ではオブジェクトのキーを省略表記できるようになったので、上の例は、次のように簡潔に書ける。

export default {
  MAX_SPEED,
  getSpeed,
  setSpeed,
};

こう書くと、先のNamed Exportsの例にそっくりになるが、構文的にはまったく別モノであるから注意が必要である。例えば、Named Exportsのようなasを使うことはできず、次のコードはエラーとなる。

export default {
  MAX_SPEED as CAR_MAX_SPEED,  // エラー!!
  getSpeed,
  setSpeed,
};

4. いずれを使うべきか

「Exploring ES6」という書籍では、Named Exportsよりも、Default Exportsが推奨されている。これは、書式の簡潔さを根拠としている。

Exploring ES6 より引用:

16.8.1 Default exports are favored

The module syntax suggesting that the default export "is" the module may
seem a bit strange, but it makes sense if you consider that one major design
goal was to make default exports as convenient as possible.
Quoting David Herman:

  ECMAScript 6 favors the single/default export style, and gives the sweetest
  syntax to importing the default. Importing named exports can and even should
  be slightly less concise.

一方、下記の記事のように、export defaultを使うメリットがないと指摘する意見もある。これは主に、Tree-Shakingという最適化との相性が悪いことを根拠にしている。例えば、多数のメソッドを持つオブジェクトをexport defaultしていて、そのうちの一部のメソッドしか使わない場合、minifyしてもサイズが小さくならないらしい。

参考: Why we have banned default exports in Javascript and you should do the same

これら双方の主張を考えると、おおよそ、以下のように使い分けをすると良さそうである。

  • ライブラリのように、使うかどうか分からないメソッドが多数ある場合には、Named Exports
  • そうでなければ、Default Exports

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Botpressで作るチャットボットにAWSインフラエンジニアの仕事をさせよう

忙しい日々が続いていて、自分の部下が欲しいーー!でも、教えるのは面倒。。。それ以前に人がいない。。。そう感じた時に自分の仕事をボットにやらせればいいんじゃないか?!と思いつき、開発?育成?することにしました。

完成イメージ


ボットに処理を依頼するとボットがansibleでsarコマンドなどを対象サーバー上で実行し、その実行結果をチャットに表示します

前回書いた記事

https://qiita.com/drafts/e87634e7bef42ed2dfe1/

環境

EC2(AmazonLinux2)
ALB
Nginx
Botpress

参考リンク

https://botpress.io/

Botpressインストール

mkdir botpress
wget https://s3.amazonaws.com/botpress-binaries/botpress-v12_10_7-linux-x64.zip
unzip botpress-v12_10_7-linux-x64.zip
./bp

■エラーになる時
※AmazonLinux2で動作しなかったので以下対応

Error starting botpress
Error: Could not require NativeExtension "fasttext.node" for OS "linux raspbian". Tried the following paths: [ /mnt/xxxxx/xxxxxxx/botpress/bindings/linux/default/fasttext.node ]

↑のエラーが出る場合、bindings/linux/にバイナリコンパイル済のファイルがあるのでそれをraspbianのところと合わせる
cp -a bindings/linux/centos_7_5 bindings/linux/raspbian

fasttextは別のオープンソースのようで別途コンパイルが必要みたい

Botpress設定

■Botpressをバックグラウンド実行する

・pm2インストール
npm install pm2 -g

・バックグラウンド実行
pm2 start './bp start -p'

■自分のWebサイトにbotpressチャットを表示させる
ヘッド部に↓

<script src="/assets/modules/channel-web/object_assign.js"></script>
<script src="/assets/modules/channel-web/inject.js"></script>

ボディ部に↓

<script>
      let lastConfig = {
      host: 'https://xxx.com/',
        botId: 'test1'
      }
      window.botpressWebChat.init(lastConfig)
</script>

フロー図の作成

・CHOICEノード
↓この選択肢が表示される
image.png
image.png
image.png
image.png
選択した値によって分岐させる
image.png

FAQ

■Code-Actionsで登録したjsファイルがNodeから呼び出せない、または呼び出していたものが呼び出せなくなっている場合
どうもこのあたりにバグがある模様
一度、エクスポートして再度、ボットをインポート作成しなおす
bpを再起動(オススメ)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React とか いろんなところ で役に立つ三項演算子

React とか いろんなところ で役に立つ三項演算子

三項演算子とは以下のようなもの

isflag ? console.log("いいよ") : console.log("ダメだよ");

if 文だと

if (isflag) {
  console.log("いいよ");
} else {
  console.log("ダメだよ");
}

何が役に立つの?

三項演算子は、非常にスマートに書ける。
しかし、見にくい

コードが見にくくなってしまう。

という問題があるらしい

使いどころ アロー関数

js には、アロー関数というのがある。

() => console.log("アロー関数");

map や Object.key などでよく私は、使います。
ここで、if 文を書くとします。

const a = [1, 2, 3, 4, 5];
a.map((data) => {
  if (data == 2) {
    console.log(data);
  }
});

// ====log=====
// 2

2 が表示されます。
こういった書き方よりもこう書いたほうがコードが見やすいと思います。

a.map((data) => (data == 2 ? console.log(data) : null));

まとめ

コードは書いていると、長くなります。
長いコードをスクロールするのも大変だと思っています。

条件式をしたとしても表示するかしないか、出力するかどうか
などで数行分書くのは、大変です。

React などでは、状態によって表示するかどうかを決める時があります。そういったとき IF 文なのか三項演算子なのかは、好みによります。

私は、単純な処理なら三項演算子を使います。
好みです!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む