首頁  >  文章  >  web前端  >  將 NextJs 和 NestJs 部署為單一應用程式

將 NextJs 和 NestJs 部署為單一應用程式

WBOY
WBOY原創
2024-09-10 11:34:471062瀏覽

嘿那裡!我很高興與您分享如何配置 NestJS 以在單一主機上無縫運作。但首先,讓我解釋一下為什麼這個設定長期以來一直是我管理前端和後端的首選。

Next.js 在啟動新專案方面非常強大。它包含內建路由、伺服器端渲染 (SSR) 和快取等功能,可協助您快速上手。此外,Next.js 擁有自己的內部 API 功能,讓您可以在框架內管理快取和資料準備等任務。這意味著您可以更專注於建立應用程序,而不是設定基礎設施。

但有時您需要為伺服器提供更強大的功能。這就是 Nest.js 的用武之地。這個框架非常強大,它不僅可以處理後端和前端之間的中間件職責,而且還可以單獨充當強大的後端解決方案。因此,在這種情況下,NestJS 是 Next.js 的一個很好的補充,允許在前端和後端使用單一程式語言。

為什麼是單一主機?

簡單地說,非常方便。只需 git pull 和 docker-compose up -d,您就可以開始了。無需擔心 CORS 或雜亂連接埠。此外,它還簡化了交付流程,使一切運作更加順利和有效率。作為一個缺點,我可以指出這不適合高負載的大型專案。

1. 首先,讓我們定義儲存庫的資料夾結構

Deploy NextJs and NestJs as a single application

2.我們為伺服器聲明一個docker文件

檔案:./docker-compose.yml

services:
    nginx:
        image: nginx:alpine
        ports:
            - "80:80"
        volumes:
            - "./docker/nginx/conf.d:/etc/nginx/conf.d"
        depends_on:
            - frontend
            - backend
        networks:
            - internal-network
            - external-network

    frontend:
        image: ${FRONTEND_IMAGE}
        restart: always
        networks:
            - internal-network

    backend:
        image: ${BACKEND_IMAGE}
        environment:
            NODE_ENV: ${NODE_ENV}
            POSTGRES_HOST: ${POSTGRES_HOST}
            POSTGRES_USER: ${POSTGRES_USER}
            POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
            POSTGRES_DB: ${POSTGRES_DB}
        depends_on:
            - postgres
        restart: always
        networks:
            - internal-network

    postgres:
        image: postgres:12.1-alpine
        container_name: postgres
        volumes:
            - "./docker/postgres:/var/lib/postgresql/data"
        environment:
            POSTGRES_USER: ${POSTGRES_USER}
            POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
            POSTGRES_DB: ${POSTGRES_DB}
        ports:
            - "5432:5432"

networks:
    internal-network:
        driver: bridge

    external-network:
        driver: bridge

簡單地說,非常方便。只需 git pull 和 docker-compose up -d,您就可以開始了。無需擔心 CORS 或雜亂連接埠。此外,它還簡化了交付流程,使一切運作更加順利和有效率。作為缺點,我可以指出這不適合高負載的大型專案。

3.開發模式的另一個docker文件

對於開發模式,我們不需要後端和前端的容器服務,因為我們將在本地運行它們。

檔:./docker-compose.dev.yml

version: '3'

services:
    nginx:
        image: nginx:alpine
        ports:
            - "80:80"
        volumes:
            - "./docker/nginx/conf.d:/etc/nginx/conf.d"

    postgres:
        image: postgres:12.1-alpine
        container_name: postgres
        volumes:
            - "./docker/postgres:/var/lib/postgresql/data"
        environment:
            POSTGRES_USER: postgres
            POSTGRES_PASSWORD: postgres
            POSTGRES_DB: postgres
        ports:
            - "5432:5432"

4. 後端Docker文件

檔案:./backend/Dockerfile

FROM node:18-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json package-lock.json ./
RUN  npm install

FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

ENV NEXT_TELEMETRY_DISABLED 1

RUN npm run build

FROM node:18-alpine AS runner
WORKDIR /app

ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder --chown=nextjs:nodejs /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

RUN mkdir -p /app/backups && chown -R nextjs:nodejs /app/backups && chmod -R 777 /app/backups

USER nextjs

EXPOSE 3010

ENV PORT 3010

CMD ["node", "dist/src/main"]

## 5. Docker file for frontend
File: ./frontend/Dockerfile

FROM node:18-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json package-lock.json ./
RUN  npm install

FROM node:18-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

ENV NEXT_TELEMETRY_DISABLED 1

RUN npm run build

FROM node:18-alpine AS runner
WORKDIR /app

ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

USER nextjs

EXPOSE 3000

ENV PORT 3000

CMD ["npm", "start"]

6.Ngnix配置

在此步驟中,我們將 Nginx 設定為充當 Next.js 前端和 Nest.js 後端的反向代理。 Nginx 設定可讓您在前端和後端之間無縫路由請求,同時從同一台主機提供服務。

檔案:/docker/nginx/conf.d/default.conf

server {
    listen 80;

    location / {
        proxy_pass http://host.docker.internal:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /api {
        proxy_pass http://host.docker.internal:3010;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

此設定偵聽連接埠 80,並將一般流量路由至連接埠 3000 上的 Next.js 前端,而對 /api 的任何請求都會轉送至連接埠 3010 上的 Nest.js 後端。

7.NestJs全域前綴

由於我們使用相同的主機,我們需要 NestJs 在 /apipath 上可用。為此,我們需要 setGlobalPrefix — API。

檔案:./backend/src/main.js

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, { cors: true  });
  app.setGlobalPrefix('api');
  await app.listen(3010);
}
bootstrap();

8. 前端

前端無需配置,只需考慮所有伺服器請求都應該相對於 /api 路徑呼叫。

9.本地運行

cd 前端
npm run dev
cd ../後端
npm run start:dev
cd ../
docker-compose -f docker-compose.dev.yml up -d

現在,我們可以透過在瀏覽器中開啟 localhost 來檢查我們的網站。在範例中,我們在伺服器上有 1 個請求,在客戶端上有另一個請求。這兩個請求都是從 Next.Js 呼叫並由 Nest.Js 處理。

Deploy NextJs and NestJs as a single application

10.透過GitHub在伺服器上部署運行

本文探討如何使用 Docker 註冊表和 GitHub Actions 將專案部署到伺服器。這個過程首先在 Docker 註冊表中為後端和前端建立 Docker 映像。之後,您需要設定 GitHub 儲存庫並配置無縫部署所需的機密:

DOCKERHUB_USERNAME
DOCKERHUB_TOKEN
DOCKER_FRONTEND_IMAGE
DOCKER_BACKEND_IMAGE
REMOTE_SERVER_HOST
REMOTE_SERVER_USERNAME
REMOTE_SERVER_SSH_KEY
REMOTE_SERVER_SSH_PORT

為後端和前端使用同一個儲存庫的背後是,每次推送某些內容時,兩個鏡像都會重建。為了優化它,我們可以使用以下條件:

if: contains(github.event_name, ‘push’) && !startsWith(github.event.head_commit.message, ‘frontend’)
if: contains(github.event_name, ‘push’) && !startsWith(github.event.head_commit.message, ‘backend’)

它可以透過指定提交訊息來僅重建您關注的圖像。

File: ./github/workflows/deploy.yml

name: deploy nextjs and nestjs to GITHUB

on:
  push:
    branches: [ "main" ]

jobs:
  build-and-push-frontend:
    runs-on: ubuntu-latest

    if: contains(github.event_name, 'push') && !startsWith(github.event.head_commit.message, 'backend')

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push frontend to Docker Hub
        uses: docker/build-push-action@v2
        with:
          context: frontend
          file: frontend/Dockerfile
          push: true
          tags: ${{ secrets.DOCKER_FRONTEND_IMAGE }}:latest

      - name: SSH into the remote server and deploy frontend
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.REMOTE_SERVER_HOST }}
          username: ${{ secrets.REMOTE_SERVER_USERNAME }}
          password: ${{ secrets.REMOTE_SERVER_SSH_KEY }}
          port: ${{ secrets.REMOTE_SERVER_SSH_PORT }}
          script: |
            cd website/
            docker rmi -f ${{ secrets.DOCKER_FRONTEND_IMAGE }}:latest
            docker-compose down
            docker-compose up -d

  build-and-push-backend:
    runs-on: ubuntu-latest

    if: contains(github.event_name, 'push') && !startsWith(github.event.head_commit.message, 'frontend')

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push backend to Docker Hub
        uses: docker/build-push-action@v2
        with:
          context: backend
          file: backend/Dockerfile
          push: true
          tags: ${{ secrets.DOCKER_BACKEND_IMAGE }}:latest

      - name: SSH into the remote server and deploy backend
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.REMOTE_SERVER_HOST }}
          username: ${{ secrets.REMOTE_SERVER_USERNAME }}
          password: ${{ secrets.REMOTE_SERVER_SSH_KEY }}
          port: ${{ secrets.REMOTE_SERVER_SSH_PORT }}
          script: |
            cd website/
            docker rmi -f ${{ secrets.DOCKER_BACKEND_IMAGE }}:latest
            docker-compose down
            docker-compose up -d=

Repository: https://github.com/xvandevx/blog-examples/tree/main/nextjs-nestjs-deploy

Recap

This article is a hands-on guide to deploying Next.js and Nest.js together on a single server, making it a go-to solution for developers who want a streamlined setup. By combining the strengths of Next.js for frontend and Nest.js for backend, I showed how to efficiently manage both parts of your application using Docker and GitHub Actions. It simplifies the deployment process, allowing you to focus on building your app rather than juggling multiple configurations. Perfect for those looking to get a full-stack project up and running quickly with minimal hassle.

以上是將 NextJs 和 NestJs 部署為單一應用程式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn