【问题标题】:nginx-proxy for more than one node app dockernginx-proxy 用于多个节点应用 docker
【发布时间】:2018-01-24 12:29:04
【问题描述】:

我正在尝试使用 nginx 反向代理多个容器。

我有 2 个容器,其中节点在 8085 上添加一个监听,在 8086 上添加另一个监听 我希望他们通过

访问

node.app1.com

node.app2.com

所以我使用了 jwilder/nginx-proxy:latest,它将位于这两个容器的源代码中,并将充当反向代理。所以这是我的 compose.yml 文件。


docker-compose.yml

version: "3"
services:
  node-proxy:
    build:  ./node-proxy
    container_name : node-proxy
    restart : always
    volumes:  
        -  /var/run/docker.sock:/tmp/docker.sock:ro
    ports:
      - 80:80
      - 443:443
  node-app1:
    build:  ./app1
    container_name : node-app1
    restart: always
    environment:
      VIRTUAL_HOST: node.app1.com
    depends_on:
      - node-proxy
  node-app2:
    build:  ./app2
    container_name : node-app2
    restart: always
    environment:
      VIRTUAL_HOST: node.app2.com
    depends_on:
      - node-proxy

./node-proxy/Dockerfile

FROM jwilder/nginx-proxy:latest

./app1/app1.js

var http = require("http");

http.createServer(function (request, response) {

   response.writeHead(200, {'Content-Type': 'text/plain'});
   response.end('Hello World 1\n');
}).listen(8085);

./app1/Dockerfile

FROM node:6.11
WORKDIR /app2
COPY app1.js .
CMD node app1.js
Expose 8085

./app2/app2.js

var http = require("http");

http.createServer(function (request, response) {

   response.writeHead(200, {'Content-Type': 'text/plain'});
   response.end('Hello World 2\n');
}).listen(8086);

./app2/Dockerfile

FROM node:6.11
WORKDIR /app2
COPY app2.js .
CMD node app2.js
Expose 8086

所以当我这样做时

docker-compose up 

我所有的容器都已启动并正在运行

但是 node.app1.com 什么时候做 --> 它说是未知主机。

所以为了检查请求是否到达代理,我尝试从浏览器调用 http://localhost,它显示 503

我还检查了侧容器中的 nginx.config

docker exec -it node-proxy_id bash

cat /etc/nginx/conf.d/

它就在那里,但我想当我做 node.app1.com 请求时不会来代理。 我没有得到我错过的地方,有人可以帮我解决这个问题。

感谢您的宝贵时间

【问题讨论】:

  • 那么您的节点应用程序是否分别在 172.18.0.4:8086 和 172.18.0.3:8085 上运行?我可以看到你用来制作它们的配置文件吗?
  • 是的,我的两个 hello word 节点应用程序都运行良好,在上面共享的 Dockerfile 中指定了暴露端口。
  • 是的,我确实知道端口 8086 和 8085 来自哪里,但是 172.18.0.4 和 172.18.0.3 的 IP 地址来自哪里?
  • 这是一个容器IP,在我们组合时自动生成。

标签: node.js docker proxy docker-compose


【解决方案1】:

查看您的应用程序/Dockerfile 的端口:

./app1/app1.js

}).listen(8085);

./app1/Dockerfile

暴露 8086

它们不匹配。


我缺少的部分是 jwilder/nginx-proxy 反映 docker 以查找需要代理的容器。

原帖:

我猜你的问题是反向代理容器无法到达每个应用程序。因此从 node-app1 和 node-app2 中删除 depends_on 并添加到 node-proxy 中:

links:
 - node-app1
 - node-app2 

反向代理需要启动两个应用程序,而不是相反。也使用links 而不是depends_on

来自docs

取决于

表达服务之间的依赖关系,有两个作用:

  • docker-compose up 将按依赖顺序启动服务。在下面的例子中,db和redis将在web之前启动。

  • docker-compose up SERVICE 将自动包含 SERVICE 的依赖项。在以下示例中, docker-compose up web 将 同时创建并启动 db 和 redis。

链接

链接服务的容器可以通过与别名相同的主机名访问,或者如果没有指定别名,则使用服务名。

链接也和depends_on一样表达服务之间的依赖关系,因此它们决定了服务启动的顺序。


我也不确定您如何在代理配置中获取此容器的 IP 地址。您可以使用(如文档中所述)别名或服务名称。 (在你的情况下 node-app1 和 node-app2)

【讨论】:

  • 查看 nginx.config 中的最后一张图片,其中配置是根据 compose..yml 文件的配置生成的。我已经手动进入代理容器并使用域提供 ping,它工作正常(因此反向代理容器能够同时访问 app1 和 app2 容器)这里的问题是我的主机文件剂量注意解析 VIRTUAL_HOST 中提供的域名 [如问题的第一张图片所示,当我尝试从浏览器调用 localhost 并显示 503 时,请求即将发送到代理服务器]
  • 如果我像这样手动编辑系统的主机文件 > 那么它工作正常 >>>>>> 127.0.0.1 localhost 127.0.0.1 node.app1.com 127.0.0.1 node.app2。 com >>>> 但每次更改 VIRTUAL_HOST 的值时编辑 DNS(主机文件)是不切实际的。
  • 我猜你以错误的方式定义了依赖关系,它可能在一些奇怪的情况下工作。您是否尝试过在代理服务中使用链接?
  • 是的,我已经尝试使用链接,但仍然无法正常工作! :(
  • 您的应用程序和 docker 文件中存在端口不匹配。更新了答案。
【解决方案2】:

当您将linksdepends_on 设置为其他服务时,docker-compose 会默认将其他服务的主机名设置为其container_name 在同一个docker 网络中。

在你的情况下,我建议添加links 作为@Mathias 回复。

version: "3"
services:
  node-app1:
    build:  ./app1
    container_name : node-app1
    restart: always
    expose:
      - "8085"
    environment:
      VIRTUAL_HOST: node.app1.com
  node-app2:
    build:  ./app2
    container_name : node-app2
    restart: always
    expose:
      - "8086"
    environment:
      VIRTUAL_HOST: node.app2.com
  node-proxy:
    build:  ./node-proxy
    container_name : node-proxy
    restart : always
    links:
        - node-app1
        - node-app2
    volumes:
        -  /var/run/docker.sock:/tmp/docker.sock:ro
    ports:
        - 80:80
        - 443:443

更新:

我注意到 Nginx 配置有 upstream 指令来保存多个主机名。您应该能够将node-app1 卷曲为:

$ curl -H 'Host: node.app1.com' localhost
Hello World 1

您还可以将node-proxy 容器中etc/hosts 文件中的最后一行修改为:

172.20.0.4 [docker-network-alias] node.app1.com node.app2.com

那么您应该可以直接在您的node-proxy 容器中访问http://node.app1.com

这是set up nginx virtual hosts on ubuntu 16 04的教程

评论一:

据我了解,nginx-proxy 倾向于将请求代理到后端服务,而不必在/etc/hosts 文件中注册主机名。因此,我们使用 Host 标头触发请求,该标头是 Nginx upstream 块中的虚拟主机名。

当您在每个应用容器设置中创建环境变量VIRTUAL_HOST 时,nginx-proxy 已经为您完成了这部分工作。但这并不意味着我们可以在浏览器中直接访问node.app1.com,并期望请求将被node-app1容器代理并响应。

回到请求转发部分,请求到达localhost的80/443端口,被Nginx监听。 Nginx 然后检查Host 标头以进入特定的位置块。这就是为什么您不能在浏览器中直接访问http://node.app1.com,因为该主机名永远不会真正在etc/hosts 中注册,因此任何服务器、应用程序或我们的nginx-proxy 都不会处理它。

如果我们想通过浏览器访问主机名,需要额外设置etc/hosts

nginx-proxy 项目提供了一些模板设置,因此您可以获取应用容器的 IP 及其VIRTUAL_HOST 环境,然后将其附加到/etc/hosts 文件中。但是这样会直接访问节点应用服务器而不是来自nginx-proxy的代理。

如果不考虑生产级别,我建议在etc/hosts 文件的最后一行附加应用程序域,该文件由nginx-proxy 设置,然后它应该可以按预期工作。否则需要从nginx-proxy 模板进行主机名动态绑定的工作。

【讨论】:

  • 查看反向代理的图像。 github.com/jwilder/nginx-proxy 此图像正在 docker(这就是安装 docker 套接字的原因)中搜索它可以代理的服务。它还负责对容器的依赖关系
  • 来自 docker 主机:curl -H 'Host: node.app1.com' localhost 应该也可以。但如果我们必须通过http://node.app1.com 访问,则需要设置DNS。如果您的 DNS 设置为将 foo.bar.com 转发到运行 nginx-proxy 的主机,则请求将被路由到设置了 VIRTUAL_HOST env var 的容器。 - https://github.com/jwilder/nginx-proxy
  • 当我在相应域的 dns 主机文件中添加条目而不对 compose 文件进行任何更改时,它正在工作,但不应该这样做。
  • @JamesYang 在进入 DNS 主机文件之前我尝试过:从 docker host: curl -H 'Host: node.app1.com' localhost 这工作正常但是,如果我不做任何输入在hosts文件中,如果我从浏览器中点击node.app1.com,请求不会进入nginx-proxy,但如果我尝试点击请求,它会进入nginx-proxy。
  • 在浏览器中使用 node.app1.com 我可以看到错误的服务器 DNS 地址找不到。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 1970-01-01
  • 1970-01-01
  • 2021-01-30
  • 2021-03-05
  • 1970-01-01
  • 2018-01-07
相关资源
最近更新 更多