Ei! Estou animado em compartilhar como você pode configurar o NestJS para funcionar perfeitamente em um único host. Mas primeiro, deixe-me explicar por que essa configuração tem sido minha principal escolha para gerenciar front-end e back-end por tanto tempo.
Next.js é uma potência quando se trata de iniciar novos projetos. Ele vem com recursos como roteamento integrado, renderização no servidor (SSR) e cache que ajudam você a começar a trabalhar. Além disso, Next.js tem seus próprios recursos de API internos, permitindo gerenciar tarefas como cache e preparação de dados diretamente na estrutura. Isso significa que você pode se concentrar mais na construção do seu aplicativo e menos na configuração da infraestrutura.
Mas às vezes você precisa de algo mais poderoso para o servidor. É aí que entra o Nest.js. Essa estrutura é tão poderosa que pode lidar não apenas com as tarefas de middleware entre seu back-end e front-end, mas também pode atuar como uma solução de back-end robusta por conta própria. Portanto NestJS é uma boa adição ao Next.js neste caso, permitindo o uso de uma única linguagem de programação para frontend e backend.
Simplificando, é incrivelmente conveniente. Com apenas um git pull e um docker-compose up -d, você está pronto para começar. Não há necessidade de se preocupar com CORS ou malabarismo com portas. Além disso, agiliza o processo de entrega, fazendo com que tudo corra de maneira mais tranquila e eficiente. Como desvantagem, posso apontar que isso não é adequado para grandes projetos com alta carga.
Arquivo: ./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
Simplificando, é incrivelmente conveniente. Com apenas um git pull e um docker-compose up -d, você está pronto para começar. Não há necessidade de se preocupar com CORS ou malabarismo com portas. Além disso, agiliza o processo de entrega, fazendo com que tudo corra de maneira mais tranquila e eficiente. Como desvantagem, posso apontar que isso não é adequado para grandes projetos com alta carga.
Para o modo de desenvolvimento, não precisamos de serviço de contêiner para back-end e front-end porque iremos executá-los localmente.
Arquivo: ./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"
Arquivo: ./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"]
Nesta etapa, configuramos o Nginx para atuar como um proxy reverso para nosso frontend Next.js e backend Nest.js. A configuração do Nginx permite encaminhar solicitações perfeitamente entre o front-end e o back-end, ao mesmo tempo em que as atende no mesmo host.
Arquivo: /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; } }
Esta configuração escuta na porta 80 e roteia o tráfego geral para o frontend Next.js na porta 3000, enquanto quaisquer solicitações para /api são encaminhadas para o backend Nest.js na porta 3010.
Como usamos o mesmo host, precisamos que os NestJs estejam disponíveis em /apipath. Para fazer isso, precisamos setGlobalPrefix — API.
Arquivo: ./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();
Nenhuma configuração é necessária no frontend, mas apenas levando em consideração que todas as solicitações do servidor devem ser chamadas em relação ao caminho /api.
front-end do CD
npm executar desenvolvedor
cd ../backend
início de execução npm:dev
cd ../
docker-compose -f docker-compose.dev.yml up -d
Agora podemos verificar nosso site abrindo localhost no navegador. No exemplo temos 1 requisição no servidor e outra no cliente. Ambas as solicitações são chamadas de Next.Js e processadas por Nest.Js.
Este artigo explora como implantar um projeto em um servidor usando Docker Registry e GitHub Actions. O processo começa com a criação de imagens Docker para back-end e front-end no Docker Registry. Depois disso, você precisará configurar um repositório GitHub e configurar os segredos necessários para uma implantação perfeita:
DOCKERHUB_USERNAME
DOCKERHUB_TOKEN
DOCKER_FRONTEND_IMAGE
DOCKER_BACKEND_IMAGE
REMOTE_SERVER_HOST
REMOTE_SERVER_USERNAME
REMOTE_SERVER_SSH_KEY
REMOTE_SERVER_SSH_PORT
A desvantagem de usar um repositório para backend e frontend é que cada vez que você envia algo, ambas as imagens são reconstruídas. Para otimizá-lo, podemos usar estas condições:
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’)
Torna possível reconstruir apenas a imagem que você atende especificando a mensagem de commit.
Arquivo: ./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=empregos: front-end de construção e push: executado: ubuntu-mais recente if: contém(github.event_name, 'push') && !startsWith(github.event.head_commit.message, 'backend') passos: - nome: Check-out usa: ações/checkout@v3 - nome: Faça login no Docker Hub usa: docker/login-action@v1 com: nome de usuário: ${{ secrets.DOCKERHUB_USERNAME }} senha: ${{ secrets.DOCKERHUB_TOKEN }} - nome: Construa e envie o front-end para o Docker Hub usa: docker/build-push-action@v2 com: contexto: front-end arquivo: frontend/Dockerfile empurrar: verdadeiro tags: ${{secrets.DOCKER_FRONTEND_IMAGE }}:mais recentes - nome: SSH no servidor remoto e implantação do frontend usa: appleboy/ssh-action@master com: anfitrião: ${{ secrets.REMOTE_SERVER_HOST }} nome de usuário: ${{ secrets.REMOTE_SERVER_USERNAME }} senha: ${{ secrets.REMOTE_SERVER_SSH_KEY }} porta: ${{ secrets.REMOTE_SERVER_SSH_PORT }} roteiro: | site do CD/ docker rmi -f ${{secrets.DOCKER_FRONTEND_IMAGE }}:mais recentes docker-compose down docker-compose up -d construir e enviar back-end: executado: ubuntu-mais recente if: contém(github.event_name, 'push') && !startsWith(github.event.head_commit.message, 'frontend') passos: - nome: Check-out usa: ações/checkout@v3 - nome: Faça login no Docker Hub usa: docker/login-action@v1 com: nome de usuário: ${{ secrets.DOCKERHUB_USERNAME }} senha: ${{ secrets.DOCKERHUB_TOKEN }} - nome: Construa e envie back-end para Docker Hub usa: docker/build-push-action@v2 com: contexto: back-end arquivo: backend/Dockerfile empurrar: verdadeiro tags: ${{secrets.DOCKER_BACKEND_IMAGE }}:mais recentes - nome: SSH no servidor remoto e implantar back-end usa: appleboy/ssh-action@master com: anfitrião: ${{ secrets.REMOTE_SERVER_HOST }} nome de usuário: ${{ secrets.REMOTE_SERVER_USERNAME }} senha: ${{ secrets.REMOTE_SERVER_SSH_KEY }} porta: ${{ secrets.REMOTE_SERVER_SSH_PORT }} roteiro: | site do CD/ docker rmi -f ${{secrets.DOCKER_BACKEND_IMAGE }}:mais recentes docker-compose down docker-compose up -d=
Repositório: https://github.com/xvandevx/blog-examples/tree/main/nextjs-nestjs-deploy
Este artigo é um guia prático para implantar Next.js e Nest.js juntos em um único servidor, tornando-o uma solução ideal para desenvolvedores que desejam uma configuração simplificada. Combinando os pontos fortes do Next.js para frontend e Nest.js para backend, mostrei como gerenciar com eficiência ambas as partes do seu aplicativo usando Docker e GitHub Actions. Ele simplifica o processo de implantação, permitindo que você se concentre na construção do seu aplicativo, em vez de fazer malabarismos com várias configurações. Perfeito para quem deseja colocar um projeto full-stack em funcionamento rapidamente e com o mínimo de complicações.
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3