如何在Docker、NextJS和Nginx中在隔离网络中创建正确的端点

huangapple go评论58阅读模式
英文:

How to create correct endpoints within an isolated network in Docker, NextJS and Nginx

问题

Nginx配置:

worker_processes 1;

events {
  worker_connections 1024;
}

http {
  sendfile on;

  upstream api {
    server nextjs-app:3000;
  }

  server {
    listen 80 default_server;

    location / {
      proxy_pass http://api;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
    }
  }
}

docker-compose:

version: '3.8'

services:

  nginx:
    image: nginx:latest
    restart: always
    depends_on:
      - rust-server
      - nextjs-app
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - "80:80"
    networks:
      - app_network

  nextjs-app:
    build:
      context: ./client
      dockerfile: Dockerfile
    container_name: nextjs-app
    environment:
      - CHOKIDAR_USEPOLLING=true
      - DB_USER=${DB_USER}
      - DB_PASS=${DB_PASS}
    expose:
      - "3000"
    networks:
      - app_network

  rust-server:
    build:
      context: ./userserver
      dockerfile: Dockerfile
    container_name: rustserver-dc
    expose:
      - "10000"
    networks:
      - app_network
    volumes:
      - './userserver:/usr/src/userserver'
      - '/usr/src/userserver/target'
    environment:
      - MY_LOG_LEVEL=info
      - MY_LOG_STYLE=Always
      - DATABASE_URL=${DATABASE_URL}
      - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
      - STRIPE_PUBLISH_KEY=${STRIPE_PUBLISH_KEY}
      - ACCESS_TOKEN_SECRET=${ACCESS_TOKEN_SECRET}
      - REFRESH_TOKEN_SECRET=${REFRESH_TOKEN_SECRET}
      - RESET_PASSWORD_SECRET=${RESET_PASSWORD_SECRET}
      - REDIS_URL=${REDIS_URL}

  surrealdb:
    image: surrealdb/surrealdb
    environment:
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}
    expose:
      - "8000"
    networks:
      - app_network
    volumes:
      - data:/var/lib/surrealdb/data
    command: "start --user ${DB_USER} --pass {DB_PASSWORD} --log full file://var/lib/surreal/data"

networks:
  app_network:
    driver: bridge

volumes:
  data:

Next.js首页页面:

import Head from 'next/head';
import axios from 'axios';
import { useState, useEffect } from 'react';

export default function Home() {
  const [data, setData] = useState(null);
  useEffect(() => {
    axios.get('http://rustserver-dc:10000')
      .then(res => {
        setData(res.data);
      })
      .catch(err => {
        console.log(err);
      })
  }, []);

  console.log(data);
  return (
    <>
      <Head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
        <div>Welcome to the app</div>
      </main>
    </>
  )
}

控制台中出现的错误:

Failed to load resource: net::ERR_NAME_NOT_RESOLVED rustserver-dc:10000/:1

以上为您提供的翻译内容,不包括代码部分。

英文:

I have a Docker network that is an isolated network and reverse proxy that serves the NextJS app to the localhost. Unfortunately, fetch to the backend gets failed whenever I open the browser. However, curl http://rustserver-dc:10000/ responds with the data. I do not want the DB and backend to get exposed, only is available from NextJS app when browsing.

Nginx conf:

worker_processes 1;

events {
  worker_connections 1024;
}

http {
  sendfile on;

  upstream api {
    server nextjs-app:3000;
  }

  server {
    listen 80 default_server;

    location / {
      proxy_pass http://api;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
    }
  }
}

docker-compose:

version: &#39;3.8&#39;

services:

  nginx:
    image: nginx:latest
    restart: always
    depends_on:
      - rust-server
      - nextjs-app
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - &quot;80:80&quot;
    networks:
      - app_network
 

  nextjs-app:
    build: 
      context: ./client
      dockerfile: Dockerfile
    container_name: nextjs-app
    environment:
      - CHOKIDAR_USEPOLLING=true
      - DB_USER=${DB_USER}
      - DB_PASS=${DB_PASS}
    expose:
      - &quot;3000&quot;
    networks:
      - app_network

  rust-server:
    build:
      context: ./userserver
      dockerfile: Dockerfile
    container_name: rustserver-dc
    expose:
      - &quot;10000&quot;
    networks:
      - app_network
    volumes:
      - &#39;./userserver:/usr/src/userserver&#39;
      - &#39;/usr/src/userserver/target&#39;
    environment:
      - MY_LOG_LEVEL=info
      - MY_LOG_STYLE=Always
      - DATABASE_URL=${DATABASE_URL}
      - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
      - STRIPE_PUBLISH_KEY=${STRIPE_PUBLISH_KEY}
      - ACCESS_TOKEN_SECRET=${ACCESS_TOKEN_SECRET}
      - REFRESH_TOKEN_SECRET=${REFRESH_TOKEN_SECRET}
      - RESET_PASSWORD_SECRET=${RESET_PASSWORD_SECRET}
      - REDIS_URL=${REDIS_URL}

  surrealdb:
    image: surrealdb/surrealdb
    environment:
      - DB_USER=${DB_USER}
      - DB_PASSWORD=${DB_PASSWORD}
    expose:
      - &quot;8000&quot;
    networks:
      - app_network
    volumes:
      - data:/var/lib/surrealdb/data
    command: &quot;start --user ${DB_USER} --pass {DB_PASSWORD} --log full 
file://var/lib/surreal/data&quot;

networks:
  app_network:
    driver: bridge
    

volumes:
  data:

Next js index page:

import Head from &#39;next/head&#39;
import axios from &#39;axios&#39;;
import { useState, useEffect } from &#39;react&#39;;

export default function Home() {
  const [data, setData] = useState(null);
  useEffect(() =&gt; {
    axios.get(&#39;http://rustserver-dc:10000&#39;)
      .then(res =&gt; {
        setData(res.data);
      })
      .catch(err =&gt; {
        console.log(err);
      })
  }, []);

  console.log(data);
  return (
    &lt;&gt;
      &lt;Head&gt;
        &lt;title&gt;Create Next App&lt;/title&gt;
        &lt;meta name=&quot;description&quot; content=&quot;Generated by create next app&quot; /&gt;
        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
        &lt;link rel=&quot;icon&quot; href=&quot;/favicon.ico&quot; /&gt;
      &lt;/Head&gt;
      &lt;main&gt;
        &lt;div&gt;Welcome to the app&lt;/div&gt;
      &lt;/main&gt;
    &lt;/&gt;
  )
}

Error occurring in console:

Failed to load resource: net::ERR_NAME_NOT_RESOLVED rustserver-dc:10000/:1

Had the same issue when I was trying to connect two nodes in Kubernetes, and exposing only NextJS app via Nginx reverse proxy

答案1

得分: 1

如果您希望在 Docker 网络上获取数据并将其发送给客户端,您可以使用 getServerSideProps 来在页面请求时获取数据,或者使用 getStaticProps 在构建时检索数据。

export async function getServerSideProps(context) {
  const res = await axios.get('http://rustserver-dc:10000')
  return {
    props: res.data, // 作为 props 传递给页面组件
  }
}

如果您需要客户端在这些时间之外请求 rustserver-dc,您可以添加一个 API 路由 到 Next.js,以将请求代理到 rustserver-dc 服务。

英文:

If you want next to fetch the data on the docker network and send it to the client you could use getServerSideProps to fetch the data when the page is requested, or getStaticProps to retrieve the data build time.

export async function getServerSideProps(context) {
  const res = await axios.get(&#39;http://rustserver-dc:10000&#39;)
  return {
    props: res.data, // will be passed to the page component as props
  }
}

If you need the client to make requests for rustserver-dc outside of those times, you could add an API route to next that proxies the request onto the rustserver-dc service.

huangapple
  • 本文由 发表于 2023年2月19日 23:14:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75501119.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定