+12

Deploy Reactjs Với Docker và Nginx lên Ubuntu Server

Tổng quan

Docker là một công cụ khá tuyệt vời và rất hữu ích trong việc triển khai các ứng dụng thông qua container, trong bài viết này mình xin chia sẻ phương pháp để deploy dự án Reactjs lên server Ubuntu sử dụng webserver Nginx hoàn toàn trên Docker.

Chuẩn bị

Trước tiên các bạn cần chuẩn bị:

  • Source code, nếu chưa có thì có thể tạo ở bước tiếp theo.
  • 1 server ubuntu version 16, 18 hoặc 20... đều được, nếu chưa có thì các bạn có thể tham khảo Sunteco Cloud, đang free trial cho tài khoản đăng ký mới.
  • 1 chút kinh nghiệm cơ bản về Docker và Nginx.

Chuẩn bị xong thì bắt tay vào việc thôi nào...

1.Source code

Tạo 1 project reactjs, nếu bạn đã có source code có thể bỏ qua bước này:

npx create-react-app react-deploy
cd react-deploy

Sau đó hãy thử run local:

npm start

Mở trình duyệt và bạn sẽ thấy project sẽ chạy ở port 3000 ( hoặc port khác nếu như port 3000 bị ứng dụng khác chiếm dụng ).

2.Cấu hình Dockerfile

Tại root project, chúng ta sẽ tạo 1 file với tên “Dockerfile” với nội dung:

# Build docker image.
# Sử dung node
FROM node:12 as node

# Khai báo tham số
ARG workdir=.
LABEL description="deploy react app"

# Khái báo workdir trong node.
WORKDIR /app

# Copy project vào trong workdir của node.
COPY ${workdir}/ /app/

# Cài đặt các thư viện node liên quan.
RUN npm install

# Chạy lệnh build.
RUN npm run build

# Sử dụng nginx
FROM nginx:1.12
# Copy folder đã được build vào folder chạy của nginx.
COPY --from=node /app/build/ /var/www/dist/

# Copy file cấu hình chạy cho nginx (file nginx.conf sẽ tạo ở bước tiếp theo)
COPY --from=node /app/nginx.conf /etc/nginx/nginx.conf

# Cài đặt curl cho câu lệnh check HEALTH
RUN apt-get update && apt-get install -y curl

# Kiểm tra trạng thái của container sau khi chạy
HEALTHCHECK --interval=1m --timeout=3s \
  CMD curl -f http://localhost || exit 1

CMD ["nginx", "-g", "daemon off;"]

3.Khởi tạo và cấu hình Nginx

Tại root project, chúng ta sẽ tạo 1 file với tên “nginx.conf” với nội dung:

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    fastcgi_read_timeout 500;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log main;
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    server {
            listen       80;
            listen  [::]:80;
            server_name  localhost;
            include /etc/nginx/default.d/*.conf;
            location / {
                    alias /var/www/dist/;
                    try_files $uri $uri/ /index.html;

                    add_header Cache-Control public;
                    add_header Cache-Control no-store;
                    add_header Cache-Control no-cache;

                    if_modified_since off;
                    add_header Last-Modified "";
                    expires off;
            }
    }
}

Trong file config của nginx sẽ xuất hiện khá nhiều concept, các bạn có thể search để tìm hiểu sâu hơn. Nhưng có 1 số concept cần quan tâm, đó là:

  • worker_processes: Thiết lập này định nghĩa số worker processes mà NGINX sẽ sử dụng. Bởi vì NGINX là đơn luồng (single threaded), nó thường bằng với số lõi CPU.

  • worker_connection: Đây là số lượng tối đa của các kết nối đồng thời cho mỗi worker process và nói cho các worker process của chúng ta có bao nhiêu người có thể được phục vụ đồng thời bởi NGINX.

  • access_log & error_log: Đây là những tệp tin mà NGINX sẽ sử dụng để log bất kỳ lỗi và số lần truy cập. Các bản ghi này thường được sử dụng để gỡ lỗi hoặc sửa chữa.

  • server: Là các khối block dùng để định nghĩa các server ảo để xử lý các request từ client của bạn. Mỗi client request sẽ được xử lý dựa trên cấu hình được xác định trong mỗi server. Do đó, NGINX cần quyết định server nào phù hợp nhất cho request đó. Các directive được sử dụng để quyết định server là:

    • listen: là sự kết hợp địa chỉ IP/port mà server này được thiết kế để respond. Nếu một request từ client phù hợp với các giá trị này, server này có khả năng sẽ được lựa chọn để xử lý kết nối.
    • server_name: directive này là một thành phần khác, dùng để chọn một server để xử lý. Nếu có nhiều server đáp ứng được directive listen, NGINX sẽ phân tích cú pháp header “Host” của request và lựa chọn server phù hợp.

Trong một block server, chúng ta có thể định nghĩa nhiều location context được sử dụng để quyết định cách xử lý các request từ client. Bất cứ khi nào một request đến, NGINX sẽ kiểm tra khớp URI tới một trong số các location context và xử lý nó cho phù hợp. Có nhiều directive quan trọng có thể được sử dụng trong location context , chẳng hạn như:

  • try_files: Sẽ cố gắng phục vụ các tệp tin tĩnh được tìm thấy trong thư mục được trỏ tới bởi directive gốc.
  • proxy_pass: Sẽ gửi request tới một proxy server cụ thể.
  • rewrite: Sẽ viết lại URI tới dựa trên một regular expression để một khối location có thể xử lý nó.

4.Run Docker local

Sau khi tạo xong nginx.confDockerfile thì chúng ta sẽ chạy thử dưới local thông qua Docker để xem thử kết quả nhé. Đầu tiên cần phải build Dockerfile thành image với câu lệnh cmd (mở cmd tại root project) :

docker build -t [image name]:[tag version] [path to dockerfile]

docker build -t  react-deploy .

Với câu lệnh trên thì chúng ta sẽ tạo 1 image với tên “react-deploy”, tag version để null nên tag mặc định sẽ là “latest” hoặc có thể sửa tag thành react-deploy:0.1 nếu muốn gắn tag 0.1 và path to dockerfile sẽ để “.” do cmd đang đứng tại project.

Lưu ý: Nếu các bạn dùng linux/ubuntu có thể sẽ gặp lỗi liên quan đến permission docker (như ảnh bên dưới).

Gặp lỗi này thì chúng ta chỉ cần cấp quyền cho docker theo câu lệnh:

sudo chown -R 1000 /var/run/docker.sock

Sau khi build image xong thì hãy kiểm tra trong list image:

docker images

Ở đây chúng ta sẽ thấy có 1 image tên react-deploy với tag là latest.

Tiếp theo chúng ta sẽ run image:

docker run -d -p 80:80 --name react-deploy-container react-deploy:latest

Với câu lệnh trên thì chúng ta sẽ run 1 container từ image “react-deploy:latest” với các option:

  • -d: Chạy container ở background, có nghĩa là khi chúng ta tắt cửa sổ cmd thì container vẫn sẽ chạy bình thường.

  • -p: Bind port của container vào port của host theo cú pháp: [port host]:[port container]

  • -–name: Tên của container, cụ thể ở đây là “react-deploy-container”.

Sau khi run image xong thì chúng ta sẽ kiểm tra xem container đã run thành công chưa nhé:

docker ps

Nếu thành công thì bạn sẽ thấy 1 container như hình và project sẽ run ở http://localhost mà không cần port 3000 nữa. Nếu đến bước này mà các bạn không thấy container thì có thể comment dưới bài viết để mình support nhé.

5.Triển khai lên server ubuntu

Đến bước này là chúng ta đã chạy thành công ở local, tiếp theo sẽ phải đưa mọi thứ lên server ubuntu. Có nhiều cách như push code lên git, copy file lên server thông qua SCP… Ở bài viết này thì mình sẽ sử dụng Docker Hub nhé.

Docker Hub là một dịch vụ do Docker cung cấp, cho phép tìm kiếm và chia sẻ các container images. Nếu chưa có tài khoản thì bạn có thể đăng ký tài khoản tại đây: https://hub.docker.com/

Sau khi tạo tài khoản xong thì chúng ta sẽ tạo 1 repository:

Tiếp theo cần phải login docker để push image vừa build từ local lên Docker hub:

docker login -u [username] -p [password]

Gắn tag cho image cần push:

docker tag [image name]:[tag] [repository]:[tag repository]

Cụ thể ở project chúng ta vừa build sẽ là:

docker tag react-deploy:latest manhlh231/deploy-nginx:0.2

Tiếp theo sẽ push tag lên Docker hub:

docker push manhlh231/deploy-nginx:0.2

Với câu lệnh trên, chúng ta vừa push image react-deploy với tag latest ở local lên repository manhlh231/deploy-nginx với tag 0.2 trên Docker hub.

Sau đó thử check trên repository Docker hub sẽ thấy tag 0.2 vừa push lên.

Sau khi push image thành công lên Docker hub thì chúng ta sẽ remote vào server Ubuntu để pull image về server.

ssh ubuntu@[ip server]
ssh ubuntu@103.9.211.66

Pull image:

docker pull manhlh231/deploy-nginx:0.2

Run image trên server:

docker run -d -p 80:80 --name reactv0.2 manhlh231/deploy-nginx:0.2

Kiểm tra kết quả tại địa chỉ của server!! http://103.9.211.66/

Cảm ơn các bạn đã theo dõi bài viết.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí