在『服務器部署 Vue 和 Django 專案的全記錄』一文中,介紹了在服務器中使用 Nginx 部署前后端專案的程序,然而,當 Web 應用流量增多時,需要考慮負載均衡、流量分發、容災等情況,原生的部署方式通常難以滿足需求,此時,引入 Docker 部署多節點,能夠在單臺高性能服務器或服務器集群中搭建更完善的部署架構,
本文主要以 Vue 和 Django 專案為例介紹 Docker 部署的流程,稍帶 Docker 簡介和基礎的 Nginx 負載均衡配置,
Docker 簡介與安裝
簡單介紹 Docker 相關概念,具體需要讀者另外學一學,推薦『Docker-從入門到實踐』
Docker 是什么
Docker 是一個開源的應用容器引擎,可以讓開發者打包應用和依賴到一個輕量級、可移植的容器中,并發布到任何流行的 Linux 機器上,也可以實作虛擬化,容器使用沙箱機制,相互之間不存在介面,其與宿主機通過埠轉發進行通信,性能開銷低,
Docker 部署 Web 應用有以下優點:
- 容器適合持續集成和持續交付(CI/CD)流程
- 回應式部署和擴展,其可移植性和輕量級的特性支持實時擴展或拆除服務
- Docker 輕巧快速,支持開發者在同一機器上運行更多作業負載
Docker 作業流程
Docker 包括三個概念:
- 鏡像(Image):相當于一個 root 檔案系統,
- 容器(Container):鏡像和容器的關系類似于物件程式設計中的類和實體,鏡像是靜態的定義,容器是鏡像運行時的物體,容器可以被創建、啟動、停止、洗掉、暫停等,
- 倉庫(Repository):倉庫可看成一個代碼控制中心,用來保存鏡像,
Docker 的作業流程通常為:
- 從倉庫中拉取(pull)官方或基準鏡像
- 在 Dockerfile 中描述應用和安裝依賴的指令,構建鏡像
- 由鏡像創建和運行容器
Docker 安裝
見『Ubuntu 安裝 Docker 環境』.
部署架構
在不考慮多節點負載均衡時,本文的部署架構如下:
前后端專案分離部署,分別部署在兩個 Nginx 節點,對應兩個域名或兩個埠,
Nginx + Docker 部署前端
首先,Vue 專案打包為 dist 檔案夾,同目錄下新建 Dockerfile、vhosts.conf 檔案和 logs 檔案夾,作用見下列代碼塊中的注釋,
.
├── dist # Vue 專案打包用以部署的檔案夾
├── Dockerfile # 用于建立 Docker 鏡像
├── vhosts.conf # 容器中啟動 Nginx 服務的組態檔
└── logs # 映射容器中的 Nginx 日志目錄,以便在宿主機查看日志
Dockerfile 檔案內容:
# 設定基礎鏡像
FROM nginx:latest
#設定CTS時區
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone
# 將dist檔案中的內容復制到 /usr/share/nginx/html/ 這個目錄下面
COPY ./dist /usr/share/nginx/html/
#用本地的 vhosts.conf 配置來替換 nginx 鏡像里的默認配置
COPY vhosts.conf /etc/nginx/conf.d/vhosts.conf
vhosts.conf 檔案內容:
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/host.access.log main;
error_log /var/log/nginx/error.log error;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
構建 Docker 鏡像
在終端中輸入以下命令,根據 Dockerfile 構建鏡像,
docker build -f Dockerfile -t nginx/hsheng-mall:v1.0.0 .
# 鏡像名稱:nginx/hsheng-mall
# 版本號:v1.0.0
運行 Docker 容器
依據創建的鏡像 nginx/hsheng-mall:v1.0.0 運行容器,
docker run -d -p 8081:80 --name=hsheng-mall -v /home/hsheng/www/hsheng-mall/logs:/var/log/nginx nginx/hsheng-mall:v1.0.0
# 宿主機 8081 埠映射容器 80 埠
# 容器名稱:hsheng-mall
# 宿主機 /home/hsheng/www/hsheng-mall/logs 目錄映射容器 /var/log/nginx 目錄
# 鏡像名稱:nginx/hsheng-mall:v1.0.0
宿主機 Nginx 轉發
與原生 Nginx 部署類似,在 /etc/nginx/conf.d 目錄下創建組態檔 hsheng-mall.conf,內容如下:
server {
listen 443 ssl; # 埠,若部署 https 域名則為 443
server_name aaa.abc.com; # 域名或 IP
location / {
proxy_pass http://127.0.0.1:8081; # 轉發本機(宿主機) 8081 埠,已與 Docker 埠建立映射
proxy_redirect default;
}
ssl_certificate /home/hsheng/www/hsheng-mall/ssl_certs/aaa.abc.com_bundle.crt; # ssl證書絕對路徑
ssl_certificate_key /home/hsheng/www/hsheng-mall/ssl_certs/aaa.abc.com.key; # ssl證書私鑰絕對路徑
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
}
server {
listen 80;
server_name aaa.abc.com;
# 把http的域名請求轉成https
return 301 https://$host$request_uri;
}
而后重啟 Nginx 服務,即可通過 server_name 訪問 Docker 的應用服務,
sudo nginx -s reload
Nginx + Docker 部署 uWSGI 后端
專案部署目錄結構如下:
.
├── src # Django 專案原始碼
│ ├── manage.py
│ ├── requirements.txt # Python 專案依賴包
│ ├── uwsgi.ini # uWSGI 組態檔
│ ├── start.sh # Django 服務啟動腳本
| └── ...
├── Dockerfile # 用于建立 Docker 鏡像
└── logs # 映射容器中的 uWSGI 日志目錄,以便在宿主機查看日志
Dockerfile 檔案內容:
FROM python:3.8
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone
RUN mkdir -p /var/www/html/backend
COPY ./src /var/www/html/backend/
WORKDIR /var/www/html/backend
RUN pip install -i https://pypi.doubanio.com/simple uwsgi
RUN pip install -i https://pypi.doubanio.com/simple/ -r requirements.txt
# Windows環境下撰寫的start.sh每行命令結尾有多余的\r字符,需移除
RUN sed -i 's/\r//' ./start.sh
RUN chmod +x ./start.sh
uwsgi.ini 檔案內容:
[uwsgi]
socket = 0.0.0.0:8000 # 容器內 uWSGI 服務須為 0.0.0.0,以便與宿主機建立正常連接
project = backend
base = /var/www/html
base-app = hshengmall
chdir = %(base)/%(project)
wsgi-file = %(base)/%(project)/%(base-app)/wsgi.py
master = true
processes = 8
threads = 4
enable-threads = true
buffer-size = 65536
post-buffering = 32768
vacuum = true
pidfile = %(base)/uwsgi/%(project)-master.pid
daemonize = %(base)/uwsgi/uwsgi.log
chmod-socket = 664
# 設定一個請求的超時時間(秒),如果一個請求超過了這個時間,則請求被丟棄
harakiri = 300
# 當一個請求被harakiri殺掉會,會輸出一條日志
harakiri-verbose = true
start.sh 檔案內容:
python manage.py makemigrations&&
python manage.py migrate&&
uwsgi --ini /var/www/html/backend/uwsgi.ini
構建 Docker 鏡像
在終端中輸入以下命令,根據 Dockerfile 構建鏡像,
docker build -f Dockerfile -t python/hsheng-mall-backend:v1.0.0 .
運行 Docker 容器
依據創建的鏡像 python/hsheng-mall-backend:v1.0.0 運行容器,
docker run -it -p 8001:8000 --name=hsheng-mall-backend -v /home/hsheng/www/hsheng-mall-backend/logs:/var/www/html/uwsgi -d python/hsheng-mall-backend:v1.0.0
啟動服務
進入容器:
docker exec -it <container_id> /bin/bash
運行啟動腳本:
./start.sh
這樣即成功啟動了一個后端服務容器,若想做多節點負載均衡,可以修改埠映射關系,按上述步驟多創建和啟動幾個容器,
宿主機 Nginx 轉發
在 /etc/nginx/conf.d 目錄下創建組態檔 hsheng-mall-backend.conf,內容如下:
server {
listen 443 ssl;
server_name api-aaa.abc.com;
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass 127.0.0.1:8001; # 轉發本機(宿主機) 8001 埠,已與 Docker 埠建立映射
}
ssl_certificate /home/hsheng/www/hsheng-mall-backend/ssl_certs/api-aaa.abc.com_bundle.crt;
ssl_certificate_key /home/hsheng/www/hsheng-mall-backend/ssl_certs/api-aaa.abc.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
}
server {
listen 80;
server_name api-aaa.abc.com;
return 301 https://$host$request_uri;
}
而后重啟 Nginx 服務,即可通過 server_name 請求后端服務,
sudo nginx -s reload
*Nginx 負載均衡
簡略描述一個負載均衡的結構:Nginx + Docker 多節點部署架構,
前端節點為靜態節點,通常只需要單個節點即可,可使用 CDN 加速優化訪問,因此,當請求流量大時,主要通過增多后端 Docker+uWSGI 節點進行負載均衡,
為實作上圖架構,首先根據本文第四章節「Docker 部署 uWSGI 后端節點」創建和啟動 3 個 Docker 后端服務節點,分別映射至宿主機 8001 ~ 8003 埠,
而后,修改宿主機用于部署后端的 Nginx 組態檔,例如本文的 hsheng-mall-backend.conf,添加 upstream,修改后檔案內容應為:
upstream uwsgicluster {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
}
server {
listen 443 ssl;
server_name api-aaa.abc.com;
location / {
include /etc/nginx/uwsgi_params;
uwsgi_pass uwsgicluster # 轉發上游集群
}
ssl_certificate /home/hsheng/www/hsheng-mall-backend/ssl_certs/api-aaa.abc.com_bundle.crt;
ssl_certificate_key /home/hsheng/www/hsheng-mall-backend/ssl_certs/api-aaa.abc.com.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
}
server {
listen 80;
server_name api-aaa.abc.com;
return 301 https://$host$request_uri;
}
可以看到,與單節點不同之處在于,新增了 upstream 定義,并將 uwsgi_pass 修改為定義的 upstream 名稱,
在組態檔中,還能設定各個節點的權重分配等,此處不展開介紹,默認為輪詢方式,請求隨機派發到各節點,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/502341.html
標籤:架構設計
上一篇:經典設計原則 - SOLID
