GET http://api:1337/games net::ERR_NAME_NOT_RESOLVED for nuxt.js pages using asyncData
GET http://api:1337/games net::ERR_NAME_NOT_RESOLVED for nuxt.js pages using asyncData
我对 docker 进行了一些复杂的设置。一切都按预期工作,除了我有这个奇怪的问题。
访问 index 页面或 /pages/_id 页面我没有错误。但是当我尝试打开 /other-page 时它崩溃了。所有人都在使用相同的 API url.
打开 /other-page 时在控制台中发现错误:
获取http://api:1337/gamesnet::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 配置文件
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
Visiting index page or /pages/_id pages I have no errors. But when I try to open /other-page it crashes.
重新制定:
- 我在
/
有一个主页,在 /pages/_id
显示了一些 link 的目标页面(其中 _id
是一个有效的游戏 ID)
- 当我打开
/
或/pages/_id
时,内容显示
- 但是如果我从
/
页点击 link 目标 /pages/xxx
(其中 xxx
是一个有效的 ID),我得到一个错误
- 此外,如果我刷新页面,我会看到内容而不是错误
- 这些页面的内容来自 api 服务器。页面应该通过调用 api 服务器来获取内容,然后使用响应呈现页面内容。
这里发生了什么?
异步数据
asyncData 在 nuxt.js 中的工作方式如下:
第一页加载时
- 用户在其浏览器中输入 url
http://yourserver/pages/123
- nuxt 网络服务器处理请求,解析路由并为该页面安装 vue 组件
- 从nuxt.js服务器端调用vue组件的
asyncData
方法
- nuxt.js 服务器(不是用户浏览器)然后通过对
http://api:1337/games/123
进行不同的调用来获取内容,接收响应并呈现内容。
当用户点击另一个页面的link时
现在有些不同。
- 用户仍在页面
http://api:1337/games/123
上,该页面有一个 link 到列出所有游戏 (http://yourserver/
) 的主页并单击它。
- 浏览器未加载任何新页面。相反,用户浏览器对
http://api:1337/games
进行 ajax 调用以尝试获取新内容。并因名称解析错误而失败
为什么?
这是 nuxt.js 为您提供的一项功能,可加快页面内容加载时间。来自 documentation 的重要信息是:
asyncData
is called every time before loading the page component. It will be called server-side once (on the first request to the Nuxt app) and client-side when navigating to further routes.
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 地址也无法访问。
可以做什么?
- 您需要设置一个反向代理,将用户浏览器发出的请求转发到 url,从
http://yourserver/api/
开始到 api
端口上的容器 1337
.
- 并且您需要配置 nuxt.js 以便 link 到 api 使
client-side
(从用户浏览器)使用 url 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, but the documentation state that the proxy is incompatible with the usage of the baseURL option. The prefix 选项为您的项目设置反向代理的示例,必须改用。
您的 nuxt.config.js 应该如下所示:
axios: {
prefix: '/api',
proxy: true
},
proxy: {
'/api/': {
target: 'http://localhost:1337',
pathRewrite: {
'^/api/': ''
}
}
},
如果 strapi 是 运行 并且在 http://localhost:1337
处响应,这在您的开发计算机上运行良好。但这在容器中不起作用,因为我们需要用 http://api:1337
替换 http://localhost: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:1.7
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 将通过查看 nuxt
和 api
容器上以 traefik.
开头的标签来配置转发规则。
有什么变化?
您现在有 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:1.7
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
我对 docker 进行了一些复杂的设置。一切都按预期工作,除了我有这个奇怪的问题。 访问 index 页面或 /pages/_id 页面我没有错误。但是当我尝试打开 /other-page 时它崩溃了。所有人都在使用相同的 API url.
打开 /other-page 时在控制台中发现错误:
获取http://api:1337/gamesnet::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 配置文件
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
Visiting index page or /pages/_id pages I have no errors. But when I try to open /other-page it crashes.
重新制定:
- 我在
/
有一个主页,在/pages/_id
显示了一些 link 的目标页面(其中_id
是一个有效的游戏 ID) - 当我打开
/
或/pages/_id
时,内容显示 - 但是如果我从
/
页点击 link 目标/pages/xxx
(其中xxx
是一个有效的 ID),我得到一个错误 - 此外,如果我刷新页面,我会看到内容而不是错误
- 这些页面的内容来自 api 服务器。页面应该通过调用 api 服务器来获取内容,然后使用响应呈现页面内容。
这里发生了什么?
异步数据
asyncData 在 nuxt.js 中的工作方式如下:
第一页加载时
- 用户在其浏览器中输入 url
http://yourserver/pages/123
- nuxt 网络服务器处理请求,解析路由并为该页面安装 vue 组件
- 从nuxt.js服务器端调用vue组件的
asyncData
方法 - nuxt.js 服务器(不是用户浏览器)然后通过对
http://api:1337/games/123
进行不同的调用来获取内容,接收响应并呈现内容。
当用户点击另一个页面的link时
现在有些不同。
- 用户仍在页面
http://api:1337/games/123
上,该页面有一个 link 到列出所有游戏 (http://yourserver/
) 的主页并单击它。 - 浏览器未加载任何新页面。相反,用户浏览器对
http://api:1337/games
进行 ajax 调用以尝试获取新内容。并因名称解析错误而失败
为什么?
这是 nuxt.js 为您提供的一项功能,可加快页面内容加载时间。来自 documentation 的重要信息是:
asyncData
is called every time before loading the page component. It will be called server-side once (on the first request to the Nuxt app) and client-side when navigating to further routes.
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 地址也无法访问。
可以做什么?
- 您需要设置一个反向代理,将用户浏览器发出的请求转发到 url,从
http://yourserver/api/
开始到api
端口上的容器1337
. - 并且您需要配置 nuxt.js 以便 link 到 api 使
client-side
(从用户浏览器)使用 urlhttp://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, but the documentation state that the proxy is incompatible with the usage of the baseURL option. The prefix 选项为您的项目设置反向代理的示例,必须改用。
您的 nuxt.config.js 应该如下所示:
axios: {
prefix: '/api',
proxy: true
},
proxy: {
'/api/': {
target: 'http://localhost:1337',
pathRewrite: {
'^/api/': ''
}
}
},
如果 strapi 是 运行 并且在 http://localhost:1337
处响应,这在您的开发计算机上运行良好。但这在容器中不起作用,因为我们需要用 http://api:1337
替换 http://localhost: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:1.7
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 将通过查看 nuxt
和 api
容器上以 traefik.
开头的标签来配置转发规则。
有什么变化?
您现在有 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:1.7
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