- vừa được xem lúc

CI-CD Lab - Sử dụng Jenkins, Nginx deploy dự án ReactJS (UmiJS) lên AWS EC2

0 0 246

Người đăng: Quang Đỗ

Theo Viblo Asia

1. Lập trình viên không nên chỉ biết code

Lập trình viên phải biết sửa máy giặt, sửa điện, sửa ống nước, có người yêu ,.... và phải biết triển khai code lên internet. Khi đã biết triển khai code lên internet (được sếp đánh giá rất cao rồi ? ) thì lại phải học tiếp CI - CD để build và test code tự động giúp quá trình triển khai diễn ra với ít sự can thiệp thủ công nhất, tiết kiệm thời gian và chi phí ( sếp thích luôn ? ),. Bài này mình sẽ thực hiện triển khai một dự án ReactJS với source base mình dùng UmiJS ( một bộ base khá phổ biến cho một dự án ReactJS với đầy đủ các thứ trên đời), bạn nào sử dụng create-react-app hay bất cứ project ngôn ngữ gì vẫn có thể làm theo bài viết này vì bài này tập trung vào việc deploy và deploy tự động là chính. Trong bài này mình sẽ thực hiện deploy thủ công trước, sau đó sẽ tích hợp Jenkins CI-CD

2. Chuẩn bị môi trường

Có rất nhiều công cụ giúp bạn thực hiện việc áp dụng CI-CD cho dự án của bạn như CircleCI, Jenkins, TravisCI, GitLabCI, .... Trong bài này chúng ta sẽ sử dụng Jenkins.

  • Chuẩn bị:
    • Repository github với source code UmiJS: Có thể fork từ github của mình https://github.com/QuangDoXuan/react-base hoặc lấy trên trang chủ của UmiJS https://umijs.org/docs/getting-started. Các bạn tạo project của riêng mình rồi đẩy lên github, vì phần sau sẽ cần phải tiến hành cài đặt github-webhook cho chính repo này.
    • 2 AWS EC2 Ubuntu instances - một cái sử dụng để làm server chạy code của project, cái còn lại để chạy jenkins ( Sử dụng 1 instance cũng được nhưng do mình sử dụng EC2 instance free cấu hình hơi thấp ?) ). Bạn nào chưa có thì nên tạo tài khoản AWS rồi vào services EC2 để tạo nhé mất có 1đô thôi mà được sử dụng free cơ bản các chức năng của AWS trong vòng 1 năm.
    • Sau khi tạo 2 instance rồi thì chúng ta cần tiến hành mở cổng cho instance, đầu tiên kiểm tra xem từng instance đang sử dụng Security group nào ( trên màn danh sách các instance sẽ hiển thị thông tin của từng instance). Kéo sang phải đến gần cuối chúng ta sẽ thấy cột Securiry Group name - chính là tên của Security group ứng với instance. Tiếp theo chọn vào Security Groups, tìm đến đúng tên của group tương ứng chúng ta vừa thấy, chọn và click Actions -> Edit inbound rules và update như sau:

3. Deploy dự án lên AWS EC2

Trong bước này mình sẽ thực hiện deploy một cách thủ công trước, nếu ai chưa biết deploy thủ công Đầu tiên chúng ta sử dụng SSH để remote vào server nơi chúng ta cần để lưu trữ source code của dự án ssh -i key.pem _@.com ( x.x.x.x là public ip của EC2 instance của bạn khi tạo ra, key.pem là file key được tạo trong quá trình tạo instance giúp bạn có thể SSH vào instance và thực hiện việc cài đặt )

 $ sudo dnf install git-all $ sudo apt install git-all

Thường thì Ec2 sẽ cài sẵn git rồi, ta kiểm tra git --version nếu chưa có thì cài đặt bằng 2 lệnh trên

  • Cài đặt node và npm, yarn
    $ curl -sL https://deb.nodesource.com/setup_13.x | sudo -E bash -
    $ sudo apt-get install nodejs
    $ curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
    $ echo "deb https://dl.yarnpkg.com/debian/ stable main" |sudo tee /etc/apt/sources.list.d/yarn.list
    $ sudo apt update && sudo apt install yarn
    
  • Clone source code từ gitthub
$ cd /var/www/
$ sudo mkdir react-base
$ cd react-base
$ sudo mkdir html
$ cd html $ git clone your-github-project-repo-url 
  • Tiến hành build
$ cd /var/www/react-base/html/react-base
$ yarn install
$ yarn run build

Khi chạy lệnh yarn run build sẽ sinh ra một file index.js trong thư mục .dist trong dự án. Ta cần cấu hình Nginx trỏ đến file này là thành công trong việc deploy thủ công rồi ?

  • Cấu hình Nginx

    $ sudo vim /etc/nginx/sites-available/react-base Copy đoạn code dưới đây và lưu:

server { listen 80; server_name your_instance_ip; root /var/www/react-base/html/react-base/dist; index index.html index.htm; location / { try_files $uri /index.html =404; }
}

File config trên có ý nghĩa như sau: dự án được chạy ở cổng 80, với ip là public ip của instance của bạn. Nginx sẽ tìm đến đường dẫn /var/www/react-base/html/react-base/dist để đọc file có dạng index.js ( hoặc index.html, index.htm). File index.js này chính là file vừa được build ra từ câu lệnh yarn run build bước trên.

  • Tiếp theo cần enable file config mà bạn vừa tạo:

$ sudo ln -s /etc/nginx/sites-available/react-base /etc/nginx/sites-enabled

Restart Nginx

$ sudo systemctl restart nginx

Truy cập link http://x.x.x.x/ để kiểm tra

4. Tích hợp CI-CD sử dụng Jenkins

Đã xong việc deploy thủ công rồi, bây giờ chúng ta bắt đầu tiến hành tích hợp Jenkins.

1. Tiến hành SSH vào server thứ 2 và cài đặt Jenkins ssh -i key.pem _@.com_ip

  • Cài đặt java: Để cài đặt được Jenkins, chúng ta phải cài java trước
 $ sudo apt install default-jre $ java -version
  • Cài đặt Jenkins: Link này rất cụ thể và chi tiết, truy cập link này và làm theo hướng dẫn https://www.digitalocean.com/community/tutorials/how-to-install-jenkins-on-ubuntu-20-04 .Sau khi cài đặt thành công ta truy cập vào cổng 8080 của instance hiện tại để đăng nhập vào Jenkins ( nếu không truy cập được cổng 8080 thì tiến hành mở cổng bằng cách cấu hình Security Groups đã đề cập ở trên).

2. Setting github webhook Sau khi cài đặt xong Jenkins, ta tiến hành setting github webhook. Truy cập vào repo github nơi lưu trữ source code của dự án -> Settings ->Webhooks->Add Webhook. Điền payload url như sau : http://x.x.x.x:8080/github-webhook với x.x.x.x là ip server cài đặt jenkins của bạn

3. Tạo ssh-key trên server lưu trữ source code, sau đó copy nội dung của private key (file id_rsa)

$ ssh -i key.pem _@.com_ip
$ ssh-keygen -t rsa
$ cat ~/.ssh/id_rsa

Copy toàn bộ nội dung và paste vào một file text nào đó trên máy bạn. Ta cần tạo file key trên Jenkins server với nội dung này để khi Jenkins server thực hiện deploy sẽ cần dùng nó để SSH vào webServer (server lưu trữ source code của dự án).

4. Cấu hình Jenkins

  1. Truy cập Jenkins Dashboard-> New Item-> Free Style Project

  2. Tại tab Source Code Management, chọn Git, sau đó điền vào Repository Url là url github project của bạn (ví dụ: https://github.com/QuangDoXuan/react-base.git). Tại mục Credentials chọn Add-> **Kinds: Username and password **-> điền username và password github. ***

  3. Branch to build: điền tên nhánh bạn muốn sử dụng để deploy, ở đây mình chọn nhánh master.

  4. Tại tab Build Triggers, chọn GitHub hook trigger for GITScm polling

  5. Tại tab Build, paste đoạn code sau và nhấn Save:

ssh -i /home/jenkins/web-key.pem _@.com << EOF
cd /var/www/react-base/html/react-base
git pull origin master
yarn install
yarn run build

Đoạn code trên có ý nghĩa sau: Khi tiến hành bấm build để start quá trình build tự động, Jenkins server sẽ sử dụng user jenkins ( được tạo sẵn khi cài đặt jenkins) để SSH vào web server ( nơi lưu trữ source code) với key là web-key.pem (là nội dung file private key mà chúng ta đã backup ra 1 file text ở các bước trên) sau đó tiến hành chạy các lệnh để deploy như một người dùng thông thường.

6. Xong bây giờ nhấn Build xem đã ổn chưa nào ?, chắc chắn là chưa rồi, vì đã tạo private key đâu. Bây giờ chúng ta sẽ tiến hành tạo key để SSH vào server ( Nguyên lý là sau khi chúng ta gen SSH key ở các bước trên, nó sẽ tạo cho chúng ta 1 cặp public key và private key. Nội dung của file public key sẽ được tự động ghi vào trong file authorized_keys). Khi 1 client muốn SSH đến server, chỉ cần sử dụng file private-key làm key (giống với file pem của AWS), server sẽ so sánh nội dung public key trong file authorized_keys với file key mà chúng ta sử dụng để SSH xem chúng có phải 1 cặp không. Nếu đúng thì server sẽ cho phép truy cập ?.

7. Tạo private key với user jenkins SSH vào Jenkins server lại và thực hiện lần lượt các lệnh sau:

 $ sudo mkdir /home/jenkins $ cd /home/jenkins $ sudo nano web-key.pem
  • Mở lại file text đã copy từ các bước trên (file id_rsa đó ? ). Paste toàn bộ nội dung vào file web-key.pem và lưu
  • Kiểm tra xem user Jenkins đã thực sự SSH vào web server được chưa. Nếu được có nghĩa là bạn thành công 99% rồi đó ?, nếu ko được hãy quay lại bước trước để đọc lại kỹ phần copy privatekey từ web server và paste key ở Jenkins server nha
$ sudo su - jenkins
$ cd /home/jenkins
$ ssh -i web-key.pem _@.com_web_server_ip

OK giờ chúng ta quay lại và nhấn Build để tận hưởng thành quả thôi nào ?.

5. Tổng kết

Sau khi hoàn thành tất cả các bước trên, bạn hãy thử thay đổi code và commit lên github, sau đó merge code và truy cập lại Jenkins rồi bấm Build sẽ thấy code được build mới nhất mà chúng ta ko cần tốn công sức phải SSH vào server và chạy lệnh đúng không nào ?. Hi vọng bài viết sẽ giúp ích được cho mọi người trong quá trình triển khai code lên server cũng như làm việc với Jenkins và CI-CD. Good Luck Quên, các bạn nhớ stop 2 instance AWS EC2 này đi khi học xong rồi nha vì một tháng chỉ được dùng EC2 750 giờ miễn phí thôi, không là mất tiền oan đấy ?

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cùng tìm hiểu về các hook trong React hooks

Đối với ai đã từng làm việc với React thì chắc hẳn đã có những lúc cảm thấy bối rối không biết nên dùng stateless (functional) component hay là stateful component. Nếu có dùng stateful component thì cũng sẽ phải loay hoay với đống LifeCycle 1 cách khổ sở Rất may là những nhà phát triển React đã kịp

0 0 81

- vừa được xem lúc

Khi nào nên (và không nên) sử dụng Redux

. Công việc quản lý state với những hệ thống lớn và phức tạp là một điều khá khó khăn cho đến khi Redux xuất hiện. Lấy cảm hứng từ design pattern Flux, Redux được thiết kế để quản lý state trong các project JavaScript.

0 0 106

- vừa được xem lúc

ReactJS: Props và State

Nếu bạn đã học ReactJS hay React Native, bạn sẽ thấy các Props và State được sử dụng rất nhiều. Vậy chính xác chúng là gì? Làm thế nào để chúng ta sử dụng chúng đúng mục đích đây.

0 0 41

- vừa được xem lúc

State và Props trong Reactjs

Hello các bạn, tiếp tục seri tìm hiểu về ReactJs hôm nay mình xin giới thiệu đến các bạn hai thứ mình cho là thú vị nhất của ReactJs là State và Props. State bạn có thể hiểu đơn giản là một nơi mà bạn lưu trữ dữ liệu của Component, từ đó bạn có thể luân chuyển dữ liệu đến các thành phần trong Compon

0 0 36

- vừa được xem lúc

Memoization trong React

. 1.Introduction. Memoization có liên quan mật thiết đến bộ nhớ đệm, và dưới đây là một ví dụ đơn giản:. const cache = {}.

0 0 38

- vừa được xem lúc

Nâng cao hiệu suất React Hooks với React.memo, Memoization và Callback Functions

1.Ngăn Re-render và React.memo. React.

0 0 67