+5

Deploy React App với Apache Httpd Server Container (Dockerize)

Mở đầu

Chào mọi người, chuyện là ở công ty, mình được giao deploy 1 dự án có thành phần Front end module được code bằng React App. Thông thường mình sẽ deploy nó với Nginx container như cách truyền thống, tuy nhiên lần này, dự án được 1 anh Senior của công ty (hiện đã out project) đề xuất trước với khách hàng dùng Apache Server để triển khai. Và đến hạn release bọn mình cũng không thể đề xuất thay đổi được.

Để giảm effort cho việc tạo tài liệu Deployment Guideline cho khách, cũng như giảm độ phức tạp trong quá trình deploy thông thường (cài đặt NodeJS, cài đặt Apache Server, npm install, npm build.... ). Mình đã đề xuất deploy system dưới dạng containers nhưng vẫn dùng apache server để host React App dưới dạng static web app.

Cấu trúc dự án

Dự án gồm 4 modules chính:

  • Microsoft SQL Server (customer side DB).
  • MySQL (local DB).
  • Spring Boot API Server.
  • ReactJS Application.

image.png

Files

Phần source code của dự án, mình chia các modules thành các folder riêng để quản lí:

└── PROJECT
	├── frontend-demo
	├── backend	
	├── db
		├── mysql
		└── mssql
	├── docker-compose.yml
	└── .....

React App File structures

Bên trong thư mục frontend-demo, mình tạo riêng 2 file cấu hình phục vụ cho việc triển khai Apache Httpd Server.

  • httpd.conf
  • .htaccess
└── frontend-demo
	├── public
	├── src
	├── index.html
	├── package.json
	├── vite.config
	├── Dockerfile
	├── httpd.conf
	├── .htaccess
	└── .....

httpd.conf

Tương đối giống với nginx.conf file, nếu bạn đã làm việc với Nginx rồi thì với Apache cũng tương tự. Chúng ta custom cấu hình Apache server bằng việc overwrite file httpd.conf này. Cụ thể, mọi người có thể overwrite lại các phần quan trọng như sau:

  • Bên trong httpd.conf, tìm đến và uncomment dòng LoadModule sau để enable mod_rewrite, mặc định mod_rewrite được disable bởi Apache.
#LoadModule rewrite_module modules/mod_rewrite.so 			#xóa dấu '#' đi
  • Tiếp tục chỉnh sửa dòng AllowOverride sau, đổi từ None sang chế độ All để cho phép ta override cấu hình.
DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">
	Options Indexes FollowSymLinks
	AllowOverride All #None -> All
	Require all granted
</Directory>
  • Save cấu hình này lại, để dành lúc chạy docker build, file này sẽ ghi đè nội dung xuống file httpd.conf của Apache container.

.htaccess

.htaccess (hypertext access) được dùng để cấu hình thêm các tính năng mà bạn mong muốn cho Apache Server. Với nó, bạn có thể cấu hình rewrite URL, password-protect directories, enable hotlink protection, disallow 1 IP nào đó, thay đổi website zone hoặc path đến file index.html ở directiory khác và còn nhiều hơn thế nữa.

  • Save file với nội dung sau:
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule . /index.html [L]
  • Đối với React sẽ là single page, tức là chỉ có 1 route duy nhất để hiển thị toàn bộ app. Với cấu hình như trên apache sẽ tự động truyền path cũng như param đến React App theo logic router đã code. Nếu không config mục này, Apache sẽ đi tìm các pages tương xứng với url và hiển thị trang trắng - error mặc định.

Dockerfile

Sau khi đã chuẩn bị 2 files: httpd.conf và .htaccess xong xuôi. Chúng ta cần soạn thảo lại nội dung Dockerfile bên trong folder Frontend code như sau:

FROM node:18-alpine as build-stage
WORKDIR /app
COPY package.json /app/package.json
RUN npm i

COPY . /app/
ARG VITE_BASE_URL
ENV VITE_BASE_URL $VITE_BASE_URL
RUN npm run build

# production stage with Apache httpd
FROM httpd:2.4.57-alpine as production-stage
COPY --from=build-stage /app/httpd.conf /usr/local/apache2/conf/httpd.conf
COPY --from=build-stage /app/dist /usr/local/apache2/htdocs/
COPY --from=build-stage /app/.htaccess /usr/local/apache2/htdocs/

Giải thích: Với cấu hình trên ta đã thực hiện

  • Copy ghi đè httpd.conf của ta vào file cấu hình của Apache tại directory: /usr/local/apache2/conf/httpd.conf
  • Copy file .htaccess vào directory /usr/local/apache2/htdocs/

File index.html sau khi build code cũng ở tại directory này, Apache sẽ đọc trực tiếp file index.html và truy cập các file trong thư directory trên.

VITE_BASE_URL là biến môi trường được thiết lập dynamic, tại đây nó là giá trị backend API server endpoint dùng để fetch API.

  • Apache container mặc định đã được thiết lập start Apache server ngay khi khởi chạy container qua lệnh httpd -D FOREGROUND . Chúng ta không cần chỉ dẫn thêm run command trong Dockerfile như Nginx.

docker-compose.yml

Cuối cùng, để khởi chạy quá trình deploy cả hệ thống, ta biên soạn 1 file docker-compose.yml để start cùng lúc các services với nhau, tại file trên mình khai báo trực tiếp URL backend, folder source code, port mapping,...

version: '3.8'
services:
	mysql: ...
	mssql: ...
	backend: ...
	frontend:
		container_name: frontend
		build:
			context: ./frontend-demo
			args:
				- VITE_BASE_URL=http://localhost:8080
		ports:
			- 80:80
		depends_on:
			- backend

Deploy commands

  • Để deploy cả system gồm 4 servies, ta mở terminal tại thư mục PROJECT - nơi chứa file docker-compose.yml và nhập lệnh cmd sau: docker compose up -d hoặc docker-compose up -d

docker-compose đã được thiết lập để khởi chạy theo thứ tự MSSQL -> MySQL -> Backend-> Frontend

  • Để deploy chạy từng service một (ex: only frontend), ta nhập lệnh: docker compose up frontend -d hoặc mở terminal tại folder frontend, chạy lệnh docker build -t frontend --build-arg VITE_BASE_URL=http://localhost:8080 . sau đó docker run --name frontend -p 80:80 -d frontend

Testing

  • Sau cùng, open browser với URL http:localhost (mình đang chạy ở port 80) để kiểm tra giao diện.

image.png

  • Navigate đến các page khác của trang web, F5 refresh lại để chắc rằng nó vẫn load đúng trang.

image.png

  • Nhập 1 trang lỗi bất kì ngoài các Route đã khai báo để chắc nó sẽ load đến trang Error Page bạn đã code.

image.png

Kết

Chúc mọi người thành công, nếu còn điều gì chưa hiểu hoặc có lỗi xảy ra, mọi người có thể để lại comment và feedback lại bên dưới. Thân.

PROJECT DEMO: Gitlab demo link


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í