使用asyncData

时间:2019-03-10 16:48:19

标签: docker nuxt.js traefik strapi

我对docker的安装有些复杂。一切都按预期工作,除了我有这个奇怪的问题。 访问 index 页面或 / pages / _id 页面我没有错误。但是,当我尝试打开 / other-page 时,它崩溃了。所有人都使用相同的API网址。

打开 / other-page 时在控制台中发现错误:

获取http://api:1337/games网:: ERR_NAME_NOT_RESOLVED

不确定该怎么做,有什么建议吗?

nuxt.config.js

  axios: {
    baseURL: 'http://api:1337'
  },

docker-compose.yml

version: '3'

services:
  api:
    build: .
    image: strapi/strapi
    environment:
      - APP_NAME=strapi-app
      - DATABASE_CLIENT=mongo
      - DATABASE_HOST=db
      - DATABASE_PORT=27017
      - DATABASE_NAME=strapi
      - DATABASE_USERNAME=
      - DATABASE_PASSWORD=
      - DATABASE_SSL=false
      - DATABASE_AUTHENTICATION_DATABASE=strapi
      - HOST=api
      - NODE_ENV=production
    ports:
      - 1337:1337
    volumes:
      - ./strapi-app:/usr/src/api/strapi-app
      #- /usr/src/api/strapi-app/node_modules
    depends_on:
      - db
    restart: always
    links:
      - db

  nuxt:
    # build: ./app/
    image: "registry.gitlab.com/username/package:latest"
    container_name: nuxt
    restart: always
    ports:
      - "3000:3000"
    links:
      - api:api
    command:
      "npm run start"


  nginx:
    image: nginx:1.14.2
    expose:
      - 80
    container_name: nginx
    restart: always
    ports:
      - "80:80"
    volumes:
      - ./nginx:/etc/nginx/conf.d
    depends_on:
      - nuxt
    links:
      - nuxt

index.vue

...
  async asyncData({ store, $axios }) {
    const games = await $axios.$get('/games')
    store.commit('games/emptyList')
    games.forEach(game => {
      store.commit('games/add', {
        id: game.id || game._id,
        ...game
      })
    })
    return { games }
  },
...

page.vue

...
  async asyncData({ store, $axios }) {
    const games = await $axios.$get('/games')
    store.commit('games/emptyList')
    games.forEach(game => {
      store.commit('games/add', {
        id: game.id || game._id,
        ...game
      })
    })
    return { games }
  },
...

Nginx conf

upstream webserver {
  ip_hash;
  server nuxt:3000;
}

server {
  listen 80;
  access_log off;
  connection_pool_size 512k;
  large_client_header_buffers 4 512k;

  location / {
    proxy_pass http://webserver;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    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;
    proxy_max_temp_file_size 0;
  }

更新:

尝试了Thomasleveil的建议。现在,我收到以下错误:

nuxt | [2:09:35 PM]错误:连接ECONNREFUSED 127.0.0.1:80

因此,现在看来/ api已转发到127.0.0.1:80。不确定为什么^^

nuxt.config.js

  axios: {
    baseURL: '/api'
  },
  server: {
    proxyTable: {
      '/api': {
         target: 'http://localhost:1337',
         changeOrigin: true,
         pathRewrite: {
           "^/api": ""
         }
      }
    }
  }

docker-compose.yml

version: '3'

services:
  reverse-proxy:
    image: traefik # The official Traefik docker image
    command: --api --docker # Enables the web UI and tells Traefik to listen to docker
    ports:
      - "80:80"     # The HTTP port
      - "8080:8080" # The Web UI (enabled by --api)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock # listen to the Docker events
    networks:
      - mynet

  api:
    build: .
    image: strapi/strapi
    container_name: api
    environment:
      - APP_NAME=strapi-app
      - DATABASE_CLIENT=mongo
      - DATABASE_HOST=db
      - DATABASE_PORT=27017
      - DATABASE_NAME=strapi
      - DATABASE_USERNAME=
      - DATABASE_PASSWORD=
      - DATABASE_SSL=false
      - DATABASE_AUTHENTICATION_DATABASE=strapi
      - HOST=api
      - NODE_ENV=development
    ports:
      - 1337:1337
    volumes:
      - ./strapi-app:/usr/src/api/strapi-app
      #- /usr/src/api/strapi-app/node_modules
    depends_on:
      - db
    restart: always
    networks:
      - mynet
    labels:
      - "traefik.backend=api"
      - "traefik.docker.network=mynet"
      - "traefik.frontend.rule=Host:example.com;PathPrefixStrip:/api"
      - "traefik.port=1337"

  db:
    image: mongo
    environment:
      - MONGO_INITDB_DATABASE=strapi
    ports:
      - 27017:27017
    volumes:
      - ./db:/data/db
    restart: always
    networks:
      - mynet

  nuxt:
    # build: ./app/
    image: "registry.gitlab.com/username/package:latest"
    container_name: nuxt
    restart: always
    ports:
      - "3000:3000"
    command:
      "npm run start"
    networks:
      - mynet
    labels:
      - "traefik.backend=nuxt"
      - "traefik.frontend.rule=Host:example.com;PathPrefixStrip:/"
      - "traefik.docker.network=web"
      - "traefik.port=3000"

networks:
  mynet:
    external: true

1 个答案:

答案 0 :(得分:2)

  

访问索引页面或/ pages / _id页面我没有错误。但是,当我尝试打开/ other-page时,它崩溃了。

重新制定:

  • 我在/有一个主页,其中显示了一些指向/pages/_id(其中_id是有效的游戏ID)上的页面的链接
  • 当我打开//pages/_id时,内容显示出来
  • 但是,如果我从页面/中定位到/pages/xxx(其中xxx是有效ID)的链接,则出现错误
  • 此外,如果刷新页面,我会看到内容而不是错误
  • 这些页面的
  • 内容来自api服务器。页面应该通过调用api服务器来获取内容,然后使用响应呈现页面内容。

这是怎么回事?

AsyncData

asyncData在nuxt.js中的工作方式如下:

在首页加载

  1. 用户在浏览器中输入网址http://yourserver/pages/123
  2. nuxt Web服务器处理请求,解析路由并为该页面安装vue组件
  3. 从nuxt.js服务器端调用vue组件的asyncData方法
  4. nuxt.js服务器(不是用户浏览器)然后通过对http://api:1337/games/123进行不同的调用来获取内容,接收响应并呈现内容。

当用户单击另一个页面的链接时

现在发生了一些变化。

  1. 用户仍位于页面http://api:1337/games/123上,该页面具有指向列出所有游戏(http://yourserver/)的主页的链接,然后单击它。
  2. 浏览器不会加载任何新页面。而是,用户浏览器对http://api:1337/games进行了ajax调用,以尝试获取新内容。由于名称解析错误而失败

为什么?

此功能是nuxt.js带来的功能,可以加快页面内容的加载时间。来自documentation的重要信息是:

  每次加载页面组件之前,都会调用

asyncData。导航到其他路由时,它将一次(在对Nuxt应用程序的第一个请求时)称为服务器端,而在客户端则称为

  • server-side表示从nuxt服务器到api服务器的调用
  • client-side表示从用户浏览器到api服务器的调用

现在有趣的部分:

  • nuxt服务器在第一个容器中运行
  • api服务器正在第二个容器中运行,并且正在侦听端口1337
  • 从nuxt容器中,用于调用api服务器的URL为http://api:1337/,并且工作正常
  • 在用户浏览器中,调用http://api:1337失败(net::ERR_NAME_NOT_RESOLVED),因为用户计算机不知道如何将域名api转换为IP地址。即使可以,该IP地址也将无法访问。

该怎么办?

  • 您需要设置一个反向代理,以将用户浏览器发出的以http://yourserver/api/开头的URL转发到端口api上的1337容器。
  • 您需要配置nuxt.js,以使client-side(通过用户浏览器)到api的链接使用网址http://yourserver/api而不是http://api:1337/
  • 您需要配置nuxt.js,以便它继续为http://api:1337进行的调用server-side

为从nuxt(server-side)进行的呼叫添加反向代理

由于您使用的是nuxt.js Axios module来调用api容器,因此您已经到达了一半。

Axios模块具有一个proxy选项,可以在nuxtjs.config.js中将其设置为true

下面是使用Traefik为您的项目设置反向代理的示例,但是文档说明该代理与baseURL选项的使用不兼容。必须使用prefix选项。

您的nuxt.config.js应该看起来像这样:

  axios: {
    prefix: '/api',
    proxy: true
  }, 
  proxy: {
    '/api/': {
      target: 'http://localhost:1337',
      pathRewrite: {
        '^/api/': ''
      }
    }
  },

这在您的开发计算机上工作正常,如果trapi正在运行并且在http://localhost:1337处响应。但这在容器中不起作用,因为我们需要将http://localhost:1337替换为http://api:1337。 为此,我们可以引入一个环境变量(STRAPI_URL):

  axios: {
    prefix: '/api',
    proxy: true
  }, 
  proxy: {
    '/api/': {
      target: process.env.STRAPI_URL || 'http://localhost:1337',
      pathRewrite: {
        '^/api/': ''
      }
    }
  },

我们稍后将在docker-compose.yml文件中设置STRAPI_URL

为从用户浏览器(client-side)发出的呼叫添加反向代理

由于在使用docker时我放弃了使用nginx实现反向代理,因此以下是Traefik的示例:

docker-compose.yml:

version: '3'

services:
  reverseproxy:  # see https://docs.traefik.io/#the-traefik-quickstart-using-docker
    image: traefik
    command: --docker
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  api:
    image: strapi/strapi
    environment:
      - ...
    expose:
      - 1337
    labels:
      traefik.frontend.rule: PathPrefixStrip:/api
      traefik.port: 1337

  nuxt:
    image: ...
    expose:
      - 3000
    command:
      "npm run start"
    labels:
      traefik.frontend.rule: PathPrefixStrip:/
      traefik.port: 3000

现在,用户浏览器向http://yourserver发出的所有HTTP请求将由Traefik反向代理处理。

Traefik将通过查看traefik.nuxt容器上以api开头的标签来配置转发规则。

发生了什么变化?

您现在有2个反向代理:

  • 一个用于server-side请求(nuxt.js Proxy module
  • 一个用于client-side请求(Traefik)

还没有完成

我们现在需要指示 nuxt.js代理模块,它必须将请求转发到http://api:1337/。为此,我们将使用STRAPI_URL环境变量。

我们需要指示 nuxt Axios模块,用户浏览器必须调用http://yourserver/api上的api。这是通过API_URL_BROWSER环境变量完成的。


在一起

nuxt.config.js

  axios: {
    prefix: '/api',
    proxy: true
  }, 
  proxy: {
    '/api/': {
      target: process.env.STRAPI_URL || 'http://localhost:1337',
      pathRewrite: {
        '^/api/': ''
      }
    }
  },

docker-compose.yml

version: '3'

services:
  reverseproxy:  # see https://docs.traefik.io/#the-traefik-quickstart-using-docker
    image: traefik
    command: --docker
    ports:
      - "80:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  api:
    image: strapi/strapi
    environment:
      - ...
    expose:
      - 1337
    labels:
      traefik.frontend.rule: PathPrefixStrip:/api
      traefik.port: 1337

  nuxt:
    image: ...
    expose:
      - 3000
    command:
      "npm run start"
    environment:
      NUXT_HOST: 0.0.0.0
      STRAPI_URL: http://api:1337/
      API_URL_BROWSER: /api
    labels:
      traefik.frontend.rule: PathPrefixStrip:/
      traefik.port: 3000