带有Nest API的Nuxt.js SSR(已在Docker容器中部署到AWS)

时间:2020-02-03 21:13:50

标签: docker axios nuxt.js nestjs

我已经在此主题上尝试了大约500万个变体,并且花了大量时间浏览Nuxt文档,当将Nest后端部署到AWS的Docker容器中时,我无法获得带有Nest后端的Nuxt SSR。以下是我当前的设置。请让我知道是否遗漏了任何东西。

这是我遇到的错误:

https://www.noticeeverythingcreative.com/contact 此路由在组件的POST方法中向https://www.noticeeverythingcreative.com/api/contact/meta发送页面元的asyncData请求。这会产生来自Axios的大错误。以下是我认为相关的部分,但是如果您需要更多,请告诉我。

{
  errno: 'ECONNREFUSED',
  code: 'ECONNREFUSED',
  syscall: 'connect',
  address: 'xxx.xx.x.x', // IP Address of the docker container
  port: 443,
  config: {
    url: 'https://www.noticeeverythingcreative.com/api/contact/meta',
    method: 'post',
    headers: {
      Accept: 'application/json, text/plain, */*',
      connection: 'close',
      'x-real-ip': 'xx.xxx.xxx.xxx', // My IP
      'x-forwarded-for': 'xx.xxx.xxx.xxx', // My IP
      'x-forwarded-proto': 'https',
      'x-forwarded-ssl': 'on',
      'x-forwarded-port': '443',
      pragma: 'no-cache',
      'cache-control': 'no-cache',
      'upgrade-insecure-requests': '1',
      'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36',
      'sec-fetch-user': '?1',
      'sec-fetch-site': 'same-origin',
      'sec-fetch-mode': 'navigate',
      'accept-encoding': 'gzip, deflate',
      'accept-language': 'en-US,en;q=0.9',
      'Content-Type': 'application/json'
    },
    baseURL: 'https://www.noticeeverythingcreative.com'
  }

这是我的nuxt.config.js的相关部分:

mode: 'universal',
srcDir: './src',
rootDir: './',
modules: ['@nuxtjs/axios'],
// NOTE: I get the same errors if I leave this block out
server: {
    host: '0.0.0.0',
    port: 3002
},

部署时,我使用Dockerfile将项目目录中所有需要的文件复制到容器中,运行yarn install,暴露端口3002,运行yarn build.prod,最后以{ {1}}(有关相关的CMD ["yarn", "start"]脚本,请参见下文)。

package.json

泊坞窗映像在本地构建,并推送到ECR存储库。然后,我通过SSH进入服务器,并使用以下撰写文件运行"scripts": { "clean.nuxt": "rimraf .nuxt", "build.client": "nuxt build", "build.server": "tsc -p tsconfig.server.json", // Transpile TypeScript from `src/server` into `.nuxt/api` "build.prod": "run-s clean.nuxt build.client build.server", "start": "cross-env NODE_ENV=production node .nuxt/api/index.js", }

docker-compose up -d

这是我的服务器端控制器,用于处理Nuxt渲染:

src / server / app / nuxt.controller.ts

version: '3.2'

services:
  my_service:
  image: link/to/my/image:${TAG:-prod}
  container_name: my_container
  hostname: www.noticeeverythingcreative.com
  restart: unless-stopped

ports:
  # Http Port
  - 3002:3002

networks:
  - web-network # External (the actual compose file also has the corresponding networks block at the bottom)

environment:
  - NODE_ENV=production
  - API_URL=https://www.noticeeverythingcreative.com
  - HOST=www.noticeeverythingcreative.com
  - PORT=3002
  - VIRTUAL_PORT=3002 

这是客户端联系人组件的import { Controller, Get, Request, Response } from '@nestjs/common'; import { join, resolve } from 'path'; import * as config from 'config'; const { Builder, Nuxt } = require('nuxt'); const nuxtConfig = require(join(resolve(), 'nuxt.config.js')); @Controller() export class NuxtController { nuxt:any; constructor() { this.nuxt = new Nuxt(nuxtConfig); const Env = config as any; // Build only in dev mode if (Env.name === 'development') { const builder = new Builder(this.nuxt); builder.build(); } else { this.nuxt.ready(); } } @Get('*') async root(@Request() req:any, @Response() res:any) { if (this.nuxt) { return await this.nuxt.render(req, res); } else { res.send('Nuxt is disabled.'); } } } asyncData实现:

head

我遇到的问题仅出现在生产主机上的生产环境中。我可以在本地运行async asyncData(ctx:any) { // fetch page meta from API try { const meta = await ctx.$axios(<any>{ method: 'post', url: `${ ctx.env.apiHost }/contact/meta`, headers: { 'Content-Type': 'application/json' } }); return { meta: meta.data }; } catch (error) { // Redirect to error page or 404 depending on server response console.log('ERR: ', error); } } head() { return this.$data.meta; } ,该应用程序可以正常运行和呈现。

更新

如果我允许Nuxt应用程序实际在docker容器内的localhost上运行,则会遇到相反的问题。例如,如果我将nuxt.config.js服务器和axios块更改为

yarn build.prod && cross-env NODE_ENV=development node .nuxt/api/index.js

并将请求更改为:

server: {
    port: 3002, // default: 3000,
},
axios: {
    baseURL: 'http://localhost:3002'
}

重新加载https://www.noticeeverythingcreative.com/contact会很好。可以通过查看页面源代码并查看标题已更新并且没有控制台错误来确认。但是,如果您加载首页(https://www.noticeeverythingcreative.com)并单击导航栏中的联系人链接,则会看到const meta = await ctx.$axios(<any>{ method: 'post', // NOTE: relative path here instead of the absolute path above url: `/api/contact/meta`, headers: { 'Content-Type': 'application/json' } }); return { meta: meta.data };

注意:这是该问题的上一次编辑以来所部署的版本。

1 个答案:

答案 0 :(得分:0)

我想出了一个解决方案,但我不喜欢它,因此,如果有人有更好的建议,请发表。

我通过允许Nuxt应用程序在docker容器内的localhost上运行,但向实际主机发出http请求(例如https://www.noticeeverythingcreative.com/whatever)来使其工作。

因此,在nuxt.config.js中:

// The server and axios blocks simply serve to set the port as something other than the default 3000
server: {
    port: 3002, // default: 3000,
},
axios: {
    baseURL: 'http://localhost:3002'
},
env: {
    apiHost: process.env.NODE_ENV === 'production' ?
        'https://www.noticeeverythingcreative.com/api' :
        'http://localhost:3002/api'
} 

docker-compose.yml中,我删除了任何可以使主机变为localhost以外的东西,以及nuxt依赖的env变量(主要是因为我不太清楚它们在Nuxt中如何工作,除了这不是我期望的方式):

version: '3.2'

services:
  my_service:
  image: link/to/my/image:${TAG:-prod}
  container_name: my_container
  # REMOVED
  # hostname: www.noticeeverythingcreative.com
  restart: unless-stopped

ports:
  # Http Port
  - 3002:3002

networks:
  - web-network # External (the actual compose file also has the corresponding networks block at the bottom)

environment:
  # REMOVED
  # - API_URL=https://www.noticeeverythingcreative.com
  # - HOST=www.noticeeverythingcreative.com
  - NODE_ENV=production
  - PORT=3002
  - VIRTUAL_PORT=3002

在发出api请求时:

// NOTE: ctx.env.apiHost is https://www.noticeeverythingcreative.com/api
const meta = await ctx.$axios(<any>{
    method: 'post',
    url: `${ ctx.env.apiHost }/contact/meta`,
    headers: { 'Content-Type': 'application/json' }
});

return { meta: meta.data };