嘿!我很高兴与您分享如何配置 NestJS 以在单个主机上无缝工作。但首先,让我解释一下为什么这个设置长期以来一直是我管理前端和后端的首选。
Next.js 在启动新项目方面是一个强大的力量。它包含内置路由、服务器端渲染 (SSR) 和缓存等功能,可帮助您快速上手。此外,Next.js 拥有自己的内部 API 功能,让您可以在框架内管理缓存和数据准备等任务。这意味着您可以更多地专注于构建应用程序,而不是设置基础设施。
但有时您需要为服务器提供更强大的功能。这就是 Nest.js 的用武之地。这个框架非常强大,它不仅可以处理后端和前端之间的中间件职责,而且还可以单独充当强大的后端解决方案。因此,在这种情况下,NestJS 是 Next.js 的一个很好的补充,允许前端和后端使用单一编程语言。
简单地说,非常方便。只需 git pull 和 docker-compose up -d,您就可以开始了。无需担心 CORS 或杂乱端口。此外,它还简化了交付流程,使一切运行更加顺利和高效。作为缺点,我可以指出这不适合高负载的大型项目。
文件:./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 或杂乱端口。此外,它还简化了交付流程,使一切运行更加顺利和高效。作为缺点,我可以指出这不适合高负载的大型项目。
对于开发模式,我们不需要后端和前端的容器服务,因为我们将在本地运行它们。
文件:./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"
文件:./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"]
在此步骤中,我们将 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 后端。
由于我们使用相同的主机,我们需要 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();
前端无需配置,只需考虑所有服务器请求都应相对于 /api 路径调用。
cd 前端
npm 运行开发
cd ../后端
npm 运行开始:dev
光盘 ../
docker-compose -f docker-compose.dev.yml up -d
现在,我们可以通过在浏览器中打开 localhost 来检查我们的网站。在示例中,我们在服务器上有 1 个请求,在客户端上有另一个请求。这两个请求都是从 Next.Js 调用并由 Nest.Js 处理。
本文探讨了如何使用 Docker Registry 和 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’)
通过指定提交消息,可以仅重建您关注的图像。
文件:./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=
存储库:https://github.com/xvandevx/blog-examples/tree/main/nextjs-nestjs-deploy
本文是在单个服务器上一起部署 Next.js 和 Nest.js 的实践指南,使其成为想要简化设置的开发人员的首选解决方案。通过结合前端 Next.js 和后端 Nest.js 的优势,我展示了如何使用 Docker 和 GitHub Actions 高效管理应用程序的两个部分。它简化了部署过程,使您能够专注于构建应用程序,而不是处理多个配置。非常适合那些希望以最少的麻烦快速启动和运行全栈项目的人。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3