带有 Nodejs 应用程序(NestJS)的 Docker 容器无法从其他容器或主机访问

Vla*_*kov 3 networking nginx node.js docker nestjs

我有一个应用程序,由几个 docker 容器组成:nginx、客户端、管理、后端和 mongo。

在容器“后端”中,NestJS 应用程序在端口 5000 上运行。容器已公开端口 5000。但容器未响应任何请求,容器内的应用程序也不会接收这些请求。我什至尝试将端口 5000 暴露给我的本地计算机,这样我就可以在 docker-host 之外发出请求,但这样容器也不会响应。当我在我的机器上本地运行这个 NestJS 应用程序时,一切都运行良好。我有 nginx.conf 来配置 nginx 容器的行为。它应该使用代理将某些请求重定向到特定容器。这种方法适用于客户端和管理容器。两者都托管 NextJS 应用程序并侦听特定端口。我对“后端”容器使用了相同的方法,但即使 nginx 似乎发出了正确的请求,它也没有收到响应,或者由于某种原因它向 docker-host 内部的错误地址发出了请求

我的自定义镜像的 Dockerfile:

FROM node:14.15.4 as client
WORKDIR /usr/src/app
COPY /src/client/package*.json ./
RUN npm install
COPY /src/client .
EXPOSE 3000
CMD ["npm", "run", "dev"]

FROM node:14.15.4 as admin
WORKDIR /usr/src/app
COPY /src/admin/package*.json ./
RUN npm install
COPY /src/admin .
EXPOSE 3001
CMD ["npm", "run", "dev"]

FROM node:14.15.4 as backend
WORKDIR /usr/src/app
COPY /src/app/package*.json ./
RUN npm install
COPY /src/app .
EXPOSE 5000
CMD ["npm", "run", "start:dev"]
Run Code Online (Sandbox Code Playgroud)

docker-compose.yml:

version: '3'
services:
  nginx:
    image: nginx:${NGNIX_VERSION}
    depends_on:
      - client
      - admin
    links:
      - client:client
      - admin:admin
      - backend:backend
    restart: on-failure:30
    volumes:
      - ./deploy/shared/config/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
    env_file:
      - .env
    networks:
      - default
    expose:
      - 80
    ports:
      - ${NGINX_BIND_PORT}:80
  mongo:
    image: mongo:${MONGO_VERSION}
    env_file:
      - .env
    networks:
      - default
    environment:
      MONGO_INITDB_ROOT_USERNAME: ${MONGO_USERNAME}
      MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
  client:
    build:
      context: .
      target: client
    networks:
      - default
    volumes:
    - ./src/client:/usr/src/app
  admin:
    build:
      context: .
      target: admin
    networks:
      - default
    volumes:
    - ./src/admin:/usr/src/app
  backend:
    build:
      context: .
      target: backend
    networks:
      - default
    volumes:
    - ./src/app:/usr/src/app
    ports:
    - 5000:5000

networks:
  default:
    driver: bridge
Run Code Online (Sandbox Code Playgroud)

nginx.conf:

upstream docker-client {
    server client:3000;
}

upstream docker-admin {
    server admin:3001;
}

upstream docker-backend {
    server backend:5000;
}

server {
    listen 80;
    server_name mr0bread.local;

    location / {
        proxy_pass http://docker-client;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
        proxy_read_timeout 600s;
    }

    location /admin {
        proxy_pass http://docker-admin;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
        proxy_read_timeout 600s;
    }

    location /backend {
            proxy_pass http://docker-backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect off;
            proxy_read_timeout 600s;
        }
}
Run Code Online (Sandbox Code Playgroud)

这是存储库的链接:GitHub

Ple*_*mor 10

使用 Fastify,对我有用的是:

app.listen(3000, "0.0.0.0")
Run Code Online (Sandbox Code Playgroud)


And*_*gle 8

为了避免答案在评论中丢失:Docker 网络和链接的设置看起来是正确的,所以这似乎是过程本身的问题。

在 Nest.js 进程启动时,绑定到与localhost或不同的接口非常重要127.0.0.1,因为 Docker 创建虚拟网络接口并使用这些接口与进程进行通信。因此,即使localhost直接在主机上运行时有效,这也不适用于 Docker 网络。该端口只能从容器内部访问。

所以,而不是

app.listen("localhost:3000");
Run Code Online (Sandbox Code Playgroud)

像这样绑定到所有接口(当然使用相应的端口号):

app.listen("0.0.0.0:3000");
Run Code Online (Sandbox Code Playgroud)