javascript - 使用 Nodejs + docker 来自 nginx 反向代理的 504 响应

标签 javascript node.js docker nginx docker-compose

更新

我发现,如果我使用 docker exec -it backend_gateway_1 nginx -s reload 重新启动容器上的 nginx,它就会起作用。我从this question找到了一些信息。似乎连接到 127.0.0.1 而不是 localhost 可以工作,但是我使用的是 docker 网络,所以我不确定我的情况会怎样。

原始问题

我正在尝试使用 nginx 作为 docker 的反向代理。我无法完全弄清楚出了什么问题,因为有时它会起作用,但如果我使用 docker-compose down && docker-compose up 重新启动它,我通常会收到此 504 错误

我感觉这与 nginx 或 docker 配置有关。我可以向/发出请求,但对/user 的任何请求都会导致间歇性问题。

当我没有收到 504 时, Node 应用程序运行良好并创建/返回用户。我还可以使用 mongo-express 很好地连接到数据库,这样应该有助于缩小范围。

docker-compose.yml

version: '3.5'
services:
  gateway:
    image: nginx:latest
    restart: always
    ports:
      - 8080:80
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/nginx-error.log:/var/log/nginx/error.log
    networks:
      - poker_network
  poker_mongo:
    image: mongo:latest
    container_name: poker_mongo
    restart: unless-stopped
    volumes:
      - db-data:/data/db
    expose: 
      - "27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: test
      MONGO_INITDB_ROOT_PASSWORD: 123
    networks:
      - poker_network
    depends_on:
      - gateway
  poker_user:
    container_name: poker_user
    build: ./user/
    image: poker/user:latest
    volumes:
      - ./user/:/usr/src/app
      #- /usr/src/app/node_modules
    expose:
      - "8080"
    depends_on:
      - gateway
      - poker_mongo
    networks:
      - poker_network
    environment:
      WAIT_HOSTS: poker_mongo:27017
  mongo-express:
    container_name: mongo-express
    image: mongo-express
    restart: always
    ports:
      - 8085:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: test
      ME_CONFIG_MONGODB_ADMINPASSWORD: 123
      ME_CONFIG_MONGODB_SERVER: poker_mongo
    depends_on:
     - gateway
     - poker_mongo
    networks:
      - poker_network

networks:
  poker_network:
volumes: 
  db-data:

nginx.conf

events { worker_connections 1024; }

http {

    server {
        listen 80;
        location /user {
            rewrite /user/(.*) /$1  break;
            proxy_pass http://poker_user:8080/;
            proxy_set_header X-Real-IP  $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header Host $host;
        }
        location / {
            return 200 'hello';
        }

    }
}

感谢任何帮助,谢谢。

最佳答案

我发现了几个类似的相关问题,并将尝试从中编译出两个可能的解决方案:

第一个解决方案

第一个解决方案是反转服务之间的依赖关系:您可以将 gateway 依赖于用户,而不是 poker_user 依赖于 gateway。这样,当 gateway 启动时,就能够解析 poker_user 主机名。

在这种情况下,Dockerfile 将如下所示:

version: '3.5'
services:
  gateway:
    image: nginx:latest
    restart: always
    ports:
      - 8080:80
    depends_on: poker_user
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/nginx-error.log:/var/log/nginx/error.log
    networks:
      - poker_network
  poker_mongo:
    image: mongo:latest
    container_name: poker_mongo
    restart: unless-stopped
    volumes:
      - db-data:/data/db
    expose: 
      - "27017"
    environment:
      MONGO_INITDB_ROOT_USERNAME: test
      MONGO_INITDB_ROOT_PASSWORD: 123
    networks:
      - poker_network
  poker_user:
    container_name: poker_user
    build: ./user/
    image: poker/user:latest
    volumes:
      - ./user/:/usr/src/app
      #- /usr/src/app/node_modules
    expose:
      - "8080"
    depends_on:
      - poker_mongo
    networks:
      - poker_network
    environment:
      WAIT_HOSTS: poker_mongo:27017
  mongo-express:
    container_name: mongo-express
    image: mongo-express
    restart: always
    ports:
      - 8085:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: test
      ME_CONFIG_MONGODB_ADMINPASSWORD: 123
      ME_CONFIG_MONGODB_SERVER: poker_mongo
    depends_on:
     - gateway
    networks:
      - poker_network

networks:
  poker_network:
volumes: 
  db-data:

我还删除了一些其他依赖项,因为我认为它们是多余的。

第二种解决方案

此解决方案基于更改 nginx 配置。看起来 nginx 尝试解析预先在 proxy_pass 中指定的主机名,并且由于当 nginx 启动时它还不可用,它将继续响应 504 因为它不会再次尝试解析它。

似乎有一种解决方法,可以在 proxy_pass 指令中使用变量,这些变量的处理方式不同,并强制 nginx 再次执行 DNS 解析。这需要在 nginxluckily there's one 中配置解析器使用用户定义的网络时内置于 Docker 中。

这是一个 nginx 配置示例(尽管我自己还没有测试过):

events { worker_connections 1024; }

http {

    server {
        listen 80;
        location /user {
            # Docker DNS server in user-defined networks
            # https://docs.docker.com/v17.09/engine/userguide/networking/configure-dns/
            resolver 127.0.0.11 ipv6=off;

            rewrite /user/(.*) /$1  break;

            # Using a variable will force nginx to re-resolve DNS name
            # https://serverfault.com/a/593003
            set $backend "http://poker_user:8080/";
            proxy_pass $backend;

            proxy_set_header X-Real-IP  $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_set_header Host $host;
        }
        location / {
            return 200 'hello';
        }

    }
}

希望这有帮助!

关于javascript - 使用 Nodejs + docker 来自 nginx 反向代理的 504 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55315958/

相关文章:

javascript indexOf 不适用于列表数据

javascript - 为什么我没有获得 SonarQube 的覆盖范围?

javascript - 通俗地理解异步代码

javascript - request.ref 不是函数

amazon-web-services - EC2 的 AWS 免费套餐限制

javascript - jQuery 如何确保多个选择框中至少有一个选择框具有值

javascript - 有没有办法在 Vuejs 中将 'watch' 用于本地存储?

node.js - 如何使用puppeteer异步从多个html文件生成pdf?

tomcat - Docker:Dockerize Tomcat 应用程序 - 最佳实践

powershell - 如何使用 docker run 命令执行 ps1 脚本?