Docker Swarm:React 前端无法连接到 Kong API 网关
Docker Swarm: React frontend cannot connect to Kong API Gateway
我正在开发一个使用微服务的项目,我正在尝试将 React 中的前端与通过 Kong API 网关提供服务的后端连接起来。问题是每当我向服务器发送请求时,我都会收到错误 net::ERR_NAME_NOT_RESOLVED
。前端服务 运行 与 API 网关服务在同一网络中,但显然 DNS 解析不起作用。
这就是我构建 React 前端的方式 Docker 图片:
FROM node:13.12.0-alpine
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm install --silent
RUN npm install react-scripts@3.4.1 -g --silent
COPY . ./
CMD ["npm", "start"]
这是我从前端发送请求的方式:
handleLogin(event) {
event.preventDefault();
console.log("Log in " + JSON.stringify(this.state.loginForm));
axios.post(`http://${process.env.API_URL}:${process.env.API_PORT}/api/users/login`, this.state.loginForm)
.then((response) => {
const model: LoginModel = response.data;
this.handleLoginResponse(model);
})
.catch((errors) => alert(`Error sending login request to server: ${errors}`));
}
这是我的 stack.yml 配置文件 Docker Swarm 部署:
version: "3.8"
services:
kong:
image: kong:latest
hostname: kong
environment:
KONG_DATABASE: "off"
KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/kong-plugins.yml
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl
deploy:
placement:
constraints: [node.role == manager]
ports:
- 8000:8000
- 8443:8443
- 8001:8001
- 8444:8444
volumes:
- ../../Kong:/usr/local/kong/declarative
networks:
- frontend-network
- internal
- logging
frontend-service:
image: virusx98/frontend
environment:
API_URL: kong
API_PORT: 8000
ports:
- "3001:3000"
networks:
- frontend-network
[...] /* other services */
volumes:
[...] /* volumes for other services */
networks:
frontend-network:
[...] /* other networks */
secrets:
[...] /* secrets for other services */
堆栈在后端完美运行。如果我使用 Postman 发送请求,它们会到达后端服务并返回结果。但是如果我从前端发送请求,就会抛出上述错误,即使这两个服务都放在同一个网络中并且 DNS 解析应该有效。 React 服务正确读取了环境变量,但它表示无法解析主机名 kong
。我在这里错过了什么?
根据评论编辑
您无法到达 API 的原因是节点进程未发送请求。您的浏览器正在发送请求。 API 必须可以从您(和其他所有人)的浏览器访问。在这种情况下,您的 URL 需要在 javascript 中是 localhost:8000
,这样您的浏览器才能访问 kong
容器。
原始答案(仅对环境变量有帮助)
react-scripts 只会从 Node.js 加载几个环境变量。来自他们的文档:
Note: You must create custom environment variables beginning with REACT_APP_. Any other variables except NODE_ENV will be ignored to avoid accidentally exposing a private key on the machine that could have the same name.
这意味着您必须像这样更新 docker-compose.yml
:
environment:
REACT_APP_API_URL: kong
REACT_APP_API_PORT: 8000
这样做,console.log(process.env)
产生:
{
"NODE_ENV": "development",
"PUBLIC_URL": "",
"FAST_REFRESH": true,
"REACT_APP_API_PORT": "8000",
"REACT_APP_API_URL": "kong"
}
话虽如此,您不应该将 react-scripts start 用于生产目的。始终进行生产构建。您应该改为将 .env
文件添加到您的项目中,以便将这些变量注入到构建中。您将无法通过 docker-compose.
注入它们
参考:
我正在开发一个使用微服务的项目,我正在尝试将 React 中的前端与通过 Kong API 网关提供服务的后端连接起来。问题是每当我向服务器发送请求时,我都会收到错误 net::ERR_NAME_NOT_RESOLVED
。前端服务 运行 与 API 网关服务在同一网络中,但显然 DNS 解析不起作用。
这就是我构建 React 前端的方式 Docker 图片:
FROM node:13.12.0-alpine
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm install --silent
RUN npm install react-scripts@3.4.1 -g --silent
COPY . ./
CMD ["npm", "start"]
这是我从前端发送请求的方式:
handleLogin(event) {
event.preventDefault();
console.log("Log in " + JSON.stringify(this.state.loginForm));
axios.post(`http://${process.env.API_URL}:${process.env.API_PORT}/api/users/login`, this.state.loginForm)
.then((response) => {
const model: LoginModel = response.data;
this.handleLoginResponse(model);
})
.catch((errors) => alert(`Error sending login request to server: ${errors}`));
}
这是我的 stack.yml 配置文件 Docker Swarm 部署:
version: "3.8"
services:
kong:
image: kong:latest
hostname: kong
environment:
KONG_DATABASE: "off"
KONG_DECLARATIVE_CONFIG: /usr/local/kong/declarative/kong-plugins.yml
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: 0.0.0.0:8001, 0.0.0.0:8444 ssl
deploy:
placement:
constraints: [node.role == manager]
ports:
- 8000:8000
- 8443:8443
- 8001:8001
- 8444:8444
volumes:
- ../../Kong:/usr/local/kong/declarative
networks:
- frontend-network
- internal
- logging
frontend-service:
image: virusx98/frontend
environment:
API_URL: kong
API_PORT: 8000
ports:
- "3001:3000"
networks:
- frontend-network
[...] /* other services */
volumes:
[...] /* volumes for other services */
networks:
frontend-network:
[...] /* other networks */
secrets:
[...] /* secrets for other services */
堆栈在后端完美运行。如果我使用 Postman 发送请求,它们会到达后端服务并返回结果。但是如果我从前端发送请求,就会抛出上述错误,即使这两个服务都放在同一个网络中并且 DNS 解析应该有效。 React 服务正确读取了环境变量,但它表示无法解析主机名 kong
。我在这里错过了什么?
根据评论编辑
您无法到达 API 的原因是节点进程未发送请求。您的浏览器正在发送请求。 API 必须可以从您(和其他所有人)的浏览器访问。在这种情况下,您的 URL 需要在 javascript 中是 localhost:8000
,这样您的浏览器才能访问 kong
容器。
原始答案(仅对环境变量有帮助)
react-scripts 只会从 Node.js 加载几个环境变量。来自他们的文档:
Note: You must create custom environment variables beginning with REACT_APP_. Any other variables except NODE_ENV will be ignored to avoid accidentally exposing a private key on the machine that could have the same name.
这意味着您必须像这样更新 docker-compose.yml
:
environment:
REACT_APP_API_URL: kong
REACT_APP_API_PORT: 8000
这样做,console.log(process.env)
产生:
{
"NODE_ENV": "development",
"PUBLIC_URL": "",
"FAST_REFRESH": true,
"REACT_APP_API_PORT": "8000",
"REACT_APP_API_URL": "kong"
}
话虽如此,您不应该将 react-scripts start 用于生产目的。始终进行生产构建。您应该改为将 .env
文件添加到您的项目中,以便将这些变量注入到构建中。您将无法通过 docker-compose.