自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何使用Docker將node項(xiàng)目部署到服務(wù)器并用pm2做負(fù)載均衡?

開(kāi)發(fā) 前端
本篇文章將以我們開(kāi)發(fā)好的后臺(tái)管理系統(tǒng)為例,介紹如何使用 docker 部署我們系統(tǒng)的后端Node服務(wù)到服務(wù)器上。

我們的后臺(tái)管理系統(tǒng)基本功能大致已經(jīng)完成了,接下來(lái)我們要做的就是把它部署到服務(wù)器上,讓用戶(hù)可以訪(fǎng)問(wèn)到我們的后臺(tái)管理系統(tǒng)。本篇文章將以我們開(kāi)發(fā)好的后臺(tái)管理系統(tǒng)為例,介紹如何使用 docker 部署我們系統(tǒng)的后端Node服務(wù)到服務(wù)器上。

docker 在前面的文章中已經(jīng)簡(jiǎn)單介紹過(guò)了,在 windows 系統(tǒng)上我們可以通過(guò)docker desktop來(lái)安裝和使用管理docker,非常方便。

Dockerfile

首先我們來(lái)了解一下什么是Dockerfile。

簡(jiǎn)單來(lái)說(shuō) Dockerfile 是一個(gè)文本文件,包含了一系列指令,用于自動(dòng)化創(chuàng)建 Docker 鏡像的過(guò)程。它定義了鏡像的基礎(chǔ)環(huán)境、所需的依賴(lài)、應(yīng)用程序的代碼以及如何運(yùn)行該應(yīng)用程序等等。比如一個(gè)簡(jiǎn)單的前端項(xiàng)目Dockerfile如下:

# 使用官方的 Node.js 鏡像作為基礎(chǔ)鏡像
FROM node:14-alpine
# 設(shè)置工作目錄
WORKDIR /app
# 復(fù)制 package.json 和 package-lock.json 到工作目錄
COPY package*.json .
# 安裝項(xiàng)目依賴(lài)
RUN npm install
# 復(fù)制項(xiàng)目代碼到工作目錄
COPY . .
# 構(gòu)建生產(chǎn)環(huán)境的應(yīng)用程序
RUN npm run build
# 暴露應(yīng)用程序的端口
EXPOSE3000
# 啟動(dòng)應(yīng)用程序
CMD ["node", "dist/main.js"]

然后我們就可以通過(guò)docker build -t <鏡像名稱(chēng)>:<標(biāo)簽> .將我們的項(xiàng)目打包成一個(gè)鏡像,就可以通過(guò)docker run [OPTIONS] <鏡像名稱(chēng)>:<標(biāo)簽>這個(gè)鏡像在任何地方運(yùn)行我們的項(xiàng)目了。

docker-compose

除了Dockerfile之外,我們還可以使用docker-compose來(lái)管理我們的項(xiàng)目。我們的后臺(tái)管理系統(tǒng)的后端服務(wù)有很多依賴(lài),比如數(shù)據(jù)庫(kù)、redis 等等,我們需要一個(gè)個(gè)拉取鏡像然后一個(gè)個(gè)的去構(gòu)建啟動(dòng)容器,有點(diǎn)麻煩。所以我們可以使用docker-compose來(lái)定義和管理多個(gè)Docker 容器,我們可以在一個(gè)docker-compose.yml文件中定義多個(gè)容器的配置,然后通過(guò)docker-compose up來(lái)啟動(dòng)所有的容器。比如一個(gè)簡(jiǎn)單的docker-compose.yml文件如下:

version: "1.0"# 指定 Docker Compose 文件的版本

services:# 定義服務(wù)部分
nest-app:# 服務(wù)名稱(chēng),表示 Nest.js 應(yīng)用
    build:# 構(gòu)建配置
      context:./# 構(gòu)建上下文,指定 Dockerfile 所在的目錄
      dockerfile:./Dockerfile# 指定 Dockerfile 的路徑
    depends_on:# 指定依賴(lài)關(guān)系,確保在啟動(dòng)此服務(wù)之前啟動(dòng)依賴(lài)的服務(wù)
      -mysql-container# 依賴(lài) MySQL 容器
      -redis-container# 依賴(lài) Redis 容器
    ports:# 端口映射
      -3000:3000# 將宿主機(jī)的 3000 端口映射到容器的 3000 端口
    networks:# 指定服務(wù)連接的網(wǎng)絡(luò)
      -common-network# 連接到名為 common-network 的網(wǎng)絡(luò)

mysql-container:# 服務(wù)名稱(chēng),表示 MySQL 數(shù)據(jù)庫(kù)
    image:mysql# 使用官方 MySQL 鏡像
    volumes:# 數(shù)據(jù)卷配置,用于持久化數(shù)據(jù)
      -E:/mysqlData:/var/lib/mysql# 將宿主機(jī)的 E:/mysqlData 目錄掛載到容器的 /var/lib/mysql 目錄
    environment:# 環(huán)境變量配置
      MYSQL_DATABASE:fs_admin# 創(chuàng)建的數(shù)據(jù)庫(kù)名稱(chēng)
      MYSQL_ROOT_PASSWORD:123456# MySQL 根用戶(hù)的密碼
    networks:# 指定服務(wù)連接的網(wǎng)絡(luò)
      -common-network# 連接到名為 common-network 的網(wǎng)絡(luò)
    ports:# 端口映射
      -3307:3306# 將宿主機(jī)的 3307 端口映射到容器的 3306 端口

redis-container:# 服務(wù)名稱(chēng),表示 Redis 數(shù)據(jù)庫(kù)
    image:redis# 使用官方 Redis 鏡像
    networks:# 指定服務(wù)連接的網(wǎng)絡(luò)
      -common-network# 連接到名為 common-network 的網(wǎng)絡(luò)
    ports:# 端口映射
      -6379:6379# 將宿主機(jī)的 6379 端口映射到容器的 6379 端口

networks:# 定義網(wǎng)絡(luò)部分
common-network:# 自定義網(wǎng)絡(luò)名稱(chēng)
    driver:bridge# 使用橋接網(wǎng)絡(luò)驅(qū)動(dòng)

然后我們就可以通過(guò)docker-compose up來(lái)啟動(dòng)所有的容器了,之后將我們的項(xiàng)目部署到服務(wù)器上也可以直接執(zhí)行docker-compose up就把所有的容器都啟動(dòng)部署了。

編寫(xiě)后端項(xiàng)目 Dockerfile

接下來(lái)看一下我們的后臺(tái)管理系統(tǒng)的后端服務(wù)的Dockerfile如何寫(xiě):

  1. 要拉取node鏡像,因?yàn)槲覀兊暮蠖朔?wù)是基于node的。
  2. 我們需要設(shè)置在 docker 中的工作目錄。(/app)
  3. 將項(xiàng)目的package.json復(fù)制到工作目錄中。
  4. 執(zhí)行npm install安裝項(xiàng)目的依賴(lài)。
  5. 將項(xiàng)目的代碼復(fù)制到工作目錄中。
  6. 執(zhí)行npm run build構(gòu)建生產(chǎn)環(huán)境的應(yīng)用程序。
  7. 暴露應(yīng)用程序的端口。
  8. 啟動(dòng)應(yīng)用程序。
FROM node:18.0-alpine3.14

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

RUN npm run build
EXPOSE 3000
CMD ["npm", "run","prod"]

但是這樣做會(huì)有一個(gè)問(wèn)題,就是我們把項(xiàng)目的代碼都復(fù)制到 docker 的工作目錄中,這樣會(huì)導(dǎo)致構(gòu)建鏡像的大小變大,其實(shí)構(gòu)建 docker 鏡像中只需要打包后的dist文件以及一些生產(chǎn)環(huán)境的依賴(lài)就行了,這時(shí)候我們?cè)撛趺醋瞿?這里就要用到Docker的多階段構(gòu)建了。

我們將前面一部分構(gòu)建作為第一階段命名為build-stage,第一階段構(gòu)建完后我們將其dist、package.json、以及我們生產(chǎn)環(huán)境所需的.env.prod復(fù)制到第二階段production-stage中,然后設(shè)置工作目錄、環(huán)境變量、安裝依賴(lài)、暴露端口等即可。

FROM node:18.0-alpine3.14 as build-stage

WORKDIR /app

COPY package.json .

RUN npm config set registry https://registry.npmmirror.com/

RUN npm install

COPY . .

RUN npm run build

# production stage
FROM node:18.0-alpine3.14 as production-stage

COPY --from=build-stage /app/dist /app/dist
COPY --from=build-stage /app/package.json /app/package.json
COPY --from=build-stage /app/.env.prod /app/.env.prod

WORKDIR /app

# 環(huán)境變量
ENV NODE_ENV production

RUN npm config set registry https://registry.npmmirror.com/

RUN npm install

EXPOSE3000

CMD ["npm", "run","prod"]

這樣我們就完成了我們的后端服務(wù)的Dockerfile的編寫(xiě)了。

docker-compose 配置

項(xiàng)目的鏡像構(gòu)建完成后,我們還需要配置docker-compose.yml文件來(lái)管理我們的項(xiàng)目。在docker-compose.yml我們可以通過(guò)${環(huán)境變量}來(lái)獲取環(huán)境變量的值,默認(rèn)取的是.env文件中的值,生產(chǎn)環(huán)境中我們可以通過(guò)--env-file來(lái)指定環(huán)境變量的文件,比如我們的項(xiàng)目的環(huán)境變量文件是.env.prod,我們就可以通過(guò)docker compose --env-file .env.prod up來(lái)啟動(dòng)我們的項(xiàng)目。

version: "1.0"
services:
nest-app:
    build:
      context:./
      dockerfile:./Dockerfile
    depends_on:
      -mysql-container
      -redis-container
    ports:
      -3000:3000
    networks:
      -common-network
    volumes:
      -${APP_PATH}:/app/static
mysql-container:
    image:mysql
    volumes:
      -${MYSQL_DATA_PATH}:/var/lib/mysql
    environment:
      MYSQL_DATABASE:${DB_DATABASE}
      MYSQL_ROOT_PASSWORD:${DB_PASSWD}
    networks:
      -common-network
    ports:
      -3307:${DB_PORT}# 顯式映射 MySQL 端口
redis-container:
    image:redis
    volumes:
      -${REDIS_DATA_PATH}:/data
    networks:
      -common-network
    ports:
      -6379:${RD_PORT}# 顯式映射 Redis 端口
networks:
common-network:
    driver:bridge

其中volumes是配置掛載的目錄,可以將宿主機(jī)的目錄掛載到容器的目錄中,這樣容器重新啟動(dòng)后,容器中的目錄中的文件不會(huì)丟失。比如mysql的數(shù)據(jù)、redis的數(shù)據(jù)、nest上傳的靜態(tài)文件等等。這些變量我們可以在.env.prod文件中配置。

# 數(shù)據(jù)庫(kù)配置 # 數(shù)據(jù)庫(kù)地址 DB_HOST=mysql-container # 數(shù)據(jù)庫(kù)端口 DB_PORT=3306 # 數(shù)據(jù)庫(kù)登錄名 DB_USER=root # 數(shù)據(jù)庫(kù)名稱(chēng) DB_DATABASE=fs_admin # 數(shù)據(jù)庫(kù)登錄密碼 DB_PASSWD=xxx # 數(shù)據(jù)庫(kù)Data保存路徑 MYSQL_DATA_PATH=/fsAdmin/mysqlData # redis配置 RD_HOST=redis-container # redis端口 RD_PORT=6379 # redis Data保存路徑 REDIS_DATA_PATH=/fsAdmin/redisData # JWT配置 JWT_SECRET=xxxx # JWT過(guò)期時(shí)間 JWT_EXP=2h # 上傳文件域名配置 FILESAVEURL=http://xxx xxx:3000/ # 上傳文件保存路徑 APP_PATH=/fsAdmin/files

我們會(huì)發(fā)現(xiàn)我們的數(shù)據(jù)庫(kù) DB_HOST 和 redis 的 RD_HOST 都是容器的名稱(chēng),這是因?yàn)槲覀兊娜萜魇峭ㄟ^(guò)docker-compose.yml文件來(lái)管理的,我們將其配置在了同一個(gè)橋接網(wǎng)絡(luò),所以我們可以通過(guò)容器的名稱(chēng)來(lái)訪(fǎng)問(wèn)容器的服務(wù)。

注意:如果我們的項(xiàng)目是開(kāi)源項(xiàng)目,就比如我這個(gè)項(xiàng)目,我們是不能吧.env.prod 上傳到 git 上的,不然你的數(shù)據(jù)庫(kù)密碼等私密信息就會(huì)被別人獲取到,所以這個(gè)文件我會(huì)在服務(wù)器上進(jìn)行配置。

負(fù)載均衡

我們都知道 nodejs 是單線(xiàn)程的,所以我們需要使用負(fù)載均衡的工具來(lái)提高我們的服務(wù)的并發(fā)能力。這里我們選擇pm2為我們的服務(wù)開(kāi)啟多個(gè)進(jìn)程。pm2用法其實(shí)很簡(jiǎn)單,首先在項(xiàng)目中安裝pm2,當(dāng)然你也可以全局安裝。然后再記住它的幾個(gè)命令即可。

這里我們使用配置文件的形式來(lái)配置pm2。我們直接使用命令pm2 init simple即可生成一個(gè)簡(jiǎn)單的配置文件ecosystem.config.js,然后我們配置一下。

module.exports = {
  apps: [
    {
      name: "Nest_APP", //應(yīng)用名稱(chēng)
      log_date_format: "YYYY-MM-DD HH:mm:ss", //日志格式
      script: "dist/main.js", //啟動(dòng)文件
      out_file: "./log/file.log", //日志文件
      error_file: "./log/file_error.log", //錯(cuò)誤日志文件
      autorestart: true, //是否自動(dòng)重啟
      instances: "max", //要啟動(dòng)實(shí)例的數(shù)量即負(fù)載數(shù)量,max表示根據(jù)cpu的進(jìn)程數(shù)來(lái)設(shè)置
    },
  ],
};

然后我們?cè)?/span>package.json中修改一下npm run prod的腳本,同時(shí)添加pm2的幾個(gè)命令用于測(cè)試使用。

"scripts": {
    "prod": "pm2 start && pm2 logs",
    "pm2:delete": "pm2 delete all",
    "pm2:stop": "pm2 stop all",
    "pm2:restart": "pm2 restart all",
  },

注意啟動(dòng)時(shí)加了一個(gè)命令 pm2 logs 是因?yàn)?docker 部署 pm2 啟動(dòng)的程序時(shí)不能直接讓 pm2 后臺(tái)運(yùn)行,因?yàn)?docker 需要一個(gè)阻塞控制臺(tái)的進(jìn)程,才可以持續(xù)運(yùn)行,否則會(huì)關(guān)閉,所以執(zhí)行的時(shí)候加一條輸出日志的命令用于阻塞控制臺(tái)進(jìn)程,docker 容器才不會(huì)關(guān)閉。

最后修改一下Dockerfile,將 pm2 配置文件也復(fù)制到容器。

圖片

此時(shí)我們就完成了 pm2 負(fù)載均衡的配置了。

本地部署

在部署服務(wù)器之前,我們先在本地部署測(cè)試一下有沒(méi)有問(wèn)題。我們直接在當(dāng)前項(xiàng)目下執(zhí)行docker compose --env-file .env.prod up看一下。

圖片

可以看到本地正常啟動(dòng)了,然后隨便訪(fǎng)問(wèn)一個(gè)接口,可以看到數(shù)據(jù)正常返回。

圖片

說(shuō)明我們的后端服務(wù)已經(jīng)使用 docker 在本地部署成功了。注意這時(shí)候數(shù)據(jù)庫(kù)中的表是不會(huì)自動(dòng)創(chuàng)建的,需要我們手動(dòng)將開(kāi)發(fā)環(huán)境的表結(jié)構(gòu)同步到部署環(huán)境。

同時(shí)控制臺(tái)執(zhí)行docker ps可以查看到我們的三個(gè)容器正在運(yùn)行。

圖片

或者直接在docker desktop中也可以看到。

圖片

如果你構(gòu)建過(guò)程出現(xiàn)了問(wèn)題,需要修改再構(gòu)建的話(huà)最好先執(zhí)行docker compose down --rmi all來(lái)停止并刪除Docker Compose 項(xiàng)目中的所有服務(wù),然后再執(zhí)行docker compose --env-file.env.pr up來(lái)重新構(gòu)建。

服務(wù)器部署

想要部署到服務(wù)器首先要有一臺(tái)自己的服務(wù)器,這里以阿里云服務(wù)器為例我購(gòu)買(mǎi)一個(gè)便宜的輕量應(yīng)用服務(wù)器。

圖片

應(yīng)用鏡像選 docker,這樣就不用再在服務(wù)器上手動(dòng)安裝 doker 了。系統(tǒng)鏡像選擇你喜歡的就行,這里我選擇第一個(gè)阿里云的 Linux 系統(tǒng)。

圖片

下單購(gòu)買(mǎi)之后我們就擁有了一臺(tái)自己的服務(wù)器了。進(jìn)入控制臺(tái)就能看到我們的服務(wù)器了。點(diǎn)擊進(jìn)去就可以進(jìn)行遠(yuǎn)程連接登錄我們的服務(wù)器了。

圖片

連接成功就進(jìn)入了服務(wù)器的終端界面。

圖片

接下來(lái)就是將我們的項(xiàng)目部署到服務(wù)器上了。我們新建一個(gè)文件夾fsAdmin來(lái)存放我們的項(xiàng)目mkdir fsAdmin,然后進(jìn)入文件夾cd fsAdmin。用 git 將項(xiàng)目克隆到這個(gè)目錄下git clone 你的項(xiàng)目倉(cāng)庫(kù)地址。

圖片

clone 完成之后進(jìn)入我們的后臺(tái)項(xiàng)目cd fs-admin/admin_nest,我們前面提到過(guò)生產(chǎn)環(huán)境的配置文件.env.prod是不在 git 上的,因此在服務(wù)器上我們需要手動(dòng)創(chuàng)建這個(gè)文件,并且配置好環(huán)境變量。所以我們需要在 Linux 上安裝一個(gè)編輯器,這里我選擇的是nano,執(zhí)行sudo yum install nano(根據(jù)你的 Linux 發(fā)行版本不同可能安裝方式有所差異)即可完成安裝。

安裝完成之后我們就可以使用nano .env.prod來(lái)創(chuàng)建或打開(kāi)這個(gè)文件了,然后將生產(chǎn)環(huán)境的配置復(fù)制到這個(gè)文件中即可。

圖片

到這里我們的前置操作就完成了。接下來(lái)我們就可以直接使用sudo docker compose --env-file.env.prod up來(lái)啟動(dòng)我們的項(xiàng)目了。不出意外的話(huà)應(yīng)該是可以啟動(dòng)成功的。 

圖片

此時(shí)我們的后端項(xiàng)目就已經(jīng)部署到服務(wù)器了,但是此時(shí)我們還是訪(fǎng)問(wèn)不到我們的接口的,因?yàn)槲覀兊姆?wù)器是在阿里云的,我們需要在阿里云的控制臺(tái)中配置一下安全組。因?yàn)槲覀冇玫氖禽p量應(yīng)用服務(wù)器,所以這里我們配置一下防火墻就行,我們需要在防火墻中添加一條規(guī)則,允許我們的服務(wù)器的 3000 端口和數(shù)據(jù)庫(kù) 3007 端口訪(fǎng)問(wèn)。直接點(diǎn)擊實(shí)例 id,然后點(diǎn)擊防火墻將 3000 端口和 3007 端口添加進(jìn)去即可。

圖片

這里解釋一下為什么是 3007 而不是 3006? 因?yàn)槲覀兊?mysql 在 docker 中的端口是 3006,而它映射到宿主機(jī)也就是我們服務(wù)器上的端口是 3007。這是在docker-compose.yml中配置的。

圖片

此時(shí)我們就應(yīng)該可以直接使用服務(wù)器公網(wǎng) ip+3000端口訪(fǎng)問(wèn)我們的接口了并且可以使用3007 來(lái)連接數(shù)據(jù)庫(kù)了。

圖片

最后我們需要將數(shù)據(jù)庫(kù)的數(shù)據(jù)表及基本的數(shù)據(jù)也同步到服務(wù)器上,因?yàn)闉榱税踩鹨?jiàn),線(xiàn)上數(shù)據(jù)表不會(huì)像開(kāi)發(fā)環(huán)境中自動(dòng)創(chuàng)建。

我們可以使用數(shù)據(jù)庫(kù)連接工具根據(jù)線(xiàn)上數(shù)據(jù)庫(kù)域名端口及密碼連接到線(xiàn)上數(shù)據(jù)庫(kù),然后將數(shù)據(jù)表及基礎(chǔ)數(shù)據(jù)導(dǎo)入。sql我已經(jīng)放在github上的項(xiàng)目中了fs_admin.sql,直接導(dǎo)入即可。管理員賬戶(hù)及密碼為admin 123456

源碼地址:https://github.com/qddidi/fs-admin

責(zé)任編輯:龐桂玉 來(lái)源: web前端進(jìn)階
相關(guān)推薦

2017-05-10 09:40:57

Ubuntupm2Nginx

2010-11-19 12:53:53

梭子魚(yú)負(fù)載均衡

2009-01-10 18:53:01

服務(wù)器ServerDNS

2015-09-06 09:53:41

DockerWeave

2010-04-28 11:22:46

2022-03-26 13:31:18

項(xiàng)目node變量

2018-10-26 09:52:25

Nginx服務(wù)器負(fù)載均衡

2011-11-22 21:26:59

pfSense配置Web服務(wù)器負(fù)載均衡

2010-05-05 18:44:27

服務(wù)器負(fù)載均衡

2010-05-05 18:28:16

負(fù)載均衡服務(wù)器

2021-09-07 22:19:00

服務(wù)器Pm2磁盤(pán)

2013-12-13 09:52:58

VDI服務(wù)器負(fù)載均衡

2019-12-10 10:23:57

Node.jsCluster前端

2010-05-06 14:15:02

流媒體服務(wù)器負(fù)載均衡

2009-04-20 14:00:57

2010-03-16 16:26:58

nginxWeb緩存服務(wù)器負(fù)載均衡服務(wù)器

2009-07-22 10:25:37

2010-05-10 14:02:53

服務(wù)器負(fù)載均衡

2011-12-31 09:49:30

MavenJava

2013-09-10 10:08:41

部署GPU服務(wù)器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)