当通过Docker-compose运行时,Nginx无法找到上游节点应用程序

Mik*_*gin 2 nginx node.js docker docker-compose

我有一个超级简单的Node应用程序和一个Nginx配置,它充当Node应用程序的反向代理.如果我在本地运行Nginx(通过自制程序)和Node应用程序,一切正常.如果我在端口8080访问由Nginx配置定义的服务器,我将从节点应用程序获得输出,该应用程序在端口3000上运行.

我一直在尝试将这个简单的设置转换为使用Docker,并编写了以下Docker-compose文件:

version: '3.0'
services:
  web:
    build: .
    ports:
      - 3000:3000
  nginx:
    build:
      context: .
      dockerfile: Dockerfile.nginx
    ports:
      - 8080:8080
Run Code Online (Sandbox Code Playgroud)

在运行时docker-compose up,会构建映像,并且控制台中没有错误消息.在访问时localhost:3000我从Node应用程序获得响应,但在访问时localhost:8080我得到一个Nginx 502错误页面,并在终端中出现以下错误:

连接到上游时连接失败(111:连接被拒绝),客户端:172.18.0.1,服务器:localhost,请求:"GET/HTTP/1.1",上游:" http://127.0.0.1:3000/ ",主持人:"localhost:8080"

我的节点应用程序的Dockerfile如下所示:

FROM node:carbon

WORKDIR /app

ADD . /app

RUN npm install

CMD ["node", "."]

EXPOSE 3000
Run Code Online (Sandbox Code Playgroud)

而Dockerfile.nginx看起来像这样:

FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
Run Code Online (Sandbox Code Playgroud)

并且nginx.conf看起来像这样:

events {
  worker_connections  1024;
}

http {

  upstream node_app {
    server 127.0.0.1:3000;
  }

  server_tokens off;

  # Define the MIME types for files.
  include       mime.types;
  default_type  application/octet-stream;

  # Speed up file transfers by using sendfile()
  # TODO: Read up on this
  sendfile on;

  server {
    listen 8080;
    server_name localhost;

    location / {
      proxy_pass http://node_app;
      proxy_http_version 1.1;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在启动Docker时,我可以看到Nginx正在端口8080上运行(因为我看到了502 Nginx页面),我可以看到节点应用正在运行(因为我可以在localhost:3000访问它).我无法理解为什么我从nginx获得502.

我尝试过使用各种不同的东西,比如使用links链接容器,depends_on但似乎没有任何区别.我也在使用docker-compose up --build以确保每次进行更改时都不会缓存以前的版本.

编辑:似乎使它工作的东西是在docker-compose中添加一个container_name属性:

  web:
    container_name: nodeapp
    build:
      context: .
      dockerfile: Dockerfile.node
    ports:
      - 3000:3000
Run Code Online (Sandbox Code Playgroud)

然后在nginx.conf中的上游node_app配置中使用该容器名称:

  upstream node_app {
    server nodeapp:3000;
  }
Run Code Online (Sandbox Code Playgroud)

这对我没用?!

yei*_*iel 6

问题是在您的Nginx配置中,您将Web服务的IP引用为127.0.0.1,这是运行docker容器的主机的环回地址.这可能会取决于您的设置(操作系统,防火墙)或可能不会.

正确的方法是使nginx服务依赖于webdocker-compose.yml文件中的服务,并更新Nginx配置以通过name(web)而不是IP地址引用Web服务.在这里您可以找到有关docker compose的更多信息,具体取决于能力.

更新的docker-compose.yml文件将是:

version: '3.0'
services:
  web:
    build: .
  nginx:
    build:
      context: .
      dockerfile: Dockerfile.nginx
    ports:
      - 8080:8080
    depends_on:
      - web
Run Code Online (Sandbox Code Playgroud)

请注意,我已停止公开web服务的端口.您可能需要保留它来监视Web服务,但该nginx服务不需要它.

通过对docker-compose.yml文件的更新,Nginx配置将如下所示:

events {
  worker_connections  1024;
}

http {

  upstream node_app {
    server web:3000;
  }

  server_tokens off;

  # Define the MIME types for files.
  include       mime.types;
  default_type  application/octet-stream;

  # Speed up file transfers by using sendfile()
  # TODO: Read up on this
  sendfile on;

  server {
    listen 8080;
    server_name localhost;

    location / {
      proxy_pass http://node_app;
      proxy_http_version 1.1;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)