首页 > 解决方案 > 如何为本地开发设置 docker 和 nginx

问题描述

语境

我正在尝试建立一个本地开发环境,但我正在努力让它发挥作用。我希望 docker 和 docker compose 将 nginx 作为反向代理和 postgresql 数据库运行

项目结构

my-app/
├─ server/ (fastify node server)
├─ client/ (sveltekit dev server)
├─ nginx/
│  ├─ Dockerfile
│  ├─ default.conf
├─ docker-compose.yml

我希望唯一的先决条件是 Node、git 和 docker。我能够克隆项目,启动 docker compose,然后分别启动两个项目

先前的研究

我已经阅读了 nginx 初学者指南和几篇 nginx 文档,但我发现他们的文档相当难以接近。我还找到了一些指南,它们让我的客户端和服务器在 docker 容器中运行,并在 docker compose 中设置为单独的服务。这不是最终目标,但不幸的是我也没有让那些工作。

这个问题似乎很接近,我发现它很有帮助。但它仍然无法正常工作。

首先,我只是想让一切都在 http://localhost:4000 上运行,以消除一些复杂性

这是我迄今为止最好的尝试:


    ##########################
    # docker-compose.yml
    ##########################
    
    version: '3.9'
    services:
      reverse-proxy:
        build: ./nginx
        ports:
          - 8080:8080
    
    ##########################
    # nginx/Dockerfile
    ##########################
    FROM nginx:1.21.3
    COPY ./default.conf /etc/nginx/conf.d/default.conf/
    
    ##########################
    # nginx/default.conf
    ##########################
    
    server {
      listen 8080;
    
      location / {
        proxy_pass http://host.docker.internal:8080;
      }
    
      location /api/ {
        proxy_pass http://host.docker.internal:3000;
      }
    }

有了这个设置,我可以点击 http://localhost:3000/api/ 并从服务器获取我的 json 响应,但是当我尝试点击 http://localhost:8080/api/ 时,我得到标准的 nginx 502响应和 nginx 没有成功到达我的节点服务器。nginx 日志给了我这个错误:

     2021/11/16 12:38:39 [error] 34#34: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.1, server: , request: "GET /api/ HTTP/1.1", upstream: "http://192.168.65.2:3000/api/", host: "localhost:8080"

我不知道上面的 IP 地址是从哪里来的,但是如果我在本地点击http://192.168.65.2:3000/api/,那么浏览器就会不停地旋转。

最终目标

目前,我正在寻找一个正确配置docker-compose.yml且相对简单的 nginx 文件,该文件被映射到默认值。HTTPS 和自定义 URL 确实是后来的问题。现在,我只想能够在 docker 容器中访问我的 nginx 反向代理,并正确路由到我的两个本地运行的节点服务器(一个是 API 服务器,一个是 sveltekit 开发服务器 - 不在 docker 容器内)。

预先感谢您的任何帮助!

编辑(Robert-Jan Kuyper 建议的更改后)

我现在基本上是这样运行的:

##########################
# docker-compose.yml
##########################

version: '3.8'
services:
  nginx:
    image: nginx:1.19.4
    depends_on:
      - api
    volumes:
      - ./nginx/default.local.conf:/etc/nginx/conf.d/default.conf
    ports:
      - '8080:8080'
  api:
    build: ./api
    hostname: api
    command: node src/app.js
    volumes:
      - ./server/src:/app/src


##########################
# nginx/default.conf
##########################

upstream api_server {
    server api:3000;
}

server {
  listen 8080;

  location /api/ {
    proxy_pass http://api_server;
  }
}

##########################
# api/Dockerfile
##########################

FROM node:16.9.0

# docker workdir
WORKDIR /home/usr/app

# copy files
COPY . .

# build the app
RUN npm ci

# expose at port 3000
EXPOSE 3000


CMD ["node", "src/app.js"]

不幸的是,它仍然失败:

[error] 29#29: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: , request: "GET /api/ HTTP/1.1", upstream: "http://172.18.0.2:3000/api/", host: "localhost:8080"

标签: dockernginxdocker-compose

解决方案


您必须记住以下几点:

  1. Docker compose 默认使用服务名作为容器间网络的主机名
  2. Nginx 需要先了解上游
  3. 您不需要在 Dockerfile 中使用 Nginx,而是直接使用它docker-compose.yml。并将您的配置文件安装到容器中。
  4. 您需要将前端和后端 dockerize 以将它们连接到 nginx
  5. 始终在您的 docker 容器中0.0.0.0而不是127.0.0.1或内部公开,请参阅此答案localhost

我使用 nginx、docker 和 docker-compose 的示例仓库:https ://gitlab.com/datails/api 。

示例default.conf

upstream api_server {
    server api:3000;
}

upstream frontend {
    server frontend:3000;
}

server {
    listen 80;

    location /api {
        proxy_pass http://api_server;
    }

    location / {           
        proxy_pass http://frontend/;
    }
}

例子docker-compose.yml

version: '3.8'
services:
  nginx:
    image: nginx:1.19.4
    depends_on:
      - server
      - frontend
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    ports:
      - '8080:80'

然后确保你的前端 dockerized 并frontend在你的 docker-compose 中作为服务调用,例如:

version: '3.8'
services:    
  nginx:
    image: nginx:1.19.4
    depends_on:
      - server
      - frontend
    volumes:
      - ./default.conf:/etc/nginx/conf.d/default.conf
    ports:
      - '8080:80'

  frontend:
    build: ./frontend
    command: npm run start
    volumes:
      - ./frontend/src:/home/usr/app/src

  api:
    build: ./api
    command: npm run start
    volumes:
      - ./api/src:/home/usr/app/src

请注意,您不需要端口,因为您使用容器间通信。


推荐阅读