PackerとAnsibleを使用してAlibaba Cloud ECSインスタンス上にReact JSアプリケーションイメージを作成する


このガイドでは、Packerを使ってAlibaba Cloud ECSインスタンス上にマシンイメージを構築する方法と、マシンイメージに持たせたいものを書くためのAnsibleについてお話します。

前提条件

このガイドに従うために専門家である必要はありません。必要なのは、Alibaba CloudのアカウントとAccess keyだけです。こちらのリンクをクリックすると、Alibaba Cloud上でのアクセスキーの作成方法が表示されます。

ステップ1:パッカーのインストール

私たちのシステムにpackerをインストールするには、packerの公式インストールページに従うか、パッケージマネージャ、Windows用のchocolateyとmacOS用のhomebrewを使用することができます。パッケージマネージャを使えば、パスに環境変数を追加する手間が省けます。

chocolatey を使って Windows に packer をインストールするには

1、chocolatey パッケージマネージャをインストールします。chocolatey をインストールするには、管理者として cmd を開き、以下のコマンドを貼り付けて chocolatey パッケージマネージャをインストールします。

@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

2、chocolatey がインストールされていることを確認するには、 choco -v コマンドを実行します。

3、以下のコマンドを実行して、packerをインストールします。

choco install packer

4、packerのインストールを確認するには、次のように実行します。

packer -v

5、Packerのバージョンがインストールされているはずです。
インストールプロセスを示すGif画像

homebrewを使ってMacOSにpackerをインストールするには

1、homebrewがまだインストールされていない場合は、インストールしてください。macOSにhomebrewをインストールするには、ターミナルを開いて以下のコマンドを貼り付けます。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2、以下のコマンドを実行して、packerをインストールします。

brew install packer

3、packerのインストールを確認するには、以下を実行します。

packer -v

4、Packerのバージョンがインストールされているはずです。
MacOSへのインストールを示すGif画像

ステップ2: Reactアプリのマシンイメージを構築する

マシンイメージを構築するには、テンプレートファイルを作成する必要があります。テンプレート ファイルは、構築するイメージを定義するために使用します。テンプレートファイルはJSON形式で、Packerの様々なコンポーネントを設定する異なるキーのセットを持っています。

1、example.jsonという名前のテンプレートファイルを作成し、以下のコードを貼り付けます。

  {
      "variables": {
        "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
        "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}"
      },
      "builders": [{
        "type": "alicloud-ecs",
        "access_key": "{{user `access_key`}}",
        "secret_key": "{{user `secret_key`}}",
        "region": "us-west-1",
        "image_name": "ReactJS-Application",
        "instance_type": "ecs.t5-lc2m1.nano",
        "source_image": "ubuntu_16_0402_32_20G_alibase_20180409.vhd",
        "io_optimized":"true",
        "image_force_delete":"true",
        "ssh_username": "root",
        "internet_charge_type": "PayByTraffic"
      }],
      "provisioners": [{
        "type": "shell",
        "script": "installAnsible.sh"
       },{
       "type": "ansible",
      "playbook_file": "playbook.yml"
     }]
    }

変数セクションでは、テンプレートファイル内のどこでも使用できる変数を定義し、
env関数を指定して環境変数からaccess_keysecret_keyの値を取得しています。

ビルダーセクションには、特定のビルダーを設定するJSONオブジェクトの配列が含まれています。ビルダーは、マシンを作成し、そのマシンをイメージに変換する役割を担う packer のコンポーネントです。

プロビジョナーセクションでは、組み込みのソフトウェアやサードパーティ製のソフトウェアを使用して、起動後のマシンイメージをインストールしたり設定したりします。このガイドでは、プロビジョナーとして ansibleshell を使います。

2、ALICLOUD_ACCESS_KEYALICLOUD_SECRET_KEYをエクスポートするには、ターミナルで以下のコマンドを実行します。

 export ALICLOUD_SECRET_KEY="YOUR_ALICLOUD_ACCESS_KEY"
   export ALICLOUD_SECRET_KEY="YOUR_ALICLOUD_SECRET_KEY"

3、playbook.ymlという名前の新しいAnsibleファイルを作成し、以下のコードを貼り付けます。example.jsonplaybook.ymlは同じディレクトリまたはフォルダに作成します。

   ---
     - hosts: all
       become: true

       vars:
         NODEJS_VERSION: 8
         domain: "localhost"

       tasks:
       - name: Add gpg key for nodejs
         apt_key:
           url:  "https://deb.nodesource.com/gpgkey/nodesource.gpg.key"
           state: present
       - name: Add nodejs LTS to apt repository
         apt_repository:
           repo: "deb https://deb.nodesource.com/node_{{ NODEJS_VERSION }}.x {{ ansible_distribution_release }} main"
           state: present
           update_cache: yes
       - name: Install nodejs
         apt:
           name: nodejs
           state: present
       - name: Setup React application
         shell:
            cmd: |
              npx create-react-app my-app # Setup our react application
              cd /root/my-app
              npm install -g pm2   # Install Pm2, A nodejs process manager which enables us to run our application in the background process
       - name: Install nginx
         apt:
           name: nginx
           state:  present
           update_cache: yes
       - name: Remove nginx default configuration
         file:
           path: /etc/nginx/sites-enabled/default
           state: absent
       - name: enable reverse proxy # This enables us to use the public IP without passing in the port on our browser address bar
         shell:
           cmd: |
             cat > /etc/nginx/sites-available/my-app <<EOF
             server {
               listen 80;
               server_name {{ domain }};
               location / {
                 proxy_pass 'http://127.0.0.1:3000';
               }
             }
             EOF
       - name: create symlinks for nginx configuration # make sure the nginx configuration files are always the same.
         file:
           src:  /etc/nginx/sites-available/my-app
           dest: /etc/nginx/sites-enabled/my-app
           state: link
         notify:
         - restart nginx
       handlers:
         - name: restart nginx # restart nginx service
           service:
             name: nginx
             state: restarted

4、テンプレートファイルを検証するには、packer validate example.jsonを実行します。これにより、テンプレートファイルに構文エラーなどのエラーがないことを確認します。
5、packer build example.jsonを実行してReactJSイメージをビルドします。

ステップ3: Reactイメージを使ってインスタンスを起動する

先ほど作成した画像を使用してインスタンスを作成するには、以下の手順に従います。

1、アリババクラウドコンソールにログオン
2、ダッシュボードのサイドナビゲーションバーにあるElastic Compute Serviceをクリックします。
3、インスタンスを作成するには、[Create Instance] の説明が記載されたボタン、またはこのリンクをクリックします。
4、基本設定では、以下の操作を行います。

----- 1、課金方法については、「Pay-As-You-Go」をクリックしてください。
----- 2、地域については、ドロップダウンをクリックして、US West 1 (Silicon Valley)を選択してください。
----- 3、インスタンスタイプでは、「エントリーレベル(共有)」をクリックします。
----- 4、画像は「Custom Image」ボタンをクリックします。Custom Imageの下のドロップダウンメニューをクリックして、作成したイメージはReactJS-Applicationを選択します。
----- 5、Next: Networkingボタンをクリックします。

5、2つ目のステップであるネットワーキングについては、以下の手順に従ってください。
-----1、Networkセクションでは、「VPC」ドロップダウンメニューをクリックし、デフォルトのVPCを選択します。
-----2、Security Groupセクションでは、「ポート設定に移動」をクリックして、アプリケーションのポートを設定します。
-----3、Add Security Group Ruleをクリックし、Port Rangeを80に、Authorization Objectsを0.0.0.0.0/0に設定します。これを繰り返しますが、ポート範囲を3000に設定します。
ポート80はHTTPリクエストのためのもので、ポート300`はリアクトアプリケーションが実行されているポートです。
-----4、セキュリティグループを設定したら、次へをクリックします。Next: System Configurations ボタンをクリックします。

6、3番目のステップであるシステム設定については、以下の手順に従ってください。
-----1、詳細設定(インスタンスRAMのロールまたはクラウドイニットに基づく)ドロップダウンをクリックして、以下のコードをユーザーデータフィールドボックスに貼り付けます。

#!/usr/bin/env bash
cd /root/my-app
pm2 start /root/my-app/node_modules/react-scripts/bin/react-scripts.js --name my-app -- start

上記のスクリプトはインスタンスの作成時に実行されるので、アプリケーションを起動するためにインスタンスに SSH 接続する必要はありません。

7、プレビューボタンをクリック
8、利用規約に同意し、「インスタンスの作成」ボタンをクリックします。
9、インスタンスが起動したら、インターネットの IP アドレスをコピーしてブラウザのアドレスバーに貼り付けます。ReactアプリケーションのWebページが表示されるはずです。
インスタンスを起動するプロセスを示すgif画像は以下の通りです。

アリババクラウドは日本に2つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
アリババクラウドジャパン公式ページ