【问题标题】:How can I serve my GraphQL docker container?如何为我的 GraphQL docker 容器提供服务?
【发布时间】:2020-01-01 14:29:32
【问题描述】:

我想运行两个不同的 docker 容器:

  • ReactJS 前端(使用create-react-app 创建)
  • NodeJS 后端(GraphQL 端点)

第一个很简单。我已经运行npm build 并使用nginx 为应用程序提供服务。这工作正常,我没有任何问题。

第二个是有问题的。我只能通过localhost:3001 而不是my_ip_addr:3001 访问它,即使我在防火墙配置中允许端口3001。这也只工作了一个小时左右 - API 不再可供前端访问,我不知道为什么。

我的服务器文件如下所示:

import express from 'express';
import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';
import bodyParser from 'body-parser';
import * as Schema from './schema';

const cors = require('cors');

const PORT = 3001;
const server = express();

const schemaFunction =
  Schema.schemaFunction ||
  function() {
    return Schema.schema;
  };
let schema;
const rootFunction =
  Schema.rootFunction ||
  function() {
    return schema.rootValue;
  };
const contextFunction =
  Schema.context ||
  function(headers, secrets) {
    return Object.assign(
      {
        headers: headers,
      },
      secrets
    );
  };

server.use(cors());
server.use('/graphql', bodyParser.json({limit: '50mb'}), graphqlExpress(async (request) => {
  if (!schema) {
    schema = schemaFunction(process.env)
  }
  const context = await contextFunction(request.headers, process.env);
  const rootValue = await rootFunction(request.headers, process.env);

  return {
    schema: await schema,
    rootValue,
    context,
    tracing: true,
  };
}));

server.use('/graphiql', graphiqlExpress({
  endpointURL: '/graphql',
  query: `# Run some stuff
`,
}));

server.listen(PORT, () => {
  console.log(`GraphQL Server is now running on http://localhost:${PORT}/graphql`);
  console.log(`View GraphiQL at http://localhost:${PORT}/graphiql`);
});

我怎样才能让它在一个 docker 容器中运行,另一个 docker 容器可以访问它?我不关心它是否可以从我的 Linux 服务器外部访问(事实上,这可能是一个好处),但我确实需要前端容器才能访问 API 端点。

编辑:

Dockerfile(前端)

# build environment
FROM node:9.6.1 as builder
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install --silent
RUN npm install react-scripts@1.1.1 -g --silent
COPY . /usr/src/app
RUN npm run build

# production environment
FROM nginx:1.13.9-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /usr/src/app/client/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Dockerfile(gql 服务器)

FROM node
RUN mkdir /server
WORKDIR /server
COPY package.json /server
RUN npm install
COPY . /server
CMD ["npm", "run", "server"]

最后一条命令运行:nodemon server/src/server.js --exec babel-node -e js

docker 命令为:docker run -dit --restart unless-stopped -p 3001:3001 {image_id}

【问题讨论】:

  • but I do need the front-end container to be able to access the API endpoint.你确定吗?
  • 您可能想在docs.docker.com/network/network-tutorial-standalone 阅读有关 docker 网络的信息。此外,您可能希望提供用于构建和启动容器的 docker 命令/dockerfile。否则很难帮到你。此外,这个问题似乎与 express、graphql 而不是 docker 无关;)。
  • 你能发帖给你Dockerfile吗?
  • @Baboo_ 我已经附上了我的 docker 文件和命令
  • 如果我猜对了,你会希望 nginx 管理客户端并将请求转发到 api。例如http://localhost/ 直接由 nginx 提供服务,而 http://localhost/api/* 将被转发到服务器。对吗?

标签: node.js docker express graphql


【解决方案1】:

使用 docker compose 让它们在同一个网络中运行,docker-compose 将自己创建一个网络,您的服务将在其中运行。 这可能会解决问题


version: "3.3"

services:
  my_back:
    image: redis:alpine
    container_name: redis-db
    ports:
      - 6379:6379

  my_front:
    image: my-image
    container_name: front-end
    environment:
      REDIS_HOSTNAME: "redis-db"

容器名称 = 主机名

【讨论】:

    【解决方案2】:

    我认为您的问题可能在于 docker 网络。您的前端容器可能无法访问您的后端,因为两个容器不在同一个网络中。您可以完美地创建 2 个容器和一个网络来连接它们。

    但是,我建议您查看docker-compose。简而言之,使用 compose 文件,您可以使用卷、网络、连接到主机的端口定义多个服务。您可以在 docker-compose 文件中定义一个网络,并使用服务名称访问网络中的其他容器,您将在前端应用程序中放置一个 ip 或主机名。

    version: '3.2'
    
    services:
      frontend:
        build:
          context: frontend
          dockerfile: Dockerfile
        depends_on:
          - backend
        restart: always
      backend:
        build:
          context: backend
          dockerfile: Dockerfile
        restart: always
    

    【讨论】:

    • env_files: .env 不是必需的,它会造成误解。 .env 文件在设计上是可选的。如果您想拥有一个强制性的环境文件,您应该选择一个不同的名称。例如app.env.
    • docker-compose 将自行创建一个网络,因此无需创建新网络。如果您需要特殊设置,则需要创建一个网络。
    【解决方案3】:

    问题可能出在您的 GraphQL Dockerfile 中。你这里也需要EXPOSE吗,例如:

    EXPOSE 3001
    

    根据documentation

    EXPOSE 指令通知 Docker 容器正在监听 运行时指定的网络端口。

    编辑:抱歉。根据文档,-p 标志会在运行时覆盖这些设置,因此实际上不太可能产生太大影响。

    【讨论】:

      猜你喜欢
      • 2021-01-06
      • 2017-11-23
      • 1970-01-01
      • 2020-09-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-11
      • 2019-05-29
      • 1970-01-01
      相关资源
      最近更新 更多