You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确配置Docker+Nginx运行Node+Mongo?本地部署问题求助

Troubleshooting Your Node+Mongo+Docker+Nginx Setup

Let's walk through each of your issues and fix them one by one. I've worked through similar Docker/Nginx/Node setups many times, so here's what's going wrong and how to resolve it:


1. Node Container Can't Connect to MongoDB

Root Causes

  • Your Node app is trying to connect to 127.0.0.1:27017—inside a Docker container, 127.0.0.1 refers to the container itself, not the Mongo container or your host machine.
  • depends_on only ensures the Mongo container starts before your Node container, but it doesn't wait for the Mongo service to actually be ready to accept connections.
  • You tried container names/IPs, but likely didn't update your connection string correctly in .env.

Fixes

  1. Update your .env Mongo connection string:
    Use the Docker Compose service name (mongodb) as the host—Compose automatically creates a network where service names resolve to container IPs:
    MONGO_URI=mongodb://mongodb:27017/wetaxitask
    
  2. Add health checks to Mongo to ensure Node only starts once Mongo is ready:
    Update your docker-compose.yml Mongo service:
    mongodb:
      container_name: wetaxitask_mongodb
      image: mongo:latest
      restart: always
      ports:
        - 27017:27017
      volumes:
        - ./data:/data/db
      environment:
        - MONGO_INITDB_DATABASE=wetaxitask
      healthcheck:
        test: ["CMD", "mongo", "--eval", "db.adminCommand('ping')"]
        interval: 5s
        timeout: 5s
        retries: 5
    
  3. Make Node wait for Mongo's health check:
    Update your Node service in docker-compose.yml:
    wetaxitask:
      container_name: wetaxitask_api_dev
      image: wetaxitask
      restart: always
      build: .
      depends_on:
        mongodb:
          condition: service_healthy
        redis:
          condition: service_started
      env_file: .env
      ports:
        - 8080:80
      links:
        - redis
        - mongodb
    
  4. Add reconnection logic to your Node code:
    If using Mongoose, enable auto-reconnect:
    mongoose.connect(process.env.MONGO_URI, {
      autoReconnect: true,
      reconnectTries: Number.MAX_VALUE,
      reconnectInterval: 1000
    });
    

Root Cause

Your Dockerfile mixes build and production environments poorly:

  • You install Python in the builder stage, but then copy the entire project to the Nginx-based production container. If your npm start triggers any build steps (like compiling native modules), the production container may have an incomplete Python environment.
  • Running both Node and Nginx in the same container violates Docker's "one process per container" best practice, leading to process management issues.

Fix

Rewrite your Dockerfile to separate build and production, and use a process manager to run both services:

# Builder Stage - handles dependencies and TypeScript compilation
FROM node:12.18-alpine AS base-builder
RUN apk update && apk add --no-cache python3 make g++ libc6-compat
WORKDIR /usr/src/app
COPY tsconfig.json package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build # Adjust to your actual build script (e.g., tsc)

# Production Stage - runs Node + Nginx via supervisord
FROM nginx:1.19.0-alpine
RUN apk add --no-cache nodejs npm supervisor
WORKDIR /usr/src/app

# Copy only necessary files from builder
COPY --from=base-builder /usr/src/app/dist ./dist
COPY --from=base-builder /usr/src/app/node_modules ./node_modules
COPY --from=base-builder /usr/src/app/package*.json ./
COPY --from=base-builder /usr/src/app/.env ./

# Replace default Nginx config
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf

# Add supervisord config to manage both processes
COPY supervisord.conf /etc/supervisord.conf

EXPOSE 80 3000
CMD ["supervisord", "-c", "/etc/supervisord.conf"]

Create a supervisord.conf file in your project root:

[supervisord]
nodaemon=true

[program:node]
command=npm start
directory=/usr/src/app
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:nginx]
command=nginx -g "daemon off;"
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

3. Nginx Returns Welcome Page for All Endpoints

Root Cause

Your Nginx config only proxies requests to /welcome to your Node service—all other requests fall back to Nginx's default static files directory (/usr/share/nginx/html), which serves the welcome page.

Fix

Adjust your Nginx config based on your project type:

If you have a frontend SPA + API:

server {
    listen 80;
    root /usr/src/app/dist/client; # Path to your built frontend files
    index index.html index.htm;

    # Proxy API requests to Node
    location /api/ {
        proxy_pass http://127.0.0.1:3000/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Handle SPA routing (redirects all non-static requests to index.html)
    location / {
        try_files $uri $uri/ /index.html;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

If this is a pure API service:

server {
    listen 80;

    # Proxy all requests to Node
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

Bonus: Better Architecture (Separate Containers)

For long-term maintainability, split Node and Nginx into separate containers. Update your docker-compose.yml:

version: '3.8'
services:
  wetaxitask_api:
    container_name: wetaxitask_api_dev
    build: ./api # Move Node project to an /api subdirectory with its own Dockerfile
    restart: always
    depends_on:
      mongodb:
        condition: service_healthy
      redis:
        condition: service_started
    env_file: .env
    networks:
      - app-network
  mongodb:
    container_name: wetaxitask_mongodb
    image: mongo:latest
    restart: always
    ports:
      - 27017:27017
    volumes:
      - ./data:/data/db
    environment:
      - MONGO_INITDB_DATABASE=wetaxitask
    healthcheck:
      test: ["CMD", "mongo", "--eval", "db.adminCommand('ping')"]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - app-network
  redis:
    container_name: wetaxitask_redis
    image: redis:latest
    ports:
      - 6379:6379
    networks:
      - app-network
  nginx:
    container_name: wetaxitask_nginx
    image: nginx:1.19.0-alpine
    restart: always
    ports:
      - 8080:80
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
      - ./client/dist:/usr/share/nginx/html # Frontend static files
    depends_on:
      - wetaxitask_api
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

Then update Nginx's proxy pass to use the Node service name:

proxy_pass http://wetaxitask_api:3000/api/;

内容的提问来源于stack exchange,提问作者Jakub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 14:42:59