无法从另一个 docker 容器连接到 dockerized Express.js 应用程序

Pav*_*l K 6 express docker

我有两个容器应用程序和网络服务器。Web服务器是普通的nginx:alpine图像,应用程序是在ubuntu:focal下的端口3030上运行的expressjs应用程序。我听说这是为应用程序和服务器使用单独的容器的常见做法。所以我添加proxy_pass http://app:3030/;到 nginx 配置中。出了点问题,我对此进行了深入研究。为了排除不正确的 nginx 设置,我检查了从网络服务器到应用程序容器的原始卷曲请求,但没有成功。这是我的 docker-compose:

version: '3.5'
services:

  webserver:
    image: nginx:alpine
    env_file: .env
    restart: always
    tty: true
    ports:
      - ${NGINX_HOST_HTTP_PORT}:80
      - ${NGINX_HOST_HTTPS_PORT}:443
    volumes:
      - ${APP_CODE_PATH_HOST}:${APP_DIR}
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/sites/:/etc/nginx/conf.d/
      - ./nginx/ssl/:/etc/ssl/
    depends_on:
      - app
    container_name: ${CONTAINER_NAME_PREFIX}-webserver
    networks:
      - app-network

  app:
    env_file: .env
    restart: on-failure
    tty: true
    build:
      dockerfile: ./docker/app/Dockerfile
      args:
        APP_ENV: ${APP_ENV}
        APP_DIR: ${APP_DIR}
        PRODUCT_ID: ${PRODUCT_ID}
      context: ../
    environment:
      - DEBIAN_FRONTEND=noninteractive
    container_name: ${CONTAINER_NAME_PREFIX}-app
    networks:
      - app-network

networks:
  app-network:
    driver: bridge
Run Code Online (Sandbox Code Playgroud)

我可以从应用程序容器 CLI 请求 Express:

/ # curl -X GET http://127.0.0.1:3030/multichannel/4034?uid=a6O5iTje8sR2PESbWpAM
{"status": "OK"}
Run Code Online (Sandbox Code Playgroud)

现在从网络服务器:

/ # ping app
PING app (172.19.0.2): 56 data bytes
64 bytes from 172.19.0.2: seq=0 ttl=64 time=0.090 ms
/ # curl -X GET http://172.19.0.2:3030/multichannel/4034?uid=a6O5iTje8sR2PESbWpAM
curl: (7) Failed to connect to 172.19.0.2 port 3030 after 0 ms: Connection refused
/ # curl -X GET http://app:3030/multichannel/4034?uid=a6O5iTje8sR2PESbWpAM
curl: (7) Failed to connect to app port 3030 after 0 ms: Connection refused
Run Code Online (Sandbox Code Playgroud)

Nginx 日志(不要关注 IP,它是正确的,容器重建后它发生了变化):

2021/10/29 15:40:46 [error] 24#24: *12 connect() failed (111: Connection refused) while connecting to upstream, client: 172.20.0.1, server: api.test, request: "GET /multichannel/4034?uid=a6O5iTje8sR2PESbWpAM HTTP/1.1", upstream: "http://172.20.0.3:3030/multichannel/4034?uid=a6O5iTje8sR2PESbWpAM", host: "api.test"
Run Code Online (Sandbox Code Playgroud)

当然Nginx的conf有:

    location / {
        proxy_pass http://app:3030;
    }
Run Code Online (Sandbox Code Playgroud)

为什么连接被拒绝?两个容器都在同一个网络中

Pav*_*l K 2

终于找到无法连接的原因了。当 @devatherock 提到时,ARTIFACTORY_URL=http://localhost:8081我检查了使用的主机上的应用程序代码,发现了这一点:

server.listen(3030, "127.0.0.1", () => {
  logger.debug(`Server is running on ${serverConfig.port} port`);
});
Run Code Online (Sandbox Code Playgroud)

然后我尝试“localhost”作为主机,但仍然得到 502。所以是时候阅读文档了。Expressjs 的server.listen工作方式类似于 Nodejs server.listen https://nodejs.org/api/net.html#serverlistenport-host-backlog-callback

如果省略 host,则当 IPv6 可用时,服务器将接受未指定的 IPv6 地址 (::) 上的连接,否则接受未指定的 IPv4 地址 (0.0.0.0) 上的连接。在大多数操作系统中,侦听未指定的 IPv6 地址 (::) 可能会导致 net.Server 也侦听未指定的 IPv4 地址 (0.0.0.0)。

答案是使用“0.0.0.0”或省略主机参数。127.0.0.1 或 localhost 只能在本地计算机上访问,因为它绑定到环回接口。