Shipit – Tự động deploy Javascript project

Bài viết được sự cho phép của tác giả Tùng Nguyễn

Để deploy 1 project Javascript đơn giản lên server (apache hoặc ngnix tuỳ sở thích các bạn) thì thường thường chúng ta phải làm các bước cơ bản như build local, zip file source, copy file zip lên server, unzip và chạy các câu lệnh cần thiết. Nếu lúc nào deploy chúng ta cũng tự làm mấy bước như thế này thì thật sự là khá mệt. Hôm nay tôi sẽ hướng dẫn các bạn cách deploy tự động 1 project Nodejs bằng Shipit. Thế Shipit là gì và sử dụng nó như thế nào,… tôi cũng sẽ giới thiệu luôn trong bài này luôn.

Shipit là gì?

Nói nôm na các bạn dễ hiểu, Shipit là công cụ tự động hoá các bước deploy dành cho các bạn Javascript developer. 1 dòng lệnh trong Shipit config ta coi như 1 task. Shipit sẽ thực hiện 1 flow tasks dựa trên package orchestrator, login và chạy các lệnh SSH trên server thông qua OpenSSH. Chúng ta có thể sử dụng Shipit để tự động hoá build và deploy cho hàng loạt các ứng dụng Nodejs.

Chuẩn bị:

Trong bài hướng dẫn này tôi sử dụng các tool như sau, các bạn có thể setup giống tôi hoặc thay thế bằng các tool, phần mềm tương tự cũng được:

  1. Server chạy Ubuntu hoặc Debian Linux và cài đặt rsync.
  2. Web server Apache.
  3. node và yarn được cài đặt trên môi trường development. Ở máy tôi đang cài Nodejs 14.19.0 và yarn 1.22.17 trên Ubuntu 21. Các bạn có thể tùy thích xài npm cũng được.
  4. Các bạn cũng cần cài rsync và git trên môi trường development.

  7 khái niệm Javascript cơ bản không thể bỏ qua

  Callback hell là gì? 6 cách “trị” callback hell trong javascript

Bước 1: Khởi tạo git repo

Cái này chắc ai cũng biết nên tôi sẽ không giới thiệu cách làm ở đây. Trong bài này tôi tạo 1 repo tên là Angular để cho các bạn dễ làm ví dụ, cũng như sau này các bài viết về Angular tôi cũng sẽ update vào đó để demo.

https://github.com/tungnt92/angular-demo.git

Bước 2: Cài đặt Shipit package

Việc đầu tiên cần làm chắc chắn là cài đặt Shipit vào project mà các bạn cần deploy. Ta thực hiện các bước như sau:

Tôi tạo 1 file package.json:

yarn init

Sau khi chạy command trên tôi được 1 file tên package.json như vầy, trong file này chứa các script như start application, build, clean up,… cũng như những thông tin cơ bản của application và các dependency cần thiết để chạy:

{
  "name": "angular-demo",
  "version": "1.0.0",
  "main": "index.js",
  "repository": "[email protected]:tungnt92/angular-demo.git",
  "author": "tungnt92 <[email protected]>",
  "license": "MIT"
}

Sau đó tôi bắt đầu cài đặt Shipit, tôi chạy command sau:

yarn add --dev shipit-cli
yarn add --dev shipit-deploy

Các bạn lưu ý tôi sử dụng --dev để chỉ cho yarn thấy rằng tôi muốn cài package này ở development dependency. File package.json của tôi có nội dung cuối cùng như sau, các bạn có thể làm theo các bước trên hoặc đơn giản là copy file này cho nhanh.

{
  "name": "angular-demo",
  "version": "1.0.0",
  "main": "index.js",
  "repository": "[email protected]:tungnt92/angular-demo.git",
  "author": "tungnt92 <[email protected]>",
  "license": "MIT",
  "devDependencies": {
    "shipit-cli": "^5.3.0",
    "shipit-deploy": "^5.3.0"
  }
}

Tham khảo việc làm JavaScript tại Hồ Chí Minh trên TopDev

Bước 3: Config shipit

Tôi đã viết sẵn 1 file shipit config với đầy đủ các chức năng mà tôi thấy cần thiết để deploy project javascipt nằm ở cuối bài viết. Các bạn có thể copy file này, sau đó sửa các config information cho phù hợp với project của mình.

Giờ tôi sẽ đi từng bước, đầu tiên tôi tạo file shipitfile.js ở root project với các init command sau:

module.exports = shipit => {
  require('shipit-deploy')(shipit)

  const stagingConfig = {
    deployUser: 'bitnami',
    key: 'doc/aws/server-staging.pem',
    deployTo: '/home/bitnami/htdocs/projects/',
  }

  // More default config goes here

  shipit.initConfig({
    staging: {
      ...stagingConfig,
      projectName: 'angular-demo',
      servers: ["[email protected]"],
    },
  })
}

Chỗ này các bạn lưu ý các config sau:

  • stagingConfig: tôi gom các config nào giống nhau ở các môi trường lại, mục đích cho gọn gàng và dễ import và chỉnh sửa khi cần.
  • staging: alias của server mà tôi sẽ deploy project của mình lên. Các server alias thường sử dụng như production, development,…
  • projectName: định danh tên của project, chỗ này sẽ dùng để xác định thư mục deploy.
  • key: trong trường hợp này tôi tạo folder ./doc/aws/ để chứa các server key. Các bạn nhớ thêm vào git ignore của mình.

Sau đó tôi viết thêm task cần thiết cho việc deploy như build project, setup remote server,…

...
shipit.task("angular:deploy", async () => {
    let zipFileName = `${shipit.config.projectName}.zip`

    // Zip the dist folder into dist.zip package then remove the folder as we don't need it anymore
    await shipit.local(`cd dist && zip -r ../${zipFileName} ${shipit.config.projectName}`);

    // Create deployTo folder if it's not existed
    await shipit.remote(
      `sudo mkdir -p ${shipit.config.deployTo} && sudo chown -R ${shipit.config.deployUser}: ${shipit.config.deployTo}`
    );

    // // Copy dist.zip to servers
    await shipit.copyToRemote(zipFileName, shipit.config.deployTo);

    // // Remove the dist.zip
    await shipit.local(`rm ${zipFileName}`);

    // // remove old frontend files
    await shipit.remote(`rm -rf ${shipit.config.deployTo}/${shipit.config.projectName}/*`);

    // // On server, unzip the dist.zip file then remove the zip package
    await shipit.remote(
      `cd ${shipit.config.deployTo} && unzip -o ${zipFileName} && rm ${zipFileName}`
    );
  });

Các config mà bạn cần lưu ý:

  • angular:deploy: tôi đặt tên cho task mà tôi sẽ gọi lúc deploy.
  • Các task khác tôi đã để comment vào rồi, các bạn đọc trên đó.

Cuối cùng ta được file config như sau:

module.exports = function (shipit) {
  // Load shipit-deploy tasks
  require("shipit-deploy")(shipit);

  const stagingConfig = {
    deployUser: 'bitnami',
    key: 'doc/aws/server-staging.pem',
    deployTo: '/home/bitnami/htdocs/projects/',
  }

  shipit.initConfig({
    staging: {
      ...stagingConfig,
      projectName: 'angular-demo',
      servers: ["[email protected]"],
    },
  })

  shipit.task("angular:deploy", async () => {
    let zipFileName = `${shipit.config.projectName}.zip`

    // Zip the dist folder into dist.zip package then remove the folder as we don't need it anymore
    await shipit.local(`cd dist && zip -r ../${zipFileName} ${shipit.config.projectName}`);

    // Create deployTo folder if it's not existed
    await shipit.remote(
      `sudo mkdir -p ${shipit.config.deployTo} && sudo chown -R ${shipit.config.deployUser}: ${shipit.config.deployTo}`
    );

    // // Copy dist.zip to servers
    await shipit.copyToRemote(zipFileName, shipit.config.deployTo);

    // // Remove the dist.zip
    await shipit.local(`rm ${zipFileName}`);

    // // remove old frontend files
    await shipit.remote(`rm -rf ${shipit.config.deployTo}/${shipit.config.projectName}/*`);

    // // On server, unzip the dist.zip file then remove the zip package
    await shipit.remote(
      `cd ${shipit.config.deployTo} && unzip -o ${zipFileName} && rm ${zipFileName}`
    );
  });
};

Đến đây về cơ bản tôi đã hoàn thành xong việc setup shipit. Tôi có thể deploy project lên môi trường staging bằng command sau:

./node_modules/.bin/shipit staging angular:deploy

Nhưng đặt trường hợp tôi muốn chạy thêm command gì đó ví dụ build application trước khi deploy, tôi phải chạy câu sau:

ng build angular --prod --aot && ./node_modules/.bin/shipit staging angular:deploy

Quá dài, việc ghi nhớ và gõ câu command dài như xe lửa như vậy với tôi là bất khả thi. Nên tôi làm thêm 1 bước là gom các command cần thiết vào cùng 1 file, sau này tôi chỉ cần execute file này khi muốn deploy, chỉnh sửa hay thêm bớt command cũng dễ dàng.

Tôi tạo folder sau ./deploy. Sau đó tạo file với tên theo cú pháp:

[project-name]-environment.sh

Ví dụ: angular-demo-staging.sh

Trong file đó tôi viết tất cả các command cần thiết vào:

#!/usr/bin/env bash
ng build angular --prod --aot && ./node_modules/.bin/shipit staging angular:deploy

Sau này bất cứ khi nào cần deploy staging tôi chỉ cần chạy command:

deploy/angular-demo-staging.sh

Chúc các bạn có thể có thêm chút kiến thức về auto deploy cho project javascript sử dụng shipit.

Happy Hacking

Bài viết gốc được đăng tải tại omatsuri.blog, biết thêm về tác giả tại LinkedIn

Xem thêm:

Đừng bỏ lỡ hàng loạt IT job tại TopDev