部署前後端為獨立的 Docker 節點

来源:https://www.cnblogs.com/zewanhuang/archive/2022/08/19/16601915.html
-Advertisement-
Play Games

在『伺服器部署 Vue 和 Django 項目的全記錄』一文中,介紹了在伺服器中使用 Nginx 部署前後端項目的過程。然而,當 Web 應用流量增多時,需要考慮負載均衡、流量分發、容災等情況,原生的部署方式通常難以滿足需求。此時,引入 Docker 部署多節點,能夠在單台高性能伺服器或伺服器集群中... ...


『伺服器部署 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 的工作流程通常為:

  1. 從倉庫中拉取(pull)官方或基準鏡像
  2. 在 Dockerfile 中描述應用和安裝依賴的指令,構建鏡像
  3. 由鏡像創建和運行容器

Docker 安裝

『Ubuntu 安裝 Docker 環境』.

部署架構

在不考慮多節點負載均衡時,本文的部署架構如下:

前後端項目分離部署,分別部署在兩個 Nginx 節點,對應兩個功能變數名稱或兩個埠。

deploy-structure

Nginx + Docker 部署前端

首先,Vue 項目打包為 dist 文件夾,同目錄下新建 Dockerfilevhosts.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 節點進行負載均衡。

deploy-structure-total

為實現上圖架構,首先根據本文第四章節「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 名稱。

在配置文件中,還能設置各個節點的權重分配等,此處不展開介紹,預設為輪詢方式,請求隨機派發到各節點。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • JSON.stringify()妙用 點擊打開視頻講解更加詳細 語法:JSON.stringify(value, replacer , space) value:將要序列化成 一個JSON 字元串的值。 replacer(可選):如果該參數是一個函數,則在序列化過程中,被序列化的值的每個屬性都會經過 ...
  • 想要項目快速迭代,輪子必不可少。normalize.css,element-plus,axios,moment,vue-router,less,前端必知必會的輪子你都知道嗎? ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 uni.login(OBJECT)登錄 H5平臺登陸註意事項: 微信內嵌瀏覽器運行H5版時,可通過js sdk實現微信登陸,需要引入一個單獨的js,詳見普通瀏覽器上實現微信登陸,並非開放API,需要向微信申請,僅個別開發者有此許可權H5平臺 ...
  • 本文是深入淺出 ahooks 源碼系列文章的第九篇,該系列已整理成文檔-地址。覺得還不錯,給個 star 支持一下哈,Thanks。 今天來看看 ahooks 是怎麼封裝 cookie/localStorage/sessionStorage 的。 cookie ahooks 封裝了 useCooki ...
  • 遞歸組件 點擊打開視頻講解更加詳細 組件是可以在它們自己的模板中調用自身的。不過它們只能通過 name 選項來做這件事: name: 'unique-name-of-my-component' 當你使用 Vue.component 全局註冊一個組件時,這個全局的 ID 會自動設置為該組件的 name ...
  • Iterator Iterator 概念 Iterator 提供了一種統一的介面機制,為各種不同數據結構提供統一的訪問機制。定義 Iterator 就是提供一個具有 next() 方法的對象,每次調用 next() 都會返回一個結果對象,該結果對象有兩個屬性,value 表示當前的值,done 表示 ...
  • 強制更新($forceUpdate) 點擊打開視頻講解更加詳細 在vue中,如果data中有基本數據類型變數:age,修改他,頁面會自動更新。 但如果data中的變數為數組或對象(引用數據類型),我們直接去給某個對象或數組添加屬性,頁面是識別不到的,不會同步更新; <template> <div i ...
  • Vue中組件通信方式有很多,其中Vue2和Vue3實現起來也會有很多差異;本文將通過選項式API 組合式API以及setup三種不同實現方式全面介紹Vue2和Vue3的組件通信方式。其中將要實現的通信方式如下表所示 | 方式 | Vue2 | Vue3 | | | | | | 父傳子 | props ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...