Creating a React JS Application Image with Packer and Ansible on Alibaba Cloud

Packer is an open source tool for creating identical machine images for multiple platforms from a single source configuration. Packer is lightweight, runs on every major operating system, and is highly performant, creating machine images for multiple platforms in parallel.

Ansible is an open source software that automates software provisioning, configuration management, and application deployment. Ansible connects via SSH, remote PowerShell or via other remote APIs.

In this guide, we will talk about using Packer to build a machine image on Alibaba Cloud Elastic Compute Service (ECS), and Ansible for writing what we want our machine image to have. We will be building an image that has a react JS application and nodejs setup. Machine image in DevOps is a single static unit that contains a pre-configured operating system and installed software which is used to quickly create new running machines. Machine image formats change for each platform.

Prerequisites

You don’t need to be an expert to follow this guide, All you need to have is an account on Alibaba Cloud and an Access key. Click on this link to see how to create an access key on Alibaba cloud.

Step 1: Install Packer

To install packer on our system, we can follow the official installation page for packer or use a package manager, chocolatey for windows and homebrew for macOS. Using a package manager saves us from the hassle of adding environment variables to path.

To install packer on windows using 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"
  • choco install packer
  • packer -v

A Gif image showing the installation process

Image for post
Image for post

To install packer on MacOS using homebrew

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

Gif image showing installation on MacOS

Image for post

Step 2: Build Our React-Application Machine Image

To build a machine image, we need to create a template file. The template file is used to define what image we want to build. The template file is in a JSON format and has a different set of keys configuring various components of Packer.

  • { "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" }] }
  • export ALICLOUD_SECRET_KEY="YOUR_ALICLOUD_ACCESS_KEY" export ALICLOUD_SECRET_KEY="YOUR_ALICLOUD_SECRET_KEY"
  • --- - 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

Step 3: Launch an Instance with Our React Image

To create an instance using the image we created earlier, follow the steps below

  • #!/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

Here is a gif image showing the process of launching an instance

Image for post
Image for post

Reference:https://www.alibabacloud.com/blog/creating-a-react-js-application-image-with-packer-and-ansible-on-alibaba-cloud_594131?spm=a2c41.12244944.0.0

Follow me to keep abreast with the latest technology news, industry insights, and developer trends.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store