Web容器无法从Docker Compose调用后端容器

3

我还在docker世界中探索。我正在尝试将我的小型宠物项目docker化。前端是vue-cli应用程序,与由spring boot创建的包含restful API的后端进行通信。

因此,我的方法是为后端和前端声明两个单独的dockerfile,并通过一个docker compose文件将它们组合起来。因此,文件夹结构如下 -

backend/
       - Dockerfile
frontend/
       - Dockerfile
docker-compose.yml

由于前端需要能够调用后端服务,因此我创建了一个桥接网络,并在它们之间共享了这个网络。以下是我的Docker Compose文件:

version: "2"
services:
  backend:
    build: backend/.
    networks:
      - movie-network
    ports:
      - "8098:8098"
  frontend:
    build: frontend/.
    ports:
      - "8812:8080"
    networks:
      - movie-network

networks:
  movie-network:
    driver: bridge

我在后端有一个名为/api/findAll的端点。如果前端服务通过主机网络调用API,如http://localhost:8098:/api/findAll,我可以在浏览器(http://localhost:8812)中查看它,一切正常。
但是,如果前端使用桥接网络调用相同的API:backend:8098/api/findAll,则我的浏览器会显示错误: error 如果我在前端执行docker exec并ping后端,则ping成功。
那么,为什么我的浏览器会显示错误(http://localhost:8812)?我是否在概念上犯了什么错误?请求建议。
前端Dockerfile:
FROM node:lts-alpine

# install simple http server for serving static content
RUN npm install -g http-server

# make the 'app' folder the current working directory
WORKDIR /app

# copy both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./

# install project dependencies
RUN npm install

# copy project files and folders to the current working directory (i.e. 'app' folder)
COPY . .

# build app for production with minification
RUN npm run build

EXPOSE 8080

后端Dockerfile -

FROM openjdk:11-jre-slim
# Creating app directory
WORKDIR /usr/src/movies
# Copying Jar (didn't use FROM maven to save some time)
COPY target/movies*.jar movies.jar

RUN pwd

RUN ls -la
# Exposing Port
EXPOSE 8098
# Running App
ENTRYPOINT ["java","-jar","/usr/src/movies/movies.jar"]
3个回答

8
这个设置的重要之处在于,你的实际前端代码并非在 Docker 中运行,而是在浏览器中运行。这意味着它对 Docker 网络、容器或其他任何内容都没有了解;你提供的 URL 必须能到达主机上发布的端口。这就是为什么在这里 localhost 可以工作(如果浏览器和容器正在同一台主机上运行),但 backend 不行。
一种典型的方法是设置某种反向代理,既可以托管前端应用程序代码,又可以代理后端应用程序。(例如,设置 Nginx,在它的 /api 路由中使用 proxy_pass http://backend:8098,而在 / 路由中则使用 try_files 预构建的 JavaScript 应用程序或proxy_pass http://frontend:8080) 。
如果您这样做,那么从浏览器的角度来看,例如http://localhost:8900是前端,http://localhost:8900/api是后端。这避免了@coedycode在他们的回答中提到的CORS问题;但这也意味着前端代码可以使用相对URL/api(没有主机名)并避开整个问题。
+-------------+                  | Docker >           /     +----------+
+-------------+                  |                 /------> | frontend |
|             |  localhost:8900  |    +-------+    |        +----------+
|   Browser   | ---------------> | -> | nginx | -> +
|             |                  |    +-------+    | /api   +----------+
|             |                  |                 \------> | backend  |
+-------------+                  |                          +----------+

2
这不是一个Docker配置问题,而是一个CORS(跨源资源共享)问题。当浏览器从http://localhosthttp://backend发出HTTP请求时,这就是一个跨源请求,但后端不允许它。对后端的ping操作有效,因为ping操作不受CORS影响。
在开发环境中,可以配置后端容器中的Web服务器以允许来自本地主机的CORS,在生产环境中,我不确定如何安全地设置以允许CORS,也许可以使用API子域网络别名来为后端设置,并允许来自主域的网络别名的请求?

0

如@coedycode在一个简短但精确的段落中所说,这是后端的问题,您需要指定接受来自特定[网络:端口]的请求。 您可以在控制器类中注释如下以解决问题。

@CrossOrigin(origins = "http://localhost:3000")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接